// Copyright (C) 2018-2024, Tellusim Technologies Inc. All rights reserved
// https://tellusim.com/

#include "../include/TellusimJNIMath.h"
#include "../include/TellusimJNIAPI.h"

/*
 */
namespace Tellusim {
	
	// Tellusim::String
	static jlong string_new(TS_JNI_ARGS) {
		return newString();
	}
	static jlong string_new_1(TS_JNI_ARGS, jint size, jbyte c) {
		return newString((uint32_t)size, c);
	}
	static jlong string_new_2(TS_JNI_ARGS, jstring str, jint length) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		jlong ret_ = newString(str_, (uint32_t)length);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jlong string_new_3(TS_JNI_ARGS, jcharArray str, jint length) {
		return newString((wchar_t*)CharArray(env, str).get(), (uint32_t)length);
	}
	static jlong string_new_4(TS_JNI_ARGS, jintArray str, jint length) {
		return newString((uint32_t*)IntArray(env, str).get(), (uint32_t)length);
	}
	static void string_delete(TS_JNI_ARGS, jlong self) {
		delete (String*)self;
	}
	static void string_reserve(TS_JNI_ARGS, jlong self, jint size, jboolean discard) {
		toString(self).reserve((uint32_t)size, (bool)discard);
	}
	static void string_resize(TS_JNI_ARGS, jlong self, jint size, jbyte c, jboolean reserve) {
		toString(self).resize((uint32_t)size, c, (bool)reserve);
	}
	static void string_release(TS_JNI_ARGS, jlong self) {
		toString(self).release();
	}
	static void string_clear(TS_JNI_ARGS, jlong self) {
		toString(self).clear();
	}
	static void string_copy(TS_JNI_ARGS, jlong self, jstring str, jint length) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		toString(self).copy(str_, (uint32_t)length);
		env->ReleaseStringUTFChars(str, str_);
	}
	static void string_copy_1(TS_JNI_ARGS, jlong self, jcharArray str, jint length) {
		toString(self).copy((wchar_t*)CharArray(env, str).get(), (uint32_t)length);
	}
	static void string_copy_2(TS_JNI_ARGS, jlong self, jintArray str, jint length) {
		toString(self).copy((uint32_t*)IntArray(env, str).get(), (uint32_t)length);
	}
	static void string_copy_3(TS_JNI_ARGS, jlong self, jlong string, jint length) {
		toString(self).copy(toString(string), (uint32_t)length);
	}
	static void string_append(TS_JNI_ARGS, jlong self, jbyte c) {
		toString(self).append(c);
	}
	static void string_append_1(TS_JNI_ARGS, jlong self, jstring str, jint length) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		toString(self).append(str_, (uint32_t)length);
		env->ReleaseStringUTFChars(str, str_);
	}
	static void string_append_2(TS_JNI_ARGS, jlong self, jlong string, jint length) {
		toString(self).append(toString(string), (uint32_t)length);
	}
	static void string_insert(TS_JNI_ARGS, jlong self, jint pos, jstring str, jint length) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		toString(self).insert((uint32_t)pos, str_, (uint32_t)length);
		env->ReleaseStringUTFChars(str, str_);
	}
	static void string_insert_1(TS_JNI_ARGS, jlong self, jint pos, jlong string, jint length) {
		toString(self).insert((uint32_t)pos, toString(string), (uint32_t)length);
	}
	static void string_remove_back(TS_JNI_ARGS, jlong self, jint length) {
		toString(self).removeBack((uint32_t)length);
	}
	static void string_remove(TS_JNI_ARGS, jlong self, jint pos, jint length) {
		toString(self).remove((uint32_t)pos, (uint32_t)length);
	}
	static void string_reverse(TS_JNI_ARGS, jlong self, jint pos, jint length) {
		toString(self).reverse((uint32_t)pos, (uint32_t)length);
	}
	static jint string_size(TS_JNI_ARGS, jlong self) {
		return toString(self).size();
	}
	static jboolean string_empty(TS_JNI_ARGS, jlong self) {
		return toString(self).empty();
	}
	static jint string_find(TS_JNI_ARGS, jlong self, jbyte c, jint pos) {
		return toString(self).find(c, (uint32_t)pos);
	}
	static jint string_rfind(TS_JNI_ARGS, jlong self, jbyte c, jint pos) {
		return toString(self).rfind(c, (uint32_t)pos);
	}
	static jint string_count(TS_JNI_ARGS, jlong self, jbyte c, jint pos) {
		return toString(self).count(c, (uint32_t)pos);
	}
	static jint string_find_1(TS_JNI_ARGS, jlong self, jstring str, jint pos) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint32_t ret_ = toString(self).find(str_, (uint32_t)pos);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jint string_rfind_1(TS_JNI_ARGS, jlong self, jstring str, jint pos) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint32_t ret_ = toString(self).rfind(str_, (uint32_t)pos);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jint string_count_1(TS_JNI_ARGS, jlong self, jstring str, jint pos) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint32_t ret_ = toString(self).count(str_, (uint32_t)pos);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jboolean string_begins(TS_JNI_ARGS, jlong self, jstring str, jint length, jint pos) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		bool ret_ = toString(self).begins(str_, (uint32_t)length, (uint32_t)pos);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jboolean string_contains(TS_JNI_ARGS, jlong self, jstring str, jint length, jint pos) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		bool ret_ = toString(self).contains(str_, (uint32_t)length, (uint32_t)pos);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jboolean string_match(TS_JNI_ARGS, jlong self, jstring str, jint length, jint pos) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		bool ret_ = toString(self).match(str_, (uint32_t)length, (uint32_t)pos);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jint string_compare(TS_JNI_ARGS, jlong self, jstring str, jint pos) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		int32_t ret_ = toString(self).compare(str_, (uint32_t)pos);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jint string_distance(TS_JNI_ARGS, jlong self, jstring str, jboolean scan, jint pos) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint32_t ret_ = toString(self).distance(str_, (bool)scan, (uint32_t)pos);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jstring string_begin(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toString(self).begin());
	}
	static jstring string_end(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toString(self).end());
	}
	static jbyte string_front(TS_JNI_ARGS, jlong self, jint index) {
		return toString(self).front((uint32_t)index);
	}
	static jbyte string_back(TS_JNI_ARGS, jlong self, jint index) {
		return toString(self).back((uint32_t)index);
	}
	static jbyte string_front_1(TS_JNI_ARGS, jlong self, jint index) {
		return toString(self).front((uint32_t)index);
	}
	static jbyte string_back_1(TS_JNI_ARGS, jlong self, jint index) {
		return toString(self).back((uint32_t)index);
	}
	static jstring string_substring(TS_JNI_ARGS, jlong self, jint pos, jint length) {
		return env->NewStringUTF(toString(self).substring((uint32_t)pos, (uint32_t)length).get());
	}
	static jstring string_replace(TS_JNI_ARGS, jlong self, jbyte before, jbyte after, jint pos) {
		return env->NewStringUTF(toString(self).replace(before, after, (uint32_t)pos).get());
	}
	static jstring string_replace_1(TS_JNI_ARGS, jlong self, jstring before, jstring after, jint pos) {
		const char *before_ = (before) ? env->GetStringUTFChars(before, nullptr) : nullptr;
		const char *after_ = (after) ? env->GetStringUTFChars(after, nullptr) : nullptr;
		String ret_ = toString(self).replace(before_, after_, (uint32_t)pos);
		env->ReleaseStringUTFChars(before, before_);
		env->ReleaseStringUTFChars(after, after_);
		return env->NewStringUTF(ret_.get());
	}
	static jstring string_extension(TS_JNI_ARGS, jlong self, jstring extension) {
		const char *extension_ = (extension) ? env->GetStringUTFChars(extension, nullptr) : nullptr;
		String ret_ = toString(self).extension(extension_);
		env->ReleaseStringUTFChars(extension, extension_);
		return env->NewStringUTF(ret_.get());
	}
	static jstring string_extension_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toString(self).extension().get());
	}
	static jstring string_pathname(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toString(self).pathname().get());
	}
	static jstring string_basename(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toString(self).basename().get());
	}
	static jstring string_dirname(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toString(self).dirname().get());
	}
	static jstring string_relname(TS_JNI_ARGS, jstring path, jstring str) {
		const char *path_ = (path) ? env->GetStringUTFChars(path, nullptr) : nullptr;
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		String ret_ = String::relname(path_, str_);
		env->ReleaseStringUTFChars(path, path_);
		env->ReleaseStringUTFChars(str, str_);
		return env->NewStringUTF(ret_.get());
	}
	static jstring string_relname_1(TS_JNI_ARGS, jlong path, jlong str) {
		return env->NewStringUTF(String::relname(toString(path), toString(str)).get());
	}
	static jstring string_capitalize(TS_JNI_ARGS, jlong self, jstring delimiters, jstring spaces) {
		const char *delimiters_ = (delimiters) ? env->GetStringUTFChars(delimiters, nullptr) : nullptr;
		const char *spaces_ = (spaces) ? env->GetStringUTFChars(spaces, nullptr) : nullptr;
		String ret_ = toString(self).capitalize(delimiters_, spaces_);
		env->ReleaseStringUTFChars(delimiters, delimiters_);
		env->ReleaseStringUTFChars(spaces, spaces_);
		return env->NewStringUTF(ret_.get());
	}
	static jstring string_lower(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toString(self).lower().get());
	}
	static jstring string_upper(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toString(self).upper().get());
	}
	static jint string_to_utf32(TS_JNI_ARGS, jstring str, jintArray code) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint32_t *code_ = (uint32_t*)env->GetIntArrayElements(code, nullptr);
		uint32_t ret_ = String::toUtf32(str_, code_[0]);
		env->ReleaseStringUTFChars(str, str_);
		env->ReleaseIntArrayElements(code, (jint*)code_, 0);
		return ret_;
	}
	static jint string_to_utf16(TS_JNI_ARGS, jlong self, jcharArray d, jint length) {
		return toString(self).toUtf16((wchar_t*)CharArray(env, d).get(), (uint32_t)length);
	}
	static jint string_to_utf32_1(TS_JNI_ARGS, jlong self, jintArray d, jint length) {
		return toString(self).toUtf32((uint32_t*)IntArray(env, d).get(), (uint32_t)length);
	}
	static jint string_from_utf32(TS_JNI_ARGS, jlong d, jint code) {
		return String::fromUtf32(toString(d), (uint32_t)code);
	}
	static jstring string_from_utf16(TS_JNI_ARGS, jcharArray str, jint length) {
		return env->NewStringUTF(String::fromUtf16((wchar_t*)CharArray(env, str).get(), (uint32_t)length).get());
	}
	static jstring string_from_utf32_1(TS_JNI_ARGS, jintArray str, jint length) {
		return env->NewStringUTF(String::fromUtf32((uint32_t*)IntArray(env, str).get(), (uint32_t)length).get());
	}
	static jstring string_from_url(TS_JNI_ARGS, jstring str, jint length) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		String ret_ = String::fromUrl(str_, (uint32_t)length);
		env->ReleaseStringUTFChars(str, str_);
		return env->NewStringUTF(ret_.get());
	}
	static jstring string_from_url_1(TS_JNI_ARGS, jlong string, jint length) {
		return env->NewStringUTF(String::fromUrl(toString(string), (uint32_t)length).get());
	}
	static jstring string_fromi32(TS_JNI_ARGS, jlong d, jint value, jint radix) {
		return env->NewStringUTF(String::fromi32(toString(d), value, (uint32_t)radix).get());
	}
	static jstring string_fromi64(TS_JNI_ARGS, jlong d, jlong value, jint radix) {
		return env->NewStringUTF(String::fromi64(toString(d), (int64_t)value, (uint32_t)radix).get());
	}
	static jstring string_fromu32(TS_JNI_ARGS, jlong d, jint value, jint radix) {
		return env->NewStringUTF(String::fromu32(toString(d), (uint32_t)value, (uint32_t)radix).get());
	}
	static jstring string_fromu64(TS_JNI_ARGS, jlong d, jlong value, jint radix) {
		return env->NewStringUTF(String::fromu64(toString(d), (uint64_t)value, (uint32_t)radix).get());
	}
	static jstring string_fromf32(TS_JNI_ARGS, jlong d, jfloat value, jint digits, jboolean compact, jboolean exponent) {
		return env->NewStringUTF(String::fromf32(toString(d), value, (uint32_t)digits, (bool)compact, (bool)exponent).get());
	}
	static jstring string_fromf64(TS_JNI_ARGS, jlong d, jdouble value, jint digits, jboolean compact, jboolean exponent) {
		return env->NewStringUTF(String::fromf64(toString(d), value, (uint32_t)digits, (bool)compact, (bool)exponent).get());
	}
	static jstring string_fromi32_1(TS_JNI_ARGS, jint value, jint radix) {
		return env->NewStringUTF(String::fromi32(value, (uint32_t)radix).get());
	}
	static jstring string_fromi64_1(TS_JNI_ARGS, jlong value, jint radix) {
		return env->NewStringUTF(String::fromi64((int64_t)value, (uint32_t)radix).get());
	}
	static jstring string_fromu32_1(TS_JNI_ARGS, jint value, jint radix) {
		return env->NewStringUTF(String::fromu32((uint32_t)value, (uint32_t)radix).get());
	}
	static jstring string_fromu64_1(TS_JNI_ARGS, jlong value, jint radix) {
		return env->NewStringUTF(String::fromu64((uint64_t)value, (uint32_t)radix).get());
	}
	static jstring string_fromf32_1(TS_JNI_ARGS, jfloat value, jint digits, jboolean compact, jboolean exponent) {
		return env->NewStringUTF(String::fromf32(value, (uint32_t)digits, (bool)compact, (bool)exponent).get());
	}
	static jstring string_fromf64_1(TS_JNI_ARGS, jdouble value, jint digits, jboolean compact, jboolean exponent) {
		return env->NewStringUTF(String::fromf64(value, (uint32_t)digits, (bool)compact, (bool)exponent).get());
	}
	static jint string_toi32(TS_JNI_ARGS, jstring str, jint radix, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		int32_t ret_ = String::toi32(str_, (uint32_t)radix, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jlong string_toi64(TS_JNI_ARGS, jstring str, jint radix, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		int64_t ret_ = String::toi64(str_, (uint32_t)radix, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return (jlong)ret_;
	}
	static jint string_tou32(TS_JNI_ARGS, jstring str, jint radix, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint32_t ret_ = String::tou32(str_, (uint32_t)radix, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jlong string_tou64(TS_JNI_ARGS, jstring str, jint radix, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint64_t ret_ = String::tou64(str_, (uint32_t)radix, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return (jlong)ret_;
	}
	static jint string_toi32_1(TS_JNI_ARGS, jstring str, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		int32_t ret_ = String::toi32(str_, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jlong string_toi64_1(TS_JNI_ARGS, jstring str, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		int64_t ret_ = String::toi64(str_, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return (jlong)ret_;
	}
	static jint string_tou32_1(TS_JNI_ARGS, jstring str, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint32_t ret_ = String::tou32(str_, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jlong string_tou64_1(TS_JNI_ARGS, jstring str, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint64_t ret_ = String::tou64(str_, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return (jlong)ret_;
	}
	static jfloat string_tof32(TS_JNI_ARGS, jstring str, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		float32_t ret_ = String::tof32(str_, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jdouble string_tof64(TS_JNI_ARGS, jstring str, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		float64_t ret_ = String::tof64(str_, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jint string_toi32_2(TS_JNI_ARGS, jlong self, jint radix, jint pos) {
		return toString(self).toi32((uint32_t)radix, (uint32_t)pos);
	}
	static jlong string_toi64_2(TS_JNI_ARGS, jlong self, jint radix, jint pos) {
		return (jlong)toString(self).toi64((uint32_t)radix, (uint32_t)pos);
	}
	static jint string_tou32_2(TS_JNI_ARGS, jlong self, jint radix, jint pos) {
		return toString(self).tou32((uint32_t)radix, (uint32_t)pos);
	}
	static jlong string_tou64_2(TS_JNI_ARGS, jlong self, jint radix, jint pos) {
		return (jlong)toString(self).tou64((uint32_t)radix, (uint32_t)pos);
	}
	static jfloat string_tof32_1(TS_JNI_ARGS, jlong self, jint pos) {
		return toString(self).tof32((uint32_t)pos);
	}
	static jdouble string_tof64_1(TS_JNI_ARGS, jlong self, jint pos) {
		return toString(self).tof64((uint32_t)pos);
	}
	static jint string_to_hashu32(TS_JNI_ARGS, jlong self, jint pos) {
		return toString(self).toHashu32((uint32_t)pos);
	}
	static jlong string_to_hashu64(TS_JNI_ARGS, jlong self, jint pos) {
		return (jlong)toString(self).toHashu64((uint32_t)pos);
	}
	static jint string_to_rgb_au8(TS_JNI_ARGS, jlong self, jint pos) {
		return toString(self).toRGBAu8((uint32_t)pos);
	}
	static jstring string_from_time(TS_JNI_ARGS, jlong usec, jint digits) {
		return env->NewStringUTF(String::fromTime((uint64_t)usec, (uint32_t)digits).get());
	}
	static jstring string_from_bytes(TS_JNI_ARGS, jlong bytes, jint digits) {
		return env->NewStringUTF(String::fromBytes((uint64_t)bytes, (uint32_t)digits).get());
	}
	static jstring string_from_number(TS_JNI_ARGS, jlong value, jint digits) {
		return env->NewStringUTF(String::fromNumber((uint64_t)value, (uint32_t)digits).get());
	}
	static jstring string_from_frequency(TS_JNI_ARGS, jlong hz, jint digits) {
		return env->NewStringUTF(String::fromFrequency((uint64_t)hz, (uint32_t)digits).get());
	}
	static jstring string_from_length(TS_JNI_ARGS, jdouble distance, jint digits) {
		return env->NewStringUTF(String::fromLength(distance, (uint32_t)digits).get());
	}
	static jstring string_from_angle(TS_JNI_ARGS, jdouble angle, jint digits) {
		return env->NewStringUTF(String::fromAngle(angle, (uint32_t)digits).get());
	}
	static jlong string_to_bytes(TS_JNI_ARGS, jstring str, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint64_t ret_ = String::toBytes(str_, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return (jlong)ret_;
	}
	static jlong string_to_number(TS_JNI_ARGS, jstring str, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint64_t ret_ = String::toNumber(str_, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return (jlong)ret_;
	}
	static jlong string_to_frequency(TS_JNI_ARGS, jstring str, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		uint64_t ret_ = String::toFrequency(str_, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return (jlong)ret_;
	}
	static jdouble string_to_length(TS_JNI_ARGS, jstring str, jintArray size) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		float64_t ret_ = String::toLength(str_, (uint32_t*)IntArray(env, size).get());
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jlong string_to_bytes_1(TS_JNI_ARGS, jlong self, jint pos, jintArray size) {
		return (jlong)toString(self).toBytes((uint32_t)pos, (uint32_t*)IntArray(env, size).get());
	}
	static jlong string_to_number_1(TS_JNI_ARGS, jlong self, jint pos, jintArray size) {
		return (jlong)toString(self).toNumber((uint32_t)pos, (uint32_t*)IntArray(env, size).get());
	}
	static jlong string_to_frequency_1(TS_JNI_ARGS, jlong self, jint pos, jintArray size) {
		return (jlong)toString(self).toFrequency((uint32_t)pos, (uint32_t*)IntArray(env, size).get());
	}
	static jdouble string_to_length_1(TS_JNI_ARGS, jlong self, jint pos, jintArray size) {
		return toString(self).toLength((uint32_t)pos, (uint32_t*)IntArray(env, size).get());
	}
	static const JNINativeMethod string_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)string_new },
		{ (char*)"new_1", (char*)"(IB)J", (void*)string_new_1 },
		{ (char*)"new_2", (char*)"(Ljava/lang/String;I)J", (void*)string_new_2 },
		{ (char*)"new_3", (char*)"([CI)J", (void*)string_new_3 },
		{ (char*)"new_4", (char*)"([II)J", (void*)string_new_4 },
		{ (char*)"delete_", (char*)"(J)V", (void*)string_delete },
		{ (char*)"reserve_", (char*)"(JIZ)V", (void*)string_reserve },
		{ (char*)"resize_", (char*)"(JIBZ)V", (void*)string_resize },
		{ (char*)"release_", (char*)"(J)V", (void*)string_release },
		{ (char*)"clear_", (char*)"(J)V", (void*)string_clear },
		{ (char*)"copy_", (char*)"(JLjava/lang/String;I)V", (void*)string_copy },
		{ (char*)"copy_1", (char*)"(J[CI)V", (void*)string_copy_1 },
		{ (char*)"copy_2", (char*)"(J[II)V", (void*)string_copy_2 },
		{ (char*)"copy_3", (char*)"(JJI)V", (void*)string_copy_3 },
		{ (char*)"append_", (char*)"(JB)V", (void*)string_append },
		{ (char*)"append_1", (char*)"(JLjava/lang/String;I)V", (void*)string_append_1 },
		{ (char*)"append_2", (char*)"(JJI)V", (void*)string_append_2 },
		{ (char*)"insert_", (char*)"(JILjava/lang/String;I)V", (void*)string_insert },
		{ (char*)"insert_1", (char*)"(JIJI)V", (void*)string_insert_1 },
		{ (char*)"remove_back", (char*)"(JI)V", (void*)string_remove_back },
		{ (char*)"remove_", (char*)"(JII)V", (void*)string_remove },
		{ (char*)"reverse_", (char*)"(JII)V", (void*)string_reverse },
		{ (char*)"size_", (char*)"(J)I", (void*)string_size },
		{ (char*)"empty_", (char*)"(J)Z", (void*)string_empty },
		{ (char*)"find_", (char*)"(JBI)I", (void*)string_find },
		{ (char*)"rfind_", (char*)"(JBI)I", (void*)string_rfind },
		{ (char*)"count_", (char*)"(JBI)I", (void*)string_count },
		{ (char*)"find_1", (char*)"(JLjava/lang/String;I)I", (void*)string_find_1 },
		{ (char*)"rfind_1", (char*)"(JLjava/lang/String;I)I", (void*)string_rfind_1 },
		{ (char*)"count_1", (char*)"(JLjava/lang/String;I)I", (void*)string_count_1 },
		{ (char*)"begins_", (char*)"(JLjava/lang/String;II)Z", (void*)string_begins },
		{ (char*)"contains_", (char*)"(JLjava/lang/String;II)Z", (void*)string_contains },
		{ (char*)"match_", (char*)"(JLjava/lang/String;II)Z", (void*)string_match },
		{ (char*)"compare_", (char*)"(JLjava/lang/String;I)I", (void*)string_compare },
		{ (char*)"distance_", (char*)"(JLjava/lang/String;ZI)I", (void*)string_distance },
		{ (char*)"begin_", (char*)"(J)Ljava/lang/String;", (void*)string_begin },
		{ (char*)"end_", (char*)"(J)Ljava/lang/String;", (void*)string_end },
		{ (char*)"front_", (char*)"(JI)B", (void*)string_front },
		{ (char*)"back_", (char*)"(JI)B", (void*)string_back },
		{ (char*)"front_1", (char*)"(JI)B", (void*)string_front_1 },
		{ (char*)"back_1", (char*)"(JI)B", (void*)string_back_1 },
		{ (char*)"substring_", (char*)"(JII)Ljava/lang/String;", (void*)string_substring },
		{ (char*)"replace_", (char*)"(JBBI)Ljava/lang/String;", (void*)string_replace },
		{ (char*)"replace_1", (char*)"(JLjava/lang/String;Ljava/lang/String;I)Ljava/lang/String;", (void*)string_replace_1 },
		{ (char*)"extension_", (char*)"(JLjava/lang/String;)Ljava/lang/String;", (void*)string_extension },
		{ (char*)"extension_1", (char*)"(J)Ljava/lang/String;", (void*)string_extension_1 },
		{ (char*)"pathname_", (char*)"(J)Ljava/lang/String;", (void*)string_pathname },
		{ (char*)"basename_", (char*)"(J)Ljava/lang/String;", (void*)string_basename },
		{ (char*)"dirname_", (char*)"(J)Ljava/lang/String;", (void*)string_dirname },
		{ (char*)"relname_", (char*)"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*)string_relname },
		{ (char*)"relname_1", (char*)"(JJ)Ljava/lang/String;", (void*)string_relname_1 },
		{ (char*)"capitalize_", (char*)"(JLjava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*)string_capitalize },
		{ (char*)"lower_", (char*)"(J)Ljava/lang/String;", (void*)string_lower },
		{ (char*)"upper_", (char*)"(J)Ljava/lang/String;", (void*)string_upper },
		{ (char*)"to_utf32", (char*)"(Ljava/lang/String;[I)I", (void*)string_to_utf32 },
		{ (char*)"to_utf16", (char*)"(J[CI)I", (void*)string_to_utf16 },
		{ (char*)"to_utf32_1", (char*)"(J[II)I", (void*)string_to_utf32_1 },
		{ (char*)"from_utf32", (char*)"(JI)I", (void*)string_from_utf32 },
		{ (char*)"from_utf16", (char*)"([CI)Ljava/lang/String;", (void*)string_from_utf16 },
		{ (char*)"from_utf32_1", (char*)"([II)Ljava/lang/String;", (void*)string_from_utf32_1 },
		{ (char*)"from_url", (char*)"(Ljava/lang/String;I)Ljava/lang/String;", (void*)string_from_url },
		{ (char*)"from_url_1", (char*)"(JI)Ljava/lang/String;", (void*)string_from_url_1 },
		{ (char*)"fromi32_", (char*)"(JII)Ljava/lang/String;", (void*)string_fromi32 },
		{ (char*)"fromi64_", (char*)"(JJI)Ljava/lang/String;", (void*)string_fromi64 },
		{ (char*)"fromu32_", (char*)"(JII)Ljava/lang/String;", (void*)string_fromu32 },
		{ (char*)"fromu64_", (char*)"(JJI)Ljava/lang/String;", (void*)string_fromu64 },
		{ (char*)"fromf32_", (char*)"(JFIZZ)Ljava/lang/String;", (void*)string_fromf32 },
		{ (char*)"fromf64_", (char*)"(JDIZZ)Ljava/lang/String;", (void*)string_fromf64 },
		{ (char*)"fromi32_1", (char*)"(II)Ljava/lang/String;", (void*)string_fromi32_1 },
		{ (char*)"fromi64_1", (char*)"(JI)Ljava/lang/String;", (void*)string_fromi64_1 },
		{ (char*)"fromu32_1", (char*)"(II)Ljava/lang/String;", (void*)string_fromu32_1 },
		{ (char*)"fromu64_1", (char*)"(JI)Ljava/lang/String;", (void*)string_fromu64_1 },
		{ (char*)"fromf32_1", (char*)"(FIZZ)Ljava/lang/String;", (void*)string_fromf32_1 },
		{ (char*)"fromf64_1", (char*)"(DIZZ)Ljava/lang/String;", (void*)string_fromf64_1 },
		{ (char*)"toi32_", (char*)"(Ljava/lang/String;I[I)I", (void*)string_toi32 },
		{ (char*)"toi64_", (char*)"(Ljava/lang/String;I[I)J", (void*)string_toi64 },
		{ (char*)"tou32_", (char*)"(Ljava/lang/String;I[I)I", (void*)string_tou32 },
		{ (char*)"tou64_", (char*)"(Ljava/lang/String;I[I)J", (void*)string_tou64 },
		{ (char*)"toi32_1", (char*)"(Ljava/lang/String;[I)I", (void*)string_toi32_1 },
		{ (char*)"toi64_1", (char*)"(Ljava/lang/String;[I)J", (void*)string_toi64_1 },
		{ (char*)"tou32_1", (char*)"(Ljava/lang/String;[I)I", (void*)string_tou32_1 },
		{ (char*)"tou64_1", (char*)"(Ljava/lang/String;[I)J", (void*)string_tou64_1 },
		{ (char*)"tof32_", (char*)"(Ljava/lang/String;[I)F", (void*)string_tof32 },
		{ (char*)"tof64_", (char*)"(Ljava/lang/String;[I)D", (void*)string_tof64 },
		{ (char*)"toi32_2", (char*)"(JII)I", (void*)string_toi32_2 },
		{ (char*)"toi64_2", (char*)"(JII)J", (void*)string_toi64_2 },
		{ (char*)"tou32_2", (char*)"(JII)I", (void*)string_tou32_2 },
		{ (char*)"tou64_2", (char*)"(JII)J", (void*)string_tou64_2 },
		{ (char*)"tof32_1", (char*)"(JI)F", (void*)string_tof32_1 },
		{ (char*)"tof64_1", (char*)"(JI)D", (void*)string_tof64_1 },
		{ (char*)"to_hashu32", (char*)"(JI)I", (void*)string_to_hashu32 },
		{ (char*)"to_hashu64", (char*)"(JI)J", (void*)string_to_hashu64 },
		{ (char*)"to_rgb_au8", (char*)"(JI)I", (void*)string_to_rgb_au8 },
		{ (char*)"from_time", (char*)"(JI)Ljava/lang/String;", (void*)string_from_time },
		{ (char*)"from_bytes", (char*)"(JI)Ljava/lang/String;", (void*)string_from_bytes },
		{ (char*)"from_number", (char*)"(JI)Ljava/lang/String;", (void*)string_from_number },
		{ (char*)"from_frequency", (char*)"(JI)Ljava/lang/String;", (void*)string_from_frequency },
		{ (char*)"from_length", (char*)"(DI)Ljava/lang/String;", (void*)string_from_length },
		{ (char*)"from_angle", (char*)"(DI)Ljava/lang/String;", (void*)string_from_angle },
		{ (char*)"to_bytes", (char*)"(Ljava/lang/String;[I)J", (void*)string_to_bytes },
		{ (char*)"to_number", (char*)"(Ljava/lang/String;[I)J", (void*)string_to_number },
		{ (char*)"to_frequency", (char*)"(Ljava/lang/String;[I)J", (void*)string_to_frequency },
		{ (char*)"to_length", (char*)"(Ljava/lang/String;[I)D", (void*)string_to_length },
		{ (char*)"to_bytes_1", (char*)"(JI[I)J", (void*)string_to_bytes_1 },
		{ (char*)"to_number_1", (char*)"(JI[I)J", (void*)string_to_number_1 },
		{ (char*)"to_frequency_1", (char*)"(JI[I)J", (void*)string_to_frequency_1 },
		{ (char*)"to_length_1", (char*)"(JI[I)D", (void*)string_to_length_1 },
	};
	
	// Tellusim::App
	static jlong app_new(TS_JNI_ARGS, jstringArray argv) {
		Array<char*> argv_((argv) ? (uint32_t)env->GetArrayLength(argv) : 0);
		for(uint32_t i = 0; i < argv_.size(); i++) argv_[i] = (char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(argv, i), nullptr);
		jlong ret_ = newApp(argv_.size(), argv_.get());
		for(uint32_t i = 0; i < argv_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(argv, i), argv_[i]);
		return ret_;
	}
	static void app_delete(TS_JNI_ARGS, jlong self) {
		delete (App*)self;
	}
	static void app_clear(TS_JNI_ARGS, jlong self) {
		toApp(self).clear();
	}
	static jint app_get_platform(TS_JNI_ARGS, jlong self) {
		return toApp(self).getPlatform();
	}
	static jint app_get_device(TS_JNI_ARGS, jlong self) {
		return toApp(self).getDevice();
	}
	static jint app_get_width(TS_JNI_ARGS, jlong self) {
		return toApp(self).getWidth();
	}
	static jint app_get_height(TS_JNI_ARGS, jlong self) {
		return toApp(self).getHeight();
	}
	static jint app_get_multisample(TS_JNI_ARGS, jlong self) {
		return toApp(self).getMultisample();
	}
	static jint app_get_num_arguments(TS_JNI_ARGS, jlong self) {
		return toApp(self).getNumArguments();
	}
	static jstring app_get_argument(TS_JNI_ARGS, jlong self, jint num) {
		return env->NewStringUTF(toApp(self).getArgument((uint32_t)num).get());
	}
	static jboolean app_is_argument(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toApp(self).isArgument(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jstring app_get_argument_1(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const String ret_ = toApp(self).getArgument(name_);
		env->ReleaseStringUTFChars(name, name_);
		return env->NewStringUTF(ret_.get());
	}
	static jboolean app_create(TS_JNI_ARGS, jlong self, jint platform, jint version) {
		return toApp(self).create((Platform)platform, (uint32_t)version);
	}
	static void app_set_platform(TS_JNI_ARGS, jint platform, jint device) {
		App::setPlatform((Platform)platform, (uint32_t)device);
	}
	static void app_set_size(TS_JNI_ARGS, jint width, jint height, jint multisample) {
		App::setSize((uint32_t)width, (uint32_t)height, (uint32_t)multisample);
	}
	static jboolean app_is_build_debug(TS_JNI_ARGS) {
		return App::isBuildDebug();
	}
	static jboolean app_is_build_float64(TS_JNI_ARGS) {
		return App::isBuildFloat64();
	}
	static jstring app_get_build_date(TS_JNI_ARGS) {
		return env->NewStringUTF(App::getBuildDate().get());
	}
	static jstring app_get_build_info(TS_JNI_ARGS) {
		return env->NewStringUTF(App::getBuildInfo().get());
	}
	static jint app_get_version(TS_JNI_ARGS) {
		return App::getVersion();
	}
	static jlong app_get_api_hash(TS_JNI_ARGS) {
		return (jlong)App::getAPIHash();
	}
	static const JNINativeMethod app_methods[] = {
		{ (char*)"new_", (char*)"([Ljava/lang/String;)J", (void*)app_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)app_delete },
		{ (char*)"clear_", (char*)"(J)V", (void*)app_clear },
		{ (char*)"get_platform", (char*)"(J)I", (void*)app_get_platform },
		{ (char*)"get_device", (char*)"(J)I", (void*)app_get_device },
		{ (char*)"get_width", (char*)"(J)I", (void*)app_get_width },
		{ (char*)"get_height", (char*)"(J)I", (void*)app_get_height },
		{ (char*)"get_multisample", (char*)"(J)I", (void*)app_get_multisample },
		{ (char*)"get_num_arguments", (char*)"(J)I", (void*)app_get_num_arguments },
		{ (char*)"get_argument", (char*)"(JI)Ljava/lang/String;", (void*)app_get_argument },
		{ (char*)"is_argument", (char*)"(JLjava/lang/String;)Z", (void*)app_is_argument },
		{ (char*)"get_argument_1", (char*)"(JLjava/lang/String;)Ljava/lang/String;", (void*)app_get_argument_1 },
		{ (char*)"create_", (char*)"(JII)Z", (void*)app_create },
		{ (char*)"set_platform", (char*)"(II)V", (void*)app_set_platform },
		{ (char*)"set_size", (char*)"(III)V", (void*)app_set_size },
		{ (char*)"is_build_debug", (char*)"()Z", (void*)app_is_build_debug },
		{ (char*)"is_build_float64", (char*)"()Z", (void*)app_is_build_float64 },
		{ (char*)"get_build_date", (char*)"()Ljava/lang/String;", (void*)app_get_build_date },
		{ (char*)"get_build_info", (char*)"()Ljava/lang/String;", (void*)app_get_build_info },
		{ (char*)"get_version", (char*)"()I", (void*)app_get_version },
		{ (char*)"get_api_hash", (char*)"()J", (void*)app_get_api_hash },
	};
	
	// Tellusim::Async
	static jlong async_new(TS_JNI_ARGS) {
		return newAsync();
	}
	static void async_delete(TS_JNI_ARGS, jlong self) {
		delete (Async*)self;
	}
	static jboolean async_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toAsync(self) == toAsync(ptr));
	}
	static jlong async_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newAsync(toAsync(self).clonePtr());
	}
	static void async_clear_ptr(TS_JNI_ARGS, jlong self) {
		toAsync(self).clearPtr();
	}
	static void async_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toAsync(self).destroyPtr();
	}
	static void async_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toAsync(self).acquirePtr();
	}
	static void async_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toAsync(self).unacquirePtr();
	}
	static jboolean async_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toAsync(self).isValidPtr();
	}
	static jboolean async_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toAsync(self).isOwnerPtr();
	}
	static jboolean async_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toAsync(self).isConstPtr();
	}
	static jint async_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toAsync(self).getCountPtr();
	}
	static jlong async_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toAsync(self).getInternalPtr();
	}
	static jboolean async_init(TS_JNI_ARGS, jlong self, jint num) {
		return toAsync(self).init((uint32_t)num);
	}
	static jboolean async_shutdown(TS_JNI_ARGS, jlong self) {
		return toAsync(self).shutdown();
	}
	static jboolean async_is_initialized(TS_JNI_ARGS, jlong self) {
		return toAsync(self).isInitialized();
	}
	static jint async_get_num_cores(TS_JNI_ARGS) {
		return Async::getNumCores();
	}
	static jint async_get_num_threads(TS_JNI_ARGS, jlong self) {
		return toAsync(self).getNumThreads();
	}
	static void async_clear(TS_JNI_ARGS, jlong self) {
		toAsync(self).clear();
	}
	static jint async_get_num_tasks(TS_JNI_ARGS, jlong self, jboolean check) {
		return toAsync(self).getNumTasks((bool)check);
	}
	static jboolean async_check(TS_JNI_ARGS, jlong self) {
		return toAsync(self).check();
	}
	static jboolean async_wait(TS_JNI_ARGS, jlong self) {
		return toAsync(self).wait();
	}
	static const JNINativeMethod async_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)async_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)async_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)async_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)async_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)async_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)async_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)async_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)async_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)async_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)async_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)async_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)async_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)async_get_internal_ptr },
		{ (char*)"init_", (char*)"(JI)Z", (void*)async_init },
		{ (char*)"shutdown_", (char*)"(J)Z", (void*)async_shutdown },
		{ (char*)"is_initialized", (char*)"(J)Z", (void*)async_is_initialized },
		{ (char*)"get_num_cores", (char*)"()I", (void*)async_get_num_cores },
		{ (char*)"get_num_threads", (char*)"(J)I", (void*)async_get_num_threads },
		{ (char*)"clear_", (char*)"(J)V", (void*)async_clear },
		{ (char*)"get_num_tasks", (char*)"(JZ)I", (void*)async_get_num_tasks },
		{ (char*)"check_", (char*)"(J)Z", (void*)async_check },
		{ (char*)"wait_", (char*)"(J)Z", (void*)async_wait },
	};
	
	// Tellusim::Stream
	static jlong stream_new(TS_JNI_ARGS) {
		return newStream();
	}
	static void stream_delete(TS_JNI_ARGS, jlong self) {
		delete (Stream*)self;
	}
	static jboolean stream_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toStream(self) == toStream(ptr));
	}
	static jlong stream_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newStream(toStream(self).clonePtr());
	}
	static void stream_clear_ptr(TS_JNI_ARGS, jlong self) {
		toStream(self).clearPtr();
	}
	static void stream_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toStream(self).destroyPtr();
	}
	static void stream_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toStream(self).acquirePtr();
	}
	static void stream_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toStream(self).unacquirePtr();
	}
	static jboolean stream_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toStream(self).isValidPtr();
	}
	static jboolean stream_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toStream(self).isOwnerPtr();
	}
	static jboolean stream_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toStream(self).isConstPtr();
	}
	static jint stream_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toStream(self).getCountPtr();
	}
	static jlong stream_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toStream(self).getInternalPtr();
	}
	static jlong stream_move(TS_JNI_ARGS, jlong self) {
		return newStream(toStream(self).move());
	}
	static jboolean stream_is_opened(TS_JNI_ARGS, jlong self) {
		return toStream(self).isOpened();
	}
	static jboolean stream_is_mapped(TS_JNI_ARGS, jlong self) {
		return toStream(self).isMapped();
	}
	static jboolean stream_is_available(TS_JNI_ARGS, jlong self) {
		return toStream(self).isAvailable();
	}
	static jlong stream_get_size(TS_JNI_ARGS, jlong self) {
		return (jlong)toStream(self).getSize();
	}
	static jstring stream_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toStream(self).getName().get());
	}
	static jlong stream_tell(TS_JNI_ARGS, jlong self) {
		return (jlong)toStream(self).tell();
	}
	static jboolean stream_seek(TS_JNI_ARGS, jlong self, jlong offset) {
		return toStream(self).seek((size_t)offset);
	}
	static jboolean stream_seek_back(TS_JNI_ARGS, jlong self, jlong offset) {
		return toStream(self).seekBack((size_t)offset);
	}
	static jboolean stream_seek_cur(TS_JNI_ARGS, jlong self, jlong offset) {
		return toStream(self).seekCur((int64_t)offset);
	}
	static jlong stream_get_data(TS_JNI_ARGS, jlong self) {
		return (jlong)toStream(self).getData();
	}
	static jlong stream_read(TS_JNI_ARGS, jlong self, jbyteArray dest) {
		return (jlong)toStream(self).read(ByteArray(env, dest).get(), env->GetArrayLength(dest));
	}
	static jlong stream_write(TS_JNI_ARGS, jlong self, jbyteArray src) {
		return (jlong)toStream(self).write(ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jboolean stream_flush(TS_JNI_ARGS, jlong self) {
		return toStream(self).flush();
	}
	static jboolean stream_puts(TS_JNI_ARGS, jlong self, jstring str) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		bool ret_ = toStream(self).puts(str_);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jboolean stream_puts_1(TS_JNI_ARGS, jlong self, jlong str) {
		return toStream(self).puts(toString(str));
	}
	static jstring stream_gets(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		String ret_ = toStream(self).gets(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return env->NewStringUTF(ret_.get());
	}
	static jbyte stream_readi8(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		int8_t ret_ = toStream(self).readi8(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jboolean stream_writei8(TS_JNI_ARGS, jlong self, jbyte value) {
		return toStream(self).writei8(value);
	}
	static jbyte stream_readu8(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		uint8_t ret_ = toStream(self).readu8(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jboolean stream_writeu8(TS_JNI_ARGS, jlong self, jbyte value) {
		return toStream(self).writeu8((uint8_t)value);
	}
	static jshort stream_readi16(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		int16_t ret_ = toStream(self).readi16(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jboolean stream_writei16(TS_JNI_ARGS, jlong self, jshort value) {
		return toStream(self).writei16(value);
	}
	static jshort stream_readu16(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		uint16_t ret_ = toStream(self).readu16(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jboolean stream_writeu16(TS_JNI_ARGS, jlong self, jshort value) {
		return toStream(self).writeu16((uint16_t)value);
	}
	static jint stream_readi32(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		int32_t ret_ = toStream(self).readi32(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jboolean stream_writei32(TS_JNI_ARGS, jlong self, jint value) {
		return toStream(self).writei32(value);
	}
	static jint stream_readu32(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		uint32_t ret_ = toStream(self).readu32(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jboolean stream_writeu32(TS_JNI_ARGS, jlong self, jint value) {
		return toStream(self).writeu32((uint32_t)value);
	}
	static jlong stream_readi64(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		int64_t ret_ = toStream(self).readi64(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jboolean stream_writei64(TS_JNI_ARGS, jlong self, jlong value) {
		return toStream(self).writei64((int64_t)value);
	}
	static jlong stream_readu64(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		uint64_t ret_ = toStream(self).readu64(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jboolean stream_writeu64(TS_JNI_ARGS, jlong self, jlong value) {
		return toStream(self).writeu64((uint64_t)value);
	}
	static jfloat stream_readf32(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		float32_t ret_ = toStream(self).readf32(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jboolean stream_writef32(TS_JNI_ARGS, jlong self, jfloat value) {
		return toStream(self).writef32(value);
	}
	static jdouble stream_readf64(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		float64_t ret_ = toStream(self).readf64(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jboolean stream_writef64(TS_JNI_ARGS, jlong self, jdouble value) {
		return toStream(self).writef64(value);
	}
	static jint stream_readi32e(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		int32_t ret_ = toStream(self).readi32e(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jboolean stream_writei32e(TS_JNI_ARGS, jlong self, jint value) {
		return toStream(self).writei32e(value);
	}
	static jint stream_readu32e(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		uint32_t ret_ = toStream(self).readu32e(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jboolean stream_writeu32e(TS_JNI_ARGS, jlong self, jint value) {
		return toStream(self).writeu32e((uint32_t)value);
	}
	static jlong stream_readi64e(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		int64_t ret_ = toStream(self).readi64e(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jboolean stream_writei64e(TS_JNI_ARGS, jlong self, jlong value) {
		return toStream(self).writei64e((int64_t)value);
	}
	static jlong stream_readu64e(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		uint64_t ret_ = toStream(self).readu64e(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jboolean stream_writeu64e(TS_JNI_ARGS, jlong self, jlong value) {
		return toStream(self).writeu64e((uint64_t)value);
	}
	static jstring stream_read_string(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		String ret_ = toStream(self).readString(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return env->NewStringUTF(ret_.get());
	}
	static jboolean stream_write_string(TS_JNI_ARGS, jlong self, jlong str) {
		return toStream(self).writeString(toString(str));
	}
	static jboolean stream_write_string_1(TS_JNI_ARGS, jlong self, jstring str) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		bool ret_ = toStream(self).writeString(str_);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jstring stream_read_string_1(TS_JNI_ARGS, jlong self, jbyte term, jbooleanArray status, jint size) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		String ret_ = toStream(self).readString(term, status_, (uint32_t)size);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return env->NewStringUTF(ret_.get());
	}
	static jboolean stream_write_string_2(TS_JNI_ARGS, jlong self, jlong str, jbyte term) {
		return toStream(self).writeString(toString(str), term);
	}
	static jboolean stream_write_string_3(TS_JNI_ARGS, jlong self, jstring str, jbyte term) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		bool ret_ = toStream(self).writeString(str_, term);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jstring stream_read_token(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		String ret_ = toStream(self).readToken(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return env->NewStringUTF(ret_.get());
	}
	static jboolean stream_read_token_1(TS_JNI_ARGS, jlong self, jlong dest, jboolean clear) {
		return toStream(self).readToken(toString(dest), (bool)clear);
	}
	static jstring stream_read_line(TS_JNI_ARGS, jlong self, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		String ret_ = toStream(self).readLine(status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return env->NewStringUTF(ret_.get());
	}
	static jboolean stream_read_line_1(TS_JNI_ARGS, jlong self, jlong dest, jboolean empty, jboolean clear) {
		return toStream(self).readLine(toString(dest), (bool)empty, (bool)clear);
	}
	static jlong stream_read_stream(TS_JNI_ARGS, jlong self, jlong dest, jlong size, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		size_t ret_ = toStream(self).readStream(toStream(dest), (size_t)size, status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jlong stream_write_stream(TS_JNI_ARGS, jlong self, jlong src, jlong size, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		size_t ret_ = toStream(self).writeStream(toStream(src), (size_t)size, status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jlong stream_read_zip(TS_JNI_ARGS, jlong self, jbyteArray dest) {
		return (jlong)toStream(self).readZip(ByteArray(env, dest).get(), env->GetArrayLength(dest));
	}
	static jlong stream_write_zip(TS_JNI_ARGS, jlong self, jbyteArray src, jint level) {
		return (jlong)toStream(self).writeZip(ByteArray(env, src).get(), env->GetArrayLength(src), level);
	}
	static jlong stream_write_zip_fast(TS_JNI_ARGS, jlong self, jbyteArray src) {
		return (jlong)toStream(self).writeZipFast(ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jlong stream_write_zip_best(TS_JNI_ARGS, jlong self, jbyteArray src) {
		return (jlong)toStream(self).writeZipBest(ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jlong stream_read_lz4(TS_JNI_ARGS, jlong self, jbyteArray dest) {
		return (jlong)toStream(self).readLz4(ByteArray(env, dest).get(), env->GetArrayLength(dest));
	}
	static jlong stream_write_lz4(TS_JNI_ARGS, jlong self, jbyteArray src, jint level) {
		return (jlong)toStream(self).writeLz4(ByteArray(env, src).get(), env->GetArrayLength(src), level);
	}
	static jlong stream_write_lz4_fast(TS_JNI_ARGS, jlong self, jbyteArray src) {
		return (jlong)toStream(self).writeLz4Fast(ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jlong stream_write_lz4_best(TS_JNI_ARGS, jlong self, jbyteArray src) {
		return (jlong)toStream(self).writeLz4Best(ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jlong stream_decode_zip(TS_JNI_ARGS, jlong self, jlong src, jlong size, jbooleanArray status, jint window) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		size_t ret_ = toStream(self).decodeZip(toStream(src), (size_t)size, status_, window);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jlong stream_encode_zip(TS_JNI_ARGS, jlong self, jlong dest, jlong size, jbooleanArray status, jint level) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		size_t ret_ = toStream(self).encodeZip(toStream(dest), (size_t)size, status_, level);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jlong stream_encode_zip_fast(TS_JNI_ARGS, jlong self, jlong dest, jlong size, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		size_t ret_ = toStream(self).encodeZipFast(toStream(dest), (size_t)size, status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jlong stream_encode_zip_best(TS_JNI_ARGS, jlong self, jlong dest, jlong size, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		size_t ret_ = toStream(self).encodeZipBest(toStream(dest), (size_t)size, status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jlong stream_decode_lz4(TS_JNI_ARGS, jlong self, jlong src, jlong size, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		size_t ret_ = toStream(self).decodeLz4(toStream(src), (size_t)size, status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jlong stream_encode_lz4(TS_JNI_ARGS, jlong self, jlong dest, jlong size, jbooleanArray status, jint level) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		size_t ret_ = toStream(self).encodeLz4(toStream(dest), (size_t)size, status_, level);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jlong stream_encode_lz4_fast(TS_JNI_ARGS, jlong self, jlong dest, jlong size, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		size_t ret_ = toStream(self).encodeLz4Fast(toStream(dest), (size_t)size, status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jlong stream_encode_lz4_best(TS_JNI_ARGS, jlong self, jlong dest, jlong size, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		size_t ret_ = toStream(self).encodeLz4Best(toStream(dest), (size_t)size, status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static const JNINativeMethod stream_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)stream_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)stream_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)stream_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)stream_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)stream_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)stream_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)stream_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)stream_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)stream_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)stream_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)stream_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)stream_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)stream_get_internal_ptr },
		{ (char*)"move_", (char*)"(J)J", (void*)stream_move },
		{ (char*)"is_opened", (char*)"(J)Z", (void*)stream_is_opened },
		{ (char*)"is_mapped", (char*)"(J)Z", (void*)stream_is_mapped },
		{ (char*)"is_available", (char*)"(J)Z", (void*)stream_is_available },
		{ (char*)"get_size", (char*)"(J)J", (void*)stream_get_size },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)stream_get_name },
		{ (char*)"tell_", (char*)"(J)J", (void*)stream_tell },
		{ (char*)"seek_", (char*)"(JJ)Z", (void*)stream_seek },
		{ (char*)"seek_back", (char*)"(JJ)Z", (void*)stream_seek_back },
		{ (char*)"seek_cur", (char*)"(JJ)Z", (void*)stream_seek_cur },
		{ (char*)"get_data", (char*)"(J)J", (void*)stream_get_data },
		{ (char*)"read_", (char*)"(J[B)J", (void*)stream_read },
		{ (char*)"write_", (char*)"(J[B)J", (void*)stream_write },
		{ (char*)"flush_", (char*)"(J)Z", (void*)stream_flush },
		{ (char*)"puts_", (char*)"(JLjava/lang/String;)Z", (void*)stream_puts },
		{ (char*)"puts_1", (char*)"(JJ)Z", (void*)stream_puts_1 },
		{ (char*)"gets_", (char*)"(J[Z)Ljava/lang/String;", (void*)stream_gets },
		{ (char*)"readi8_", (char*)"(J[Z)B", (void*)stream_readi8 },
		{ (char*)"writei8_", (char*)"(JB)Z", (void*)stream_writei8 },
		{ (char*)"readu8_", (char*)"(J[Z)B", (void*)stream_readu8 },
		{ (char*)"writeu8_", (char*)"(JB)Z", (void*)stream_writeu8 },
		{ (char*)"readi16_", (char*)"(J[Z)S", (void*)stream_readi16 },
		{ (char*)"writei16_", (char*)"(JS)Z", (void*)stream_writei16 },
		{ (char*)"readu16_", (char*)"(J[Z)S", (void*)stream_readu16 },
		{ (char*)"writeu16_", (char*)"(JS)Z", (void*)stream_writeu16 },
		{ (char*)"readi32_", (char*)"(J[Z)I", (void*)stream_readi32 },
		{ (char*)"writei32_", (char*)"(JI)Z", (void*)stream_writei32 },
		{ (char*)"readu32_", (char*)"(J[Z)I", (void*)stream_readu32 },
		{ (char*)"writeu32_", (char*)"(JI)Z", (void*)stream_writeu32 },
		{ (char*)"readi64_", (char*)"(J[Z)J", (void*)stream_readi64 },
		{ (char*)"writei64_", (char*)"(JJ)Z", (void*)stream_writei64 },
		{ (char*)"readu64_", (char*)"(J[Z)J", (void*)stream_readu64 },
		{ (char*)"writeu64_", (char*)"(JJ)Z", (void*)stream_writeu64 },
		{ (char*)"readf32_", (char*)"(J[Z)F", (void*)stream_readf32 },
		{ (char*)"writef32_", (char*)"(JF)Z", (void*)stream_writef32 },
		{ (char*)"readf64_", (char*)"(J[Z)D", (void*)stream_readf64 },
		{ (char*)"writef64_", (char*)"(JD)Z", (void*)stream_writef64 },
		{ (char*)"readi32e_", (char*)"(J[Z)I", (void*)stream_readi32e },
		{ (char*)"writei32e_", (char*)"(JI)Z", (void*)stream_writei32e },
		{ (char*)"readu32e_", (char*)"(J[Z)I", (void*)stream_readu32e },
		{ (char*)"writeu32e_", (char*)"(JI)Z", (void*)stream_writeu32e },
		{ (char*)"readi64e_", (char*)"(J[Z)J", (void*)stream_readi64e },
		{ (char*)"writei64e_", (char*)"(JJ)Z", (void*)stream_writei64e },
		{ (char*)"readu64e_", (char*)"(J[Z)J", (void*)stream_readu64e },
		{ (char*)"writeu64e_", (char*)"(JJ)Z", (void*)stream_writeu64e },
		{ (char*)"read_string", (char*)"(J[Z)Ljava/lang/String;", (void*)stream_read_string },
		{ (char*)"write_string", (char*)"(JJ)Z", (void*)stream_write_string },
		{ (char*)"write_string_1", (char*)"(JLjava/lang/String;)Z", (void*)stream_write_string_1 },
		{ (char*)"read_string_1", (char*)"(JB[ZI)Ljava/lang/String;", (void*)stream_read_string_1 },
		{ (char*)"write_string_2", (char*)"(JJB)Z", (void*)stream_write_string_2 },
		{ (char*)"write_string_3", (char*)"(JLjava/lang/String;B)Z", (void*)stream_write_string_3 },
		{ (char*)"read_token", (char*)"(J[Z)Ljava/lang/String;", (void*)stream_read_token },
		{ (char*)"read_token_1", (char*)"(JJZ)Z", (void*)stream_read_token_1 },
		{ (char*)"read_line", (char*)"(J[Z)Ljava/lang/String;", (void*)stream_read_line },
		{ (char*)"read_line_1", (char*)"(JJZZ)Z", (void*)stream_read_line_1 },
		{ (char*)"read_stream", (char*)"(JJJ[Z)J", (void*)stream_read_stream },
		{ (char*)"write_stream", (char*)"(JJJ[Z)J", (void*)stream_write_stream },
		{ (char*)"read_zip", (char*)"(J[B)J", (void*)stream_read_zip },
		{ (char*)"write_zip", (char*)"(J[BI)J", (void*)stream_write_zip },
		{ (char*)"write_zip_fast", (char*)"(J[B)J", (void*)stream_write_zip_fast },
		{ (char*)"write_zip_best", (char*)"(J[B)J", (void*)stream_write_zip_best },
		{ (char*)"read_lz4", (char*)"(J[B)J", (void*)stream_read_lz4 },
		{ (char*)"write_lz4", (char*)"(J[BI)J", (void*)stream_write_lz4 },
		{ (char*)"write_lz4_fast", (char*)"(J[B)J", (void*)stream_write_lz4_fast },
		{ (char*)"write_lz4_best", (char*)"(J[B)J", (void*)stream_write_lz4_best },
		{ (char*)"decode_zip", (char*)"(JJJ[ZI)J", (void*)stream_decode_zip },
		{ (char*)"encode_zip", (char*)"(JJJ[ZI)J", (void*)stream_encode_zip },
		{ (char*)"encode_zip_fast", (char*)"(JJJ[Z)J", (void*)stream_encode_zip_fast },
		{ (char*)"encode_zip_best", (char*)"(JJJ[Z)J", (void*)stream_encode_zip_best },
		{ (char*)"decode_lz4", (char*)"(JJJ[Z)J", (void*)stream_decode_lz4 },
		{ (char*)"encode_lz4", (char*)"(JJJ[ZI)J", (void*)stream_encode_lz4 },
		{ (char*)"encode_lz4_fast", (char*)"(JJJ[Z)J", (void*)stream_encode_lz4_fast },
		{ (char*)"encode_lz4_best", (char*)"(JJJ[Z)J", (void*)stream_encode_lz4_best },
	};
	
	// Tellusim::Blob
	static jlong blob_new(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newBlob(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong blob_new_1(TS_JNI_ARGS, jlong name) {
		return newBlob(toString(name));
	}
	static jlong blob_new_2(TS_JNI_ARGS, jbyteArray data, jlong size, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newBlob((uint8_t*)ByteArray(env, data).get(), (size_t)size, name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong blob_new_3(TS_JNI_ARGS, jlong blob, jboolean move) {
		return newBlob(toBlob(blob), (bool)move);
	}
	static void blob_delete(TS_JNI_ARGS, jlong self) {
		delete (Blob*)self;
	}
	static void blob_release(TS_JNI_ARGS, jlong self) {
		toBlob(self).release();
	}
	static void blob_clear(TS_JNI_ARGS, jlong self) {
		toBlob(self).clear();
	}
	static void blob_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toBlob(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void blob_set_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toBlob(self).setName(toString(name));
	}
	static void blob_set_size(TS_JNI_ARGS, jlong self, jlong size) {
		toBlob(self).setSize((size_t)size);
	}
	static void blob_set_capacity(TS_JNI_ARGS, jlong self, jlong size) {
		toBlob(self).setCapacity((size_t)size);
	}
	static jlong blob_get_capacity(TS_JNI_ARGS, jlong self) {
		return (jlong)toBlob(self).getCapacity();
	}
	static jboolean blob_set_data(TS_JNI_ARGS, jlong self, jbyteArray data, jlong size) {
		return toBlob(self).setData((uint8_t*)ByteArray(env, data).get(), (size_t)size);
	}
	static jboolean blob_set_data_1(TS_JNI_ARGS, jlong self, jlong blob) {
		return toBlob(self).setData(toBlob(blob));
	}
	static jlong blob_get_data(TS_JNI_ARGS, jlong self) {
		return (jlong)toBlob(self).getData();
	}
	static jlong blob_get_data_1(TS_JNI_ARGS, jlong self) {
		return (jlong)toBlob(self).getData();
	}
	static jstring blob_encode_base64(TS_JNI_ARGS, jlong self, jlong size) {
		return env->NewStringUTF(toBlob(self).encodeBase64((size_t)size).get());
	}
	static jboolean blob_decode_base64(TS_JNI_ARGS, jlong self, jstring src) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		bool ret_ = toBlob(self).decodeBase64(src_);
		env->ReleaseStringUTFChars(src, src_);
		return ret_;
	}
	static void blob_get_md5(TS_JNI_ARGS, jlong self, jintArray hash, jlong size) {
		toBlob(self).getMD5(hash, (size_t)size);
	}
	static jstring blob_get_md5_1(TS_JNI_ARGS, jlong self, jlong size) {
		return env->NewStringUTF(toBlob(self).getMD5((size_t)size).get());
	}
	static jstring blob_get_md5_2(TS_JNI_ARGS, jlong str) {
		return env->NewStringUTF(Blob::getMD5(toString(str)).get());
	}
	static jstring blob_get_md5_3(TS_JNI_ARGS, jbyteArray src) {
		return env->NewStringUTF(Blob::getMD5(ByteArray(env, src).get(), env->GetArrayLength(src)).get());
	}
	static jstring blob_get_md5_4(TS_JNI_ARGS, jlong src, jlong size) {
		return env->NewStringUTF(Blob::getMD5(toStream(src), (size_t)size).get());
	}
	static void blob_get_sha1(TS_JNI_ARGS, jlong self, jintArray hash, jlong size) {
		toBlob(self).getSHA1(hash, (size_t)size);
	}
	static jstring blob_get_sha1_1(TS_JNI_ARGS, jlong self, jlong size) {
		return env->NewStringUTF(toBlob(self).getSHA1((size_t)size).get());
	}
	static jstring blob_get_sha1_2(TS_JNI_ARGS, jlong str) {
		return env->NewStringUTF(Blob::getSHA1(toString(str)).get());
	}
	static jstring blob_get_sha1_3(TS_JNI_ARGS, jbyteArray src) {
		return env->NewStringUTF(Blob::getSHA1(ByteArray(env, src).get(), env->GetArrayLength(src)).get());
	}
	static jstring blob_get_sha1_4(TS_JNI_ARGS, jlong src, jlong size) {
		return env->NewStringUTF(Blob::getSHA1(toStream(src), (size_t)size).get());
	}
	static const JNINativeMethod blob_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;)J", (void*)blob_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)blob_new_1 },
		{ (char*)"new_2", (char*)"([BJLjava/lang/String;)J", (void*)blob_new_2 },
		{ (char*)"new_3", (char*)"(JZ)J", (void*)blob_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)blob_delete },
		{ (char*)"release_", (char*)"(J)V", (void*)blob_release },
		{ (char*)"clear_", (char*)"(J)V", (void*)blob_clear },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)blob_set_name },
		{ (char*)"set_name_1", (char*)"(JJ)V", (void*)blob_set_name_1 },
		{ (char*)"set_size", (char*)"(JJ)V", (void*)blob_set_size },
		{ (char*)"set_capacity", (char*)"(JJ)V", (void*)blob_set_capacity },
		{ (char*)"get_capacity", (char*)"(J)J", (void*)blob_get_capacity },
		{ (char*)"set_data", (char*)"(J[BJ)Z", (void*)blob_set_data },
		{ (char*)"set_data_1", (char*)"(JJ)Z", (void*)blob_set_data_1 },
		{ (char*)"get_data", (char*)"(J)J", (void*)blob_get_data },
		{ (char*)"get_data_1", (char*)"(J)J", (void*)blob_get_data_1 },
		{ (char*)"encode_base64", (char*)"(JJ)Ljava/lang/String;", (void*)blob_encode_base64 },
		{ (char*)"decode_base64", (char*)"(JLjava/lang/String;)Z", (void*)blob_decode_base64 },
		{ (char*)"get_md5", (char*)"(J[IJ)V", (void*)blob_get_md5 },
		{ (char*)"get_md5_1", (char*)"(JJ)Ljava/lang/String;", (void*)blob_get_md5_1 },
		{ (char*)"get_md5_2", (char*)"(J)Ljava/lang/String;", (void*)blob_get_md5_2 },
		{ (char*)"get_md5_3", (char*)"([B)Ljava/lang/String;", (void*)blob_get_md5_3 },
		{ (char*)"get_md5_4", (char*)"(JJ)Ljava/lang/String;", (void*)blob_get_md5_4 },
		{ (char*)"get_sha1", (char*)"(J[IJ)V", (void*)blob_get_sha1 },
		{ (char*)"get_sha1_1", (char*)"(JJ)Ljava/lang/String;", (void*)blob_get_sha1_1 },
		{ (char*)"get_sha1_2", (char*)"(J)Ljava/lang/String;", (void*)blob_get_sha1_2 },
		{ (char*)"get_sha1_3", (char*)"([B)Ljava/lang/String;", (void*)blob_get_sha1_3 },
		{ (char*)"get_sha1_4", (char*)"(JJ)Ljava/lang/String;", (void*)blob_get_sha1_4 },
	};
	
	// Tellusim::File
	static jlong file_new(TS_JNI_ARGS) {
		return newFile();
	}
	static void file_delete(TS_JNI_ARGS, jlong self) {
		delete (File*)self;
	}
	static jboolean file_open(TS_JNI_ARGS, jlong self, jstring name, jstring mode) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *mode_ = (mode) ? env->GetStringUTFChars(mode, nullptr) : nullptr;
		bool ret_ = toFile(self).open(name_, mode_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(mode, mode_);
		return ret_;
	}
	static jboolean file_open_1(TS_JNI_ARGS, jlong self, jlong name, jstring mode) {
		const char *mode_ = (mode) ? env->GetStringUTFChars(mode, nullptr) : nullptr;
		bool ret_ = toFile(self).open(toString(name), mode_);
		env->ReleaseStringUTFChars(mode, mode_);
		return ret_;
	}
	static jboolean file_open_2(TS_JNI_ARGS, jlong self, jint fd, jstring name, jstring mode) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *mode_ = (mode) ? env->GetStringUTFChars(mode, nullptr) : nullptr;
		bool ret_ = toFile(self).open(fd, name_, mode_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(mode, mode_);
		return ret_;
	}
	static jboolean file_popen(TS_JNI_ARGS, jlong self, jstring command, jstring mode) {
		const char *command_ = (command) ? env->GetStringUTFChars(command, nullptr) : nullptr;
		const char *mode_ = (mode) ? env->GetStringUTFChars(mode, nullptr) : nullptr;
		bool ret_ = toFile(self).popen(command_, mode_);
		env->ReleaseStringUTFChars(command, command_);
		env->ReleaseStringUTFChars(mode, mode_);
		return ret_;
	}
	static jboolean file_popen_1(TS_JNI_ARGS, jlong self, jlong command, jstring mode) {
		const char *mode_ = (mode) ? env->GetStringUTFChars(mode, nullptr) : nullptr;
		bool ret_ = toFile(self).popen(toString(command), mode_);
		env->ReleaseStringUTFChars(mode, mode_);
		return ret_;
	}
	static void file_close(TS_JNI_ARGS, jlong self) {
		toFile(self).close();
	}
	static jboolean file_is_file(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = File::isFile(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean file_is_file_1(TS_JNI_ARGS, jlong name) {
		return File::isFile(toString(name));
	}
	static jlong file_get_mtime(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint64_t ret_ = File::getMTime(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jlong file_get_size(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		size_t ret_ = File::getSize(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jboolean file_remove(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = File::remove(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static const JNINativeMethod file_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)file_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)file_delete },
		{ (char*)"open_", (char*)"(JLjava/lang/String;Ljava/lang/String;)Z", (void*)file_open },
		{ (char*)"open_1", (char*)"(JJLjava/lang/String;)Z", (void*)file_open_1 },
		{ (char*)"open_2", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)file_open_2 },
		{ (char*)"popen_", (char*)"(JLjava/lang/String;Ljava/lang/String;)Z", (void*)file_popen },
		{ (char*)"popen_1", (char*)"(JJLjava/lang/String;)Z", (void*)file_popen_1 },
		{ (char*)"close_", (char*)"(J)V", (void*)file_close },
		{ (char*)"is_file", (char*)"(Ljava/lang/String;)Z", (void*)file_is_file },
		{ (char*)"is_file_1", (char*)"(J)Z", (void*)file_is_file_1 },
		{ (char*)"get_mtime", (char*)"(Ljava/lang/String;)J", (void*)file_get_mtime },
		{ (char*)"get_size", (char*)"(Ljava/lang/String;)J", (void*)file_get_size },
		{ (char*)"remove_", (char*)"(Ljava/lang/String;)Z", (void*)file_remove },
	};
	
	// Tellusim::Socket
	static jlong socket_new(TS_JNI_ARGS, jint type) {
		return newSocket((Socket::Type)type);
	}
	static void socket_delete(TS_JNI_ARGS, jlong self) {
		delete (Socket*)self;
	}
	static jboolean socket_open(TS_JNI_ARGS, jlong self, jshort port, jshort num) {
		return toSocket(self).open((uint16_t)port, (uint16_t)num);
	}
	static jboolean socket_open_1(TS_JNI_ARGS, jlong self, jstring name, jshort port) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toSocket(self).open(name_, (uint16_t)port);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean socket_open_2(TS_JNI_ARGS, jlong self, jlong name, jshort port) {
		return toSocket(self).open(toString(name), (uint16_t)port);
	}
	static void socket_close(TS_JNI_ARGS, jlong self) {
		toSocket(self).close();
	}
	static jboolean socket_connect(TS_JNI_ARGS, jlong self, jint sec, jint usec) {
		return toSocket(self).connect((uint32_t)sec, (uint32_t)usec);
	}
	static jboolean socket_accept(TS_JNI_ARGS, jlong self, jlong socket) {
		return toSocket(self).accept(toSocket(socket));
	}
	static jboolean socket_select(TS_JNI_ARGS, jlong self, jint sec, jint usec) {
		return toSocket(self).select((uint32_t)sec, (uint32_t)usec);
	}
	static jboolean socket_set_timeout(TS_JNI_ARGS, jlong self, jint sec) {
		return toSocket(self).setTimeout((uint32_t)sec);
	}
	static jint socket_get_timeout(TS_JNI_ARGS, jlong self) {
		return toSocket(self).getTimeout();
	}
	static jboolean socket_set_block(TS_JNI_ARGS, jlong self, jboolean block) {
		return toSocket(self).setBlock((bool)block);
	}
	static jboolean socket_get_block(TS_JNI_ARGS, jlong self) {
		return toSocket(self).getBlock();
	}
	static jboolean socket_set_delay(TS_JNI_ARGS, jlong self, jboolean delay) {
		return toSocket(self).setDelay((bool)delay);
	}
	static jboolean socket_get_delay(TS_JNI_ARGS, jlong self) {
		return toSocket(self).getDelay();
	}
	static void socket_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toSocket(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void socket_set_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toSocket(self).setName(toString(name));
	}
	static jshort socket_get_port(TS_JNI_ARGS, jlong self) {
		return toSocket(self).getPort();
	}
	static jint socket_get_fd(TS_JNI_ARGS, jlong self) {
		return toSocket(self).getFD();
	}
	static jint socket_get_type(TS_JNI_ARGS, jlong self) {
		return toSocket(self).getType();
	}
	static jstring socket_get_address(TS_JNI_ARGS, jstring delimiter) {
		const char *delimiter_ = (delimiter) ? env->GetStringUTFChars(delimiter, nullptr) : nullptr;
		String ret_ = Socket::getAddress(delimiter_);
		env->ReleaseStringUTFChars(delimiter, delimiter_);
		return env->NewStringUTF(ret_.get());
	}
	static const JNINativeMethod socket_methods[] = {
		{ (char*)"new_", (char*)"(I)J", (void*)socket_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)socket_delete },
		{ (char*)"open_", (char*)"(JSS)Z", (void*)socket_open },
		{ (char*)"open_1", (char*)"(JLjava/lang/String;S)Z", (void*)socket_open_1 },
		{ (char*)"open_2", (char*)"(JJS)Z", (void*)socket_open_2 },
		{ (char*)"close_", (char*)"(J)V", (void*)socket_close },
		{ (char*)"connect_", (char*)"(JII)Z", (void*)socket_connect },
		{ (char*)"accept_", (char*)"(JJ)Z", (void*)socket_accept },
		{ (char*)"select_", (char*)"(JII)Z", (void*)socket_select },
		{ (char*)"set_timeout", (char*)"(JI)Z", (void*)socket_set_timeout },
		{ (char*)"get_timeout", (char*)"(J)I", (void*)socket_get_timeout },
		{ (char*)"set_block", (char*)"(JZ)Z", (void*)socket_set_block },
		{ (char*)"get_block", (char*)"(J)Z", (void*)socket_get_block },
		{ (char*)"set_delay", (char*)"(JZ)Z", (void*)socket_set_delay },
		{ (char*)"get_delay", (char*)"(J)Z", (void*)socket_get_delay },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)socket_set_name },
		{ (char*)"set_name_1", (char*)"(JJ)V", (void*)socket_set_name_1 },
		{ (char*)"get_port", (char*)"(J)S", (void*)socket_get_port },
		{ (char*)"get_fd", (char*)"(J)I", (void*)socket_get_fd },
		{ (char*)"get_type", (char*)"(J)I", (void*)socket_get_type },
		{ (char*)"get_address", (char*)"(Ljava/lang/String;)Ljava/lang/String;", (void*)socket_get_address },
	};
	
	// Tellusim::SocketSSL
	static jlong socket_ssl_new(TS_JNI_ARGS) {
		return newSocketSSL();
	}
	static void socket_ssl_delete(TS_JNI_ARGS, jlong self) {
		delete (SocketSSL*)self;
	}
	static jboolean socket_ssl_equal_socket_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toSocketSSL(self).operator==(toSocket(base));
	}
	static jlong socket_ssl_cast_socket_ptr(TS_JNI_ARGS, jlong self) {
		return newSocketSSL(toSocket(self));
	}
	static jlong socket_ssl_base_socket_ptr(TS_JNI_ARGS, jlong self) {
		return newSocket(toSocketSSL(self).getSocket());
	}
	static jboolean socket_ssl_handshake(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toSocketSSL(self).handshake(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean socket_ssl_accept(TS_JNI_ARGS, jlong self, jlong socket) {
		return toSocketSSL(self).accept(toSocketSSL(socket));
	}
	static jboolean socket_ssl_accept_1(TS_JNI_ARGS, jlong self, jlong socket) {
		return toSocketSSL(self).accept(toSocket(socket));
	}
	static jboolean socket_ssl_load(TS_JNI_ARGS, jlong self, jlong stream) {
		return toSocketSSL(self).load(toStream(stream));
	}
	static jboolean socket_ssl_load_1(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toSocketSSL(self).load(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean socket_ssl_load_2(TS_JNI_ARGS, jlong self, jlong name) {
		return toSocketSSL(self).load(toString(name));
	}
	static jboolean socket_ssl_is_connected(TS_JNI_ARGS, jlong self) {
		return toSocketSSL(self).isConnected();
	}
	static const JNINativeMethod socket_ssl_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)socket_ssl_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)socket_ssl_delete },
		{ (char*)"equal_socket_ptr", (char*)"(JJ)Z", (void*)socket_ssl_equal_socket_ptr },
		{ (char*)"cast_socket_ptr", (char*)"(J)J", (void*)socket_ssl_cast_socket_ptr },
		{ (char*)"base_socket_ptr", (char*)"(J)J", (void*)socket_ssl_base_socket_ptr },
		{ (char*)"handshake_", (char*)"(JLjava/lang/String;)Z", (void*)socket_ssl_handshake },
		{ (char*)"accept_", (char*)"(JJ)Z", (void*)socket_ssl_accept },
		{ (char*)"accept_1", (char*)"(JJ)Z", (void*)socket_ssl_accept_1 },
		{ (char*)"load_", (char*)"(JJ)Z", (void*)socket_ssl_load },
		{ (char*)"load_1", (char*)"(JLjava/lang/String;)Z", (void*)socket_ssl_load_1 },
		{ (char*)"load_2", (char*)"(JJ)Z", (void*)socket_ssl_load_2 },
		{ (char*)"is_connected", (char*)"(J)Z", (void*)socket_ssl_is_connected },
	};
	
	// Tellusim::Source
	static jlong source_new(TS_JNI_ARGS) {
		return newSource();
	}
	static jlong source_new_1(TS_JNI_ARGS, jbyteArray data, jlong size, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newSource((uint8_t*)ByteArray(env, data).get(), (size_t)size, name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void source_delete(TS_JNI_ARGS, jlong self) {
		delete (Source*)self;
	}
	static jboolean source_open(TS_JNI_ARGS, jlong self, jstring name, jboolean callback, jboolean write) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toSource(self).open(name_, (bool)callback, (bool)write);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean source_open_1(TS_JNI_ARGS, jlong self, jlong name, jboolean callback, jboolean write) {
		return toSource(self).open(toString(name), (bool)callback, (bool)write);
	}
	static void source_close(TS_JNI_ARGS, jlong self) {
		toSource(self).close();
	}
	static void source_set_name(TS_JNI_ARGS, jlong self, jstring name, jlong offset, jlong size) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toSource(self).setName(name_, (size_t)offset, (size_t)size);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void source_set_name_1(TS_JNI_ARGS, jlong self, jlong name, jlong offset, jlong size) {
		toSource(self).setName(toString(name), (size_t)offset, (size_t)size);
	}
	static void source_set_data(TS_JNI_ARGS, jlong self, jbyteArray data, jlong size, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toSource(self).setData((uint8_t*)ByteArray(env, data).get(), (size_t)size, name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jboolean source_is_source(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Source::isSource(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean source_is_source_1(TS_JNI_ARGS, jlong name) {
		return Source::isSource(toString(name));
	}
	static jlong source_get_mtime(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint64_t ret_ = Source::getMTime(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jlong source_get_size(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		size_t ret_ = Source::getSize(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static const JNINativeMethod source_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)source_new },
		{ (char*)"new_1", (char*)"([BJLjava/lang/String;)J", (void*)source_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)source_delete },
		{ (char*)"open_", (char*)"(JLjava/lang/String;ZZ)Z", (void*)source_open },
		{ (char*)"open_1", (char*)"(JJZZ)Z", (void*)source_open_1 },
		{ (char*)"close_", (char*)"(J)V", (void*)source_close },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;JJ)V", (void*)source_set_name },
		{ (char*)"set_name_1", (char*)"(JJJJ)V", (void*)source_set_name_1 },
		{ (char*)"set_data", (char*)"(J[BJLjava/lang/String;)V", (void*)source_set_data },
		{ (char*)"is_source", (char*)"(Ljava/lang/String;)Z", (void*)source_is_source },
		{ (char*)"is_source_1", (char*)"(J)Z", (void*)source_is_source_1 },
		{ (char*)"get_mtime", (char*)"(Ljava/lang/String;)J", (void*)source_get_mtime },
		{ (char*)"get_size", (char*)"(Ljava/lang/String;)J", (void*)source_get_size },
	};
	
	// Tellusim::Date
	static jlong date_new(TS_JNI_ARGS) {
		return newDate();
	}
	static jlong date_new_1(TS_JNI_ARGS, jlong time, jboolean local) {
		return newDate((int64_t)time, (bool)local);
	}
	static jlong date_new_2(TS_JNI_ARGS, jstring str, jstring format) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		jlong ret_ = newDate(str_, format_);
		env->ReleaseStringUTFChars(str, str_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static void date_delete(TS_JNI_ARGS, jlong self) {
		delete (Date*)self;
	}
	static jboolean date_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDate(self) == toDate(ptr));
	}
	static jlong date_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDate(toDate(self).clonePtr());
	}
	static void date_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDate(self).clearPtr();
	}
	static void date_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDate(self).destroyPtr();
	}
	static void date_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDate(self).acquirePtr();
	}
	static void date_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDate(self).unacquirePtr();
	}
	static jboolean date_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDate(self).isValidPtr();
	}
	static jboolean date_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDate(self).isOwnerPtr();
	}
	static jboolean date_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDate(self).isConstPtr();
	}
	static jint date_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDate(self).getCountPtr();
	}
	static jlong date_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDate(self).getInternalPtr();
	}
	static void date_clear(TS_JNI_ARGS, jlong self) {
		toDate(self).clear();
	}
	static void date_set_time(TS_JNI_ARGS, jlong self, jlong time, jboolean local) {
		toDate(self).setTime((int64_t)time, (bool)local);
	}
	static jlong date_get_time(TS_JNI_ARGS, jlong self, jboolean local) {
		return (jlong)toDate(self).getTime((bool)local);
	}
	static jboolean date_set_string(TS_JNI_ARGS, jlong self, jstring str, jstring format) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toDate(self).setString(str_, format_);
		env->ReleaseStringUTFChars(str, str_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jstring date_get_string(TS_JNI_ARGS, jlong self, jstring format) {
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		String ret_ = toDate(self).getString(format_);
		env->ReleaseStringUTFChars(format, format_);
		return env->NewStringUTF(ret_.get());
	}
	static void date_set_year(TS_JNI_ARGS, jlong self, jint year) {
		toDate(self).setYear((uint32_t)year);
	}
	static void date_set_month(TS_JNI_ARGS, jlong self, jint month) {
		toDate(self).setMonth((uint32_t)month);
	}
	static void date_set_date(TS_JNI_ARGS, jlong self, jint date) {
		toDate(self).setDate((uint32_t)date);
	}
	static void date_set_day(TS_JNI_ARGS, jlong self, jint day) {
		toDate(self).setDay((uint32_t)day);
	}
	static void date_set_hours(TS_JNI_ARGS, jlong self, jint hours) {
		toDate(self).setHours((uint32_t)hours);
	}
	static void date_set_minutes(TS_JNI_ARGS, jlong self, jint minutes) {
		toDate(self).setMinutes((uint32_t)minutes);
	}
	static void date_set_seconds(TS_JNI_ARGS, jlong self, jint seconds) {
		toDate(self).setSeconds((uint32_t)seconds);
	}
	static jint date_get_year(TS_JNI_ARGS, jlong self) {
		return toDate(self).getYear();
	}
	static jint date_get_month(TS_JNI_ARGS, jlong self) {
		return toDate(self).getMonth();
	}
	static jint date_get_date(TS_JNI_ARGS, jlong self) {
		return toDate(self).getDate();
	}
	static jint date_get_day(TS_JNI_ARGS, jlong self) {
		return toDate(self).getDay();
	}
	static jint date_get_hours(TS_JNI_ARGS, jlong self) {
		return toDate(self).getHours();
	}
	static jint date_get_minutes(TS_JNI_ARGS, jlong self) {
		return toDate(self).getMinutes();
	}
	static jint date_get_seconds(TS_JNI_ARGS, jlong self) {
		return toDate(self).getSeconds();
	}
	static jint date_get_time_zone(TS_JNI_ARGS) {
		return Date::getTimeZone();
	}
	static const JNINativeMethod date_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)date_new },
		{ (char*)"new_1", (char*)"(JZ)J", (void*)date_new_1 },
		{ (char*)"new_2", (char*)"(Ljava/lang/String;Ljava/lang/String;)J", (void*)date_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)date_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)date_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)date_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)date_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)date_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)date_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)date_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)date_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)date_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)date_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)date_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)date_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)date_clear },
		{ (char*)"set_time", (char*)"(JJZ)V", (void*)date_set_time },
		{ (char*)"get_time", (char*)"(JZ)J", (void*)date_get_time },
		{ (char*)"set_string", (char*)"(JLjava/lang/String;Ljava/lang/String;)Z", (void*)date_set_string },
		{ (char*)"get_string", (char*)"(JLjava/lang/String;)Ljava/lang/String;", (void*)date_get_string },
		{ (char*)"set_year", (char*)"(JI)V", (void*)date_set_year },
		{ (char*)"set_month", (char*)"(JI)V", (void*)date_set_month },
		{ (char*)"set_date", (char*)"(JI)V", (void*)date_set_date },
		{ (char*)"set_day", (char*)"(JI)V", (void*)date_set_day },
		{ (char*)"set_hours", (char*)"(JI)V", (void*)date_set_hours },
		{ (char*)"set_minutes", (char*)"(JI)V", (void*)date_set_minutes },
		{ (char*)"set_seconds", (char*)"(JI)V", (void*)date_set_seconds },
		{ (char*)"get_year", (char*)"(J)I", (void*)date_get_year },
		{ (char*)"get_month", (char*)"(J)I", (void*)date_get_month },
		{ (char*)"get_date", (char*)"(J)I", (void*)date_get_date },
		{ (char*)"get_day", (char*)"(J)I", (void*)date_get_day },
		{ (char*)"get_hours", (char*)"(J)I", (void*)date_get_hours },
		{ (char*)"get_minutes", (char*)"(J)I", (void*)date_get_minutes },
		{ (char*)"get_seconds", (char*)"(J)I", (void*)date_get_seconds },
		{ (char*)"get_time_zone", (char*)"()I", (void*)date_get_time_zone },
	};
	
	// Tellusim::Info
	static jlong info_new(TS_JNI_ARGS) {
		return newInfo();
	}
	static void info_delete(TS_JNI_ARGS, jlong self) {
		delete (Info*)self;
	}
	static jboolean info_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toInfo(self) == toInfo(ptr));
	}
	static jlong info_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newInfo(toInfo(self).clonePtr());
	}
	static void info_clear_ptr(TS_JNI_ARGS, jlong self) {
		toInfo(self).clearPtr();
	}
	static void info_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toInfo(self).destroyPtr();
	}
	static void info_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toInfo(self).acquirePtr();
	}
	static void info_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toInfo(self).unacquirePtr();
	}
	static jboolean info_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toInfo(self).isValidPtr();
	}
	static jboolean info_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toInfo(self).isOwnerPtr();
	}
	static jboolean info_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toInfo(self).isConstPtr();
	}
	static jint info_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toInfo(self).getCountPtr();
	}
	static jlong info_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toInfo(self).getInternalPtr();
	}
	static jlong info_get_system_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toInfo(self).getSystemMemory();
	}
	static jlong info_get_system_uptime(TS_JNI_ARGS, jlong self) {
		return (jlong)toInfo(self).getSystemUptime();
	}
	static jstring info_get_system_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toInfo(self).getSystemName().get());
	}
	static jstring info_get_system_version(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toInfo(self).getSystemVersion().get());
	}
	static jstring info_get_kernel_version(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toInfo(self).getKernelVersion().get());
	}
	static jint info_get_cpu_count(TS_JNI_ARGS, jlong self) {
		return toInfo(self).getCPUCount();
	}
	static jstring info_get_cpu_name(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toInfo(self).getCPUName((uint32_t)index).get());
	}
	static jstring info_get_cpu_vendor(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toInfo(self).getCPUVendor((uint32_t)index).get());
	}
	static jint info_get_cpu_cores(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getCPUCores((uint32_t)index);
	}
	static jint info_get_cpu_threads(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getCPUThreads((uint32_t)index);
	}
	static jlong info_get_cpu_frequency(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toInfo(self).getCPUFrequency((uint32_t)index);
	}
	static jint info_get_cpu_temperature(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getCPUTemperature((uint32_t)index);
	}
	static jint info_get_cpu_utilization(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getCPUUtilization((uint32_t)index);
	}
	static jint info_get_cpu_fan_speed(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getCPUFanSpeed((uint32_t)index);
	}
	static jint info_get_cpu_power(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getCPUPower((uint32_t)index);
	}
	static jint info_get_gpu_count(TS_JNI_ARGS, jlong self) {
		return toInfo(self).getGPUCount();
	}
	static jstring info_get_gpu_name(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toInfo(self).getGPUName((uint32_t)index).get());
	}
	static jstring info_get_gpu_vendor(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toInfo(self).getGPUVendor((uint32_t)index).get());
	}
	static jstring info_get_gpu_serial(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toInfo(self).getGPUSerial((uint32_t)index).get());
	}
	static jstring info_get_gpu_device(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toInfo(self).getGPUDevice((uint32_t)index).get());
	}
	static jstring info_get_gpu_version(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toInfo(self).getGPUVersion((uint32_t)index).get());
	}
	static jlong info_get_gpu_memory(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toInfo(self).getGPUMemory((uint32_t)index);
	}
	static jint info_get_gpu_screens(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getGPUScreens((uint32_t)index);
	}
	static jlong info_get_gpu_frequency(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toInfo(self).getGPUFrequency((uint32_t)index);
	}
	static jint info_get_gpu_temperature(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getGPUTemperature((uint32_t)index);
	}
	static jint info_get_gpu_utilization(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getGPUUtilization((uint32_t)index);
	}
	static jint info_get_gpu_fan_speed(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getGPUFanSpeed((uint32_t)index);
	}
	static jint info_get_gpu_power(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).getGPUPower((uint32_t)index);
	}
	static jboolean info_is_gpu_throttling(TS_JNI_ARGS, jlong self, jint index) {
		return toInfo(self).isGPUThrottling((uint32_t)index);
	}
	static const JNINativeMethod info_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)info_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)info_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)info_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)info_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)info_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)info_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)info_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)info_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)info_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)info_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)info_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)info_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)info_get_internal_ptr },
		{ (char*)"get_system_memory", (char*)"(J)J", (void*)info_get_system_memory },
		{ (char*)"get_system_uptime", (char*)"(J)J", (void*)info_get_system_uptime },
		{ (char*)"get_system_name", (char*)"(J)Ljava/lang/String;", (void*)info_get_system_name },
		{ (char*)"get_system_version", (char*)"(J)Ljava/lang/String;", (void*)info_get_system_version },
		{ (char*)"get_kernel_version", (char*)"(J)Ljava/lang/String;", (void*)info_get_kernel_version },
		{ (char*)"get_cpu_count", (char*)"(J)I", (void*)info_get_cpu_count },
		{ (char*)"get_cpu_name", (char*)"(JI)Ljava/lang/String;", (void*)info_get_cpu_name },
		{ (char*)"get_cpu_vendor", (char*)"(JI)Ljava/lang/String;", (void*)info_get_cpu_vendor },
		{ (char*)"get_cpu_cores", (char*)"(JI)I", (void*)info_get_cpu_cores },
		{ (char*)"get_cpu_threads", (char*)"(JI)I", (void*)info_get_cpu_threads },
		{ (char*)"get_cpu_frequency", (char*)"(JI)J", (void*)info_get_cpu_frequency },
		{ (char*)"get_cpu_temperature", (char*)"(JI)I", (void*)info_get_cpu_temperature },
		{ (char*)"get_cpu_utilization", (char*)"(JI)I", (void*)info_get_cpu_utilization },
		{ (char*)"get_cpu_fan_speed", (char*)"(JI)I", (void*)info_get_cpu_fan_speed },
		{ (char*)"get_cpu_power", (char*)"(JI)I", (void*)info_get_cpu_power },
		{ (char*)"get_gpu_count", (char*)"(J)I", (void*)info_get_gpu_count },
		{ (char*)"get_gpu_name", (char*)"(JI)Ljava/lang/String;", (void*)info_get_gpu_name },
		{ (char*)"get_gpu_vendor", (char*)"(JI)Ljava/lang/String;", (void*)info_get_gpu_vendor },
		{ (char*)"get_gpu_serial", (char*)"(JI)Ljava/lang/String;", (void*)info_get_gpu_serial },
		{ (char*)"get_gpu_device", (char*)"(JI)Ljava/lang/String;", (void*)info_get_gpu_device },
		{ (char*)"get_gpu_version", (char*)"(JI)Ljava/lang/String;", (void*)info_get_gpu_version },
		{ (char*)"get_gpu_memory", (char*)"(JI)J", (void*)info_get_gpu_memory },
		{ (char*)"get_gpu_screens", (char*)"(JI)I", (void*)info_get_gpu_screens },
		{ (char*)"get_gpu_frequency", (char*)"(JI)J", (void*)info_get_gpu_frequency },
		{ (char*)"get_gpu_temperature", (char*)"(JI)I", (void*)info_get_gpu_temperature },
		{ (char*)"get_gpu_utilization", (char*)"(JI)I", (void*)info_get_gpu_utilization },
		{ (char*)"get_gpu_fan_speed", (char*)"(JI)I", (void*)info_get_gpu_fan_speed },
		{ (char*)"get_gpu_power", (char*)"(JI)I", (void*)info_get_gpu_power },
		{ (char*)"is_gpu_throttling", (char*)"(JI)Z", (void*)info_is_gpu_throttling },
	};
	
	// Tellusim::Directory
	static jlong directory_new(TS_JNI_ARGS) {
		return newDirectory();
	}
	static void directory_delete(TS_JNI_ARGS, jlong self) {
		delete (Directory*)self;
	}
	static jboolean directory_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDirectory(self) == toDirectory(ptr));
	}
	static jlong directory_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDirectory(toDirectory(self).clonePtr());
	}
	static void directory_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDirectory(self).clearPtr();
	}
	static void directory_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDirectory(self).destroyPtr();
	}
	static void directory_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDirectory(self).acquirePtr();
	}
	static void directory_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDirectory(self).unacquirePtr();
	}
	static jboolean directory_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDirectory(self).isValidPtr();
	}
	static jboolean directory_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDirectory(self).isOwnerPtr();
	}
	static jboolean directory_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDirectory(self).isConstPtr();
	}
	static jint directory_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDirectory(self).getCountPtr();
	}
	static jlong directory_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDirectory(self).getInternalPtr();
	}
	static jboolean directory_open(TS_JNI_ARGS, jlong self, jstring name, jboolean children) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toDirectory(self).open(name_, (bool)children);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean directory_open_1(TS_JNI_ARGS, jlong self, jlong name, jboolean children) {
		return toDirectory(self).open(toString(name), (bool)children);
	}
	static void directory_close(TS_JNI_ARGS, jlong self) {
		toDirectory(self).close();
	}
	static jboolean directory_is_opened(TS_JNI_ARGS, jlong self) {
		return toDirectory(self).isOpened();
	}
	static jstring directory_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDirectory(self).getName().get());
	}
	static jint directory_get_num_files(TS_JNI_ARGS, jlong self) {
		return toDirectory(self).getNumFiles();
	}
	static jstring directory_get_file_name(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toDirectory(self).getFileName((uint32_t)index).get());
	}
	static jint directory_get_file_attributes(TS_JNI_ARGS, jlong self, jint index) {
		return toDirectory(self).getFileAttributes((uint32_t)index);
	}
	static jlong directory_get_file_mtime(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toDirectory(self).getFileMTime((uint32_t)index);
	}
	static jlong directory_get_file_atime(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toDirectory(self).getFileATime((uint32_t)index);
	}
	static jlong directory_get_file_ctime(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toDirectory(self).getFileCTime((uint32_t)index);
	}
	static jlong directory_get_file_size(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toDirectory(self).getFileSize((uint32_t)index);
	}
	static jint directory_get_num_directories(TS_JNI_ARGS, jlong self) {
		return toDirectory(self).getNumDirectories();
	}
	static jstring directory_get_directory_name(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toDirectory(self).getDirectoryName((uint32_t)index).get());
	}
	static jint directory_get_directory_attributes(TS_JNI_ARGS, jlong self, jint index) {
		return toDirectory(self).getDirectoryAttributes((uint32_t)index);
	}
	static jlong directory_get_directory_ctime(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toDirectory(self).getDirectoryCTime((uint32_t)index);
	}
	static jint directory_get_directory_size(TS_JNI_ARGS, jlong self, jint index) {
		return toDirectory(self).getDirectorySize((uint32_t)index);
	}
	static jboolean directory_is_file(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Directory::isFile(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean directory_is_file_1(TS_JNI_ARGS, jlong name) {
		return Directory::isFile(toString(name));
	}
	static jboolean directory_set_file_attributes(TS_JNI_ARGS, jstring name, jint attributes) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Directory::setFileAttributes(name_, (Directory::Attributes)attributes);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint directory_get_file_attributes_1(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Directory::Attributes ret_ = Directory::getFileAttributes(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean directory_set_file_mtime(TS_JNI_ARGS, jstring name, jlong time) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Directory::setFileMTime(name_, (uint64_t)time);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong directory_get_file_mtime_1(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint64_t ret_ = Directory::getFileMTime(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jlong directory_get_file_atime_1(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint64_t ret_ = Directory::getFileATime(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jlong directory_get_file_ctime_1(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint64_t ret_ = Directory::getFileCTime(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jlong directory_get_file_size_1(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		size_t ret_ = Directory::getFileSize(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jlong directory_get_file_size_2(TS_JNI_ARGS, jlong name) {
		return (jlong)Directory::getFileSize(toString(name));
	}
	static jboolean directory_remove_file(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Directory::removeFile(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean directory_remove_file_1(TS_JNI_ARGS, jlong name) {
		return Directory::removeFile(toString(name));
	}
	static jboolean directory_copy_file(TS_JNI_ARGS, jstring name, jstring new_name, jboolean attributes) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *new_name_ = (new_name) ? env->GetStringUTFChars(new_name, nullptr) : nullptr;
		bool ret_ = Directory::copyFile(name_, new_name_, (bool)attributes);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(new_name, new_name_);
		return ret_;
	}
	static jboolean directory_copy_file_1(TS_JNI_ARGS, jlong name, jlong new_name, jboolean attributes) {
		return Directory::copyFile(toString(name), toString(new_name), (bool)attributes);
	}
	static jboolean directory_is_directory(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Directory::isDirectory(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean directory_is_directory_1(TS_JNI_ARGS, jlong name) {
		return Directory::isDirectory(toString(name));
	}
	static jboolean directory_change_directory(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Directory::changeDirectory(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean directory_change_directory_1(TS_JNI_ARGS, jlong name) {
		return Directory::changeDirectory(toString(name));
	}
	static jboolean directory_create_directory(TS_JNI_ARGS, jstring name, jboolean children) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Directory::createDirectory(name_, (bool)children);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean directory_create_directory_1(TS_JNI_ARGS, jlong name, jboolean children) {
		return Directory::createDirectory(toString(name), (bool)children);
	}
	static jboolean directory_remove_directory(TS_JNI_ARGS, jstring name, jboolean children) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Directory::removeDirectory(name_, (bool)children);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean directory_remove_directory_1(TS_JNI_ARGS, jlong name, jboolean children) {
		return Directory::removeDirectory(toString(name), (bool)children);
	}
	static jboolean directory_copy_directory(TS_JNI_ARGS, jstring name, jstring new_name, jboolean attributes) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *new_name_ = (new_name) ? env->GetStringUTFChars(new_name, nullptr) : nullptr;
		bool ret_ = Directory::copyDirectory(name_, new_name_, (bool)attributes);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(new_name, new_name_);
		return ret_;
	}
	static jboolean directory_copy_directory_1(TS_JNI_ARGS, jlong name, jlong new_name, jboolean attributes) {
		return Directory::copyDirectory(toString(name), toString(new_name), (bool)attributes);
	}
	static jboolean directory_rename(TS_JNI_ARGS, jstring name, jstring new_name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *new_name_ = (new_name) ? env->GetStringUTFChars(new_name, nullptr) : nullptr;
		bool ret_ = Directory::rename(name_, new_name_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(new_name, new_name_);
		return ret_;
	}
	static jboolean directory_rename_1(TS_JNI_ARGS, jlong name, jlong new_name) {
		return Directory::rename(toString(name), toString(new_name));
	}
	static jstring directory_get_current_directory(TS_JNI_ARGS) {
		return env->NewStringUTF(Directory::getCurrentDirectory().get());
	}
	static jstring directory_get_home_directory(TS_JNI_ARGS) {
		return env->NewStringUTF(Directory::getHomeDirectory().get());
	}
	static jstring directory_get_temp_directory(TS_JNI_ARGS) {
		return env->NewStringUTF(Directory::getTempDirectory().get());
	}
	static jstring directory_get_config_directory(TS_JNI_ARGS) {
		return env->NewStringUTF(Directory::getConfigDirectory().get());
	}
	static jstring directory_get_documents_directory(TS_JNI_ARGS) {
		return env->NewStringUTF(Directory::getDocumentsDirectory().get());
	}
	static const JNINativeMethod directory_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)directory_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)directory_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)directory_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)directory_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)directory_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)directory_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)directory_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)directory_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)directory_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)directory_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)directory_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)directory_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)directory_get_internal_ptr },
		{ (char*)"open_", (char*)"(JLjava/lang/String;Z)Z", (void*)directory_open },
		{ (char*)"open_1", (char*)"(JJZ)Z", (void*)directory_open_1 },
		{ (char*)"close_", (char*)"(J)V", (void*)directory_close },
		{ (char*)"is_opened", (char*)"(J)Z", (void*)directory_is_opened },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)directory_get_name },
		{ (char*)"get_num_files", (char*)"(J)I", (void*)directory_get_num_files },
		{ (char*)"get_file_name", (char*)"(JI)Ljava/lang/String;", (void*)directory_get_file_name },
		{ (char*)"get_file_attributes", (char*)"(JI)I", (void*)directory_get_file_attributes },
		{ (char*)"get_file_mtime", (char*)"(JI)J", (void*)directory_get_file_mtime },
		{ (char*)"get_file_atime", (char*)"(JI)J", (void*)directory_get_file_atime },
		{ (char*)"get_file_ctime", (char*)"(JI)J", (void*)directory_get_file_ctime },
		{ (char*)"get_file_size", (char*)"(JI)J", (void*)directory_get_file_size },
		{ (char*)"get_num_directories", (char*)"(J)I", (void*)directory_get_num_directories },
		{ (char*)"get_directory_name", (char*)"(JI)Ljava/lang/String;", (void*)directory_get_directory_name },
		{ (char*)"get_directory_attributes", (char*)"(JI)I", (void*)directory_get_directory_attributes },
		{ (char*)"get_directory_ctime", (char*)"(JI)J", (void*)directory_get_directory_ctime },
		{ (char*)"get_directory_size", (char*)"(JI)I", (void*)directory_get_directory_size },
		{ (char*)"is_file", (char*)"(Ljava/lang/String;)Z", (void*)directory_is_file },
		{ (char*)"is_file_1", (char*)"(J)Z", (void*)directory_is_file_1 },
		{ (char*)"set_file_attributes", (char*)"(Ljava/lang/String;I)Z", (void*)directory_set_file_attributes },
		{ (char*)"get_file_attributes_1", (char*)"(Ljava/lang/String;)I", (void*)directory_get_file_attributes_1 },
		{ (char*)"set_file_mtime", (char*)"(Ljava/lang/String;J)Z", (void*)directory_set_file_mtime },
		{ (char*)"get_file_mtime_1", (char*)"(Ljava/lang/String;)J", (void*)directory_get_file_mtime_1 },
		{ (char*)"get_file_atime_1", (char*)"(Ljava/lang/String;)J", (void*)directory_get_file_atime_1 },
		{ (char*)"get_file_ctime_1", (char*)"(Ljava/lang/String;)J", (void*)directory_get_file_ctime_1 },
		{ (char*)"get_file_size_1", (char*)"(Ljava/lang/String;)J", (void*)directory_get_file_size_1 },
		{ (char*)"get_file_size_2", (char*)"(J)J", (void*)directory_get_file_size_2 },
		{ (char*)"remove_file", (char*)"(Ljava/lang/String;)Z", (void*)directory_remove_file },
		{ (char*)"remove_file_1", (char*)"(J)Z", (void*)directory_remove_file_1 },
		{ (char*)"copy_file", (char*)"(Ljava/lang/String;Ljava/lang/String;Z)Z", (void*)directory_copy_file },
		{ (char*)"copy_file_1", (char*)"(JJZ)Z", (void*)directory_copy_file_1 },
		{ (char*)"is_directory", (char*)"(Ljava/lang/String;)Z", (void*)directory_is_directory },
		{ (char*)"is_directory_1", (char*)"(J)Z", (void*)directory_is_directory_1 },
		{ (char*)"change_directory", (char*)"(Ljava/lang/String;)Z", (void*)directory_change_directory },
		{ (char*)"change_directory_1", (char*)"(J)Z", (void*)directory_change_directory_1 },
		{ (char*)"create_directory", (char*)"(Ljava/lang/String;Z)Z", (void*)directory_create_directory },
		{ (char*)"create_directory_1", (char*)"(JZ)Z", (void*)directory_create_directory_1 },
		{ (char*)"remove_directory", (char*)"(Ljava/lang/String;Z)Z", (void*)directory_remove_directory },
		{ (char*)"remove_directory_1", (char*)"(JZ)Z", (void*)directory_remove_directory_1 },
		{ (char*)"copy_directory", (char*)"(Ljava/lang/String;Ljava/lang/String;Z)Z", (void*)directory_copy_directory },
		{ (char*)"copy_directory_1", (char*)"(JJZ)Z", (void*)directory_copy_directory_1 },
		{ (char*)"rename_", (char*)"(Ljava/lang/String;Ljava/lang/String;)Z", (void*)directory_rename },
		{ (char*)"rename_1", (char*)"(JJ)Z", (void*)directory_rename_1 },
		{ (char*)"get_current_directory", (char*)"()Ljava/lang/String;", (void*)directory_get_current_directory },
		{ (char*)"get_home_directory", (char*)"()Ljava/lang/String;", (void*)directory_get_home_directory },
		{ (char*)"get_temp_directory", (char*)"()Ljava/lang/String;", (void*)directory_get_temp_directory },
		{ (char*)"get_config_directory", (char*)"()Ljava/lang/String;", (void*)directory_get_config_directory },
		{ (char*)"get_documents_directory", (char*)"()Ljava/lang/String;", (void*)directory_get_documents_directory },
	};
	
	// Tellusim::Archive
	static jlong archive_new(TS_JNI_ARGS) {
		return newArchive();
	}
	static void archive_delete(TS_JNI_ARGS, jlong self) {
		delete (Archive*)self;
	}
	static jboolean archive_open(TS_JNI_ARGS, jlong self, jstring name, jstring type) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toArchive(self).open(name_, type_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jboolean archive_open_1(TS_JNI_ARGS, jlong self, jlong name, jstring type) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toArchive(self).open(toString(name), type_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jboolean archive_open_2(TS_JNI_ARGS, jlong self, jlong stream, jstring type) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toArchive(self).open(toStream(stream), type_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static void archive_close(TS_JNI_ARGS, jlong self) {
		toArchive(self).close();
	}
	static jboolean archive_is_opened(TS_JNI_ARGS, jlong self) {
		return toArchive(self).isOpened();
	}
	static jstring archive_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toArchive(self).getName().get());
	}
	static jint archive_get_num_files(TS_JNI_ARGS, jlong self) {
		return toArchive(self).getNumFiles();
	}
	static jstring archive_get_file_name(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toArchive(self).getFileName((uint32_t)index).get());
	}
	static jlong archive_get_file_mtime(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toArchive(self).getFileMTime((uint32_t)index);
	}
	static jlong archive_get_file_size(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toArchive(self).getFileSize((uint32_t)index);
	}
	static jint archive_find_file(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toArchive(self).findFile(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint archive_find_file_1(TS_JNI_ARGS, jlong self, jlong name) {
		return toArchive(self).findFile(toString(name));
	}
	static jboolean archive_is_file(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toArchive(self).isFile(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean archive_is_file_1(TS_JNI_ARGS, jlong self, jlong name) {
		return toArchive(self).isFile(toString(name));
	}
	static jlong archive_open_file(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Stream ret_ = toArchive(self).openFile(name_);
		env->ReleaseStringUTFChars(name, name_);
		return newStream(ret_);
	}
	static jlong archive_open_file_1(TS_JNI_ARGS, jlong self, jlong name) {
		return newStream(toArchive(self).openFile(toString(name)));
	}
	static jlong archive_open_file_2(TS_JNI_ARGS, jlong self, jint index) {
		return newStream(toArchive(self).openFile((uint32_t)index));
	}
	static const JNINativeMethod archive_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)archive_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)archive_delete },
		{ (char*)"open_", (char*)"(JLjava/lang/String;Ljava/lang/String;)Z", (void*)archive_open },
		{ (char*)"open_1", (char*)"(JJLjava/lang/String;)Z", (void*)archive_open_1 },
		{ (char*)"open_2", (char*)"(JJLjava/lang/String;)Z", (void*)archive_open_2 },
		{ (char*)"close_", (char*)"(J)V", (void*)archive_close },
		{ (char*)"is_opened", (char*)"(J)Z", (void*)archive_is_opened },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)archive_get_name },
		{ (char*)"get_num_files", (char*)"(J)I", (void*)archive_get_num_files },
		{ (char*)"get_file_name", (char*)"(JI)Ljava/lang/String;", (void*)archive_get_file_name },
		{ (char*)"get_file_mtime", (char*)"(JI)J", (void*)archive_get_file_mtime },
		{ (char*)"get_file_size", (char*)"(JI)J", (void*)archive_get_file_size },
		{ (char*)"find_file", (char*)"(JLjava/lang/String;)I", (void*)archive_find_file },
		{ (char*)"find_file_1", (char*)"(JJ)I", (void*)archive_find_file_1 },
		{ (char*)"is_file", (char*)"(JLjava/lang/String;)Z", (void*)archive_is_file },
		{ (char*)"is_file_1", (char*)"(JJ)Z", (void*)archive_is_file_1 },
		{ (char*)"open_file", (char*)"(JLjava/lang/String;)J", (void*)archive_open_file },
		{ (char*)"open_file_1", (char*)"(JJ)J", (void*)archive_open_file_1 },
		{ (char*)"open_file_2", (char*)"(JI)J", (void*)archive_open_file_2 },
	};
	
	// Tellusim::Image
	static jlong image_new(TS_JNI_ARGS) {
		return newImage();
	}
	static jlong image_new_1(TS_JNI_ARGS, jstring name, jint flags, jint offset) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newImage(name_, (Image::Flags)flags, (uint32_t)offset);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong image_new_2(TS_JNI_ARGS, jlong stream, jint flags, jint offset) {
		return newImage(toStream(stream), (Image::Flags)flags, (uint32_t)offset);
	}
	static jlong image_new_3(TS_JNI_ARGS, jint type, jint format, jlong size, jint flags) {
		return newImage((Image::Type)type, (Format)format, toSize(size), (Image::Flags)flags);
	}
	static jlong image_new_4(TS_JNI_ARGS, jint type, jint format, jlong size, jint layers, jint flags) {
		return newImage((Image::Type)type, (Format)format, toSize(size), (uint32_t)layers, (Image::Flags)flags);
	}
	static void image_delete(TS_JNI_ARGS, jlong self) {
		delete (Image*)self;
	}
	static jboolean image_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toImage(self) == toImage(ptr));
	}
	static jlong image_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newImage(toImage(self).clonePtr());
	}
	static void image_clear_ptr(TS_JNI_ARGS, jlong self) {
		toImage(self).clearPtr();
	}
	static void image_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toImage(self).destroyPtr();
	}
	static void image_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toImage(self).acquirePtr();
	}
	static void image_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toImage(self).unacquirePtr();
	}
	static jboolean image_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toImage(self).isValidPtr();
	}
	static jboolean image_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toImage(self).isOwnerPtr();
	}
	static jboolean image_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toImage(self).isConstPtr();
	}
	static jint image_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toImage(self).getCountPtr();
	}
	static jlong image_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toImage(self).getInternalPtr();
	}
	static void image_clear(TS_JNI_ARGS, jlong self) {
		toImage(self).clear();
	}
	static jboolean image_is_loaded(TS_JNI_ARGS, jlong self) {
		return toImage(self).isLoaded();
	}
	static jboolean image_is_allocated(TS_JNI_ARGS, jlong self) {
		return toImage(self).isAllocated();
	}
	static jint image_get_type(TS_JNI_ARGS, jlong self) {
		return toImage(self).getType();
	}
	static jstring image_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(Image::getTypeName((Image::Type)type));
	}
	static jstring image_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toImage(self).getTypeName());
	}
	static jboolean image_is2d_type(TS_JNI_ARGS, jlong self) {
		return toImage(self).is2DType();
	}
	static jboolean image_is3d_type(TS_JNI_ARGS, jlong self) {
		return toImage(self).is3DType();
	}
	static jboolean image_is_cube_type(TS_JNI_ARGS, jlong self) {
		return toImage(self).isCubeType();
	}
	static jint image_get_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).getFormat();
	}
	static jstring image_get_format_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toImage(self).getFormatName());
	}
	static jboolean image_is_color_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isColorFormat();
	}
	static jboolean image_is_depth_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isDepthFormat();
	}
	static jboolean image_is_pixel_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isPixelFormat();
	}
	static jboolean image_is_plain_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isPlainFormat();
	}
	static jboolean image_is_mixed_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isMixedFormat();
	}
	static jboolean image_is_block_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isBlockFormat();
	}
	static jboolean image_is_stencil_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isStencilFormat();
	}
	static jboolean image_is_norm_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isNormFormat();
	}
	static jboolean image_is_srgb_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isSRGBFormat();
	}
	static jboolean image_is_float_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isFloatFormat();
	}
	static jboolean image_is_signed_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isSignedFormat();
	}
	static jboolean image_is_unsigned_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isUnsignedFormat();
	}
	static jboolean image_is_integer_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isIntegerFormat();
	}
	static jboolean image_isi8_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isi8Format();
	}
	static jboolean image_isu8_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isu8Format();
	}
	static jboolean image_is8_bit_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).is8BitFormat();
	}
	static jboolean image_isi16_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isi16Format();
	}
	static jboolean image_isu16_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isu16Format();
	}
	static jboolean image_isf16_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isf16Format();
	}
	static jboolean image_is16_bit_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).is16BitFormat();
	}
	static jboolean image_isi32_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isi32Format();
	}
	static jboolean image_isu32_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isu32Format();
	}
	static jboolean image_isf32_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isf32Format();
	}
	static jboolean image_is32_bit_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).is32BitFormat();
	}
	static jboolean image_isi64_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isi64Format();
	}
	static jboolean image_isu64_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isu64Format();
	}
	static jboolean image_isf64_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isf64Format();
	}
	static jboolean image_is64_bit_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).is64BitFormat();
	}
	static jboolean image_is_bc15_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isBC15Format();
	}
	static jboolean image_is_bc67_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isBC67Format();
	}
	static jboolean image_is_etc2_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isETC2Format();
	}
	static jboolean image_is_astc_format(TS_JNI_ARGS, jlong self) {
		return toImage(self).isASTCFormat();
	}
	static jint image_get_components(TS_JNI_ARGS, jlong self) {
		return toImage(self).getComponents();
	}
	static jint image_get_pixel_size(TS_JNI_ARGS, jlong self) {
		return toImage(self).getPixelSize();
	}
	static jint image_get_block_size(TS_JNI_ARGS, jlong self) {
		return toImage(self).getBlockSize();
	}
	static jint image_get_block_width(TS_JNI_ARGS, jlong self) {
		return toImage(self).getBlockWidth();
	}
	static jint image_get_block_height(TS_JNI_ARGS, jlong self) {
		return toImage(self).getBlockHeight();
	}
	static jint image_get_width(TS_JNI_ARGS, jlong self) {
		return toImage(self).getWidth();
	}
	static jint image_get_height(TS_JNI_ARGS, jlong self) {
		return toImage(self).getHeight();
	}
	static jint image_get_depth(TS_JNI_ARGS, jlong self) {
		return toImage(self).getDepth();
	}
	static jint image_get_faces(TS_JNI_ARGS, jlong self) {
		return toImage(self).getFaces();
	}
	static jint image_get_layers(TS_JNI_ARGS, jlong self) {
		return toImage(self).getLayers();
	}
	static jint image_get_mipmaps(TS_JNI_ARGS, jlong self) {
		return toImage(self).getMipmaps();
	}
	static jint image_find_mipmap(TS_JNI_ARGS, jlong self, jlong size) {
		return toImage(self).findMipmap(toSize(size));
	}
	static jint image_get_width_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return toImage(self).getWidth((uint32_t)mipmap);
	}
	static jint image_get_height_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return toImage(self).getHeight((uint32_t)mipmap);
	}
	static jint image_get_depth_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return toImage(self).getDepth((uint32_t)mipmap);
	}
	static jboolean image_has_layers(TS_JNI_ARGS, jlong self) {
		return toImage(self).hasLayers();
	}
	static jboolean image_has_mipmaps(TS_JNI_ARGS, jlong self) {
		return toImage(self).hasMipmaps();
	}
	static jlong image_get_size(TS_JNI_ARGS, jlong self) {
		return newSize(toImage(self).getSize());
	}
	static jlong image_get_region(TS_JNI_ARGS, jlong self) {
		return newRegion(toImage(self).getRegion());
	}
	static jlong image_get_slice(TS_JNI_ARGS, jlong self) {
		return newSlice(toImage(self).getSlice());
	}
	static jlong image_get_size_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return newSize(toImage(self).getSize((uint32_t)mipmap));
	}
	static jlong image_get_region_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return newRegion(toImage(self).getRegion((uint32_t)mipmap));
	}
	static jlong image_get_slice_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return newSlice(toImage(self).getSlice((uint32_t)mipmap));
	}
	static void image_set_meta_info(TS_JNI_ARGS, jlong self, jlong str) {
		toImage(self).setMetaInfo(toString(str));
	}
	static jstring image_get_meta_info(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toImage(self).getMetaInfo().get());
	}
	static jstring image_get_description(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toImage(self).getDescription().get());
	}
	static jlong image_get_offset(TS_JNI_ARGS, jlong self, jlong slice, jint alignment) {
		return (jlong)toImage(self).getOffset(toSlice(slice), (uint32_t)alignment);
	}
	static jlong image_get_stride(TS_JNI_ARGS, jlong self, jint mipmap, jint alignment) {
		return (jlong)toImage(self).getStride((uint32_t)mipmap, (uint32_t)alignment);
	}
	static jlong image_get_mipmap_size(TS_JNI_ARGS, jlong self, jint mipmap, jint alignment) {
		return (jlong)toImage(self).getMipmapSize((uint32_t)mipmap, (uint32_t)alignment);
	}
	static jlong image_get_layer_size(TS_JNI_ARGS, jlong self, jint alignment) {
		return (jlong)toImage(self).getLayerSize((uint32_t)alignment);
	}
	static jlong image_get_data_size(TS_JNI_ARGS, jlong self, jint alignment) {
		return (jlong)toImage(self).getDataSize((uint32_t)alignment);
	}
	static jboolean image_create(TS_JNI_ARGS, jlong self, jint type, jint format, jlong size, jint flags) {
		return toImage(self).create((Image::Type)type, (Format)format, toSize(size), (Image::Flags)flags);
	}
	static jboolean image_create_1(TS_JNI_ARGS, jlong self, jint type, jint format, jlong size, jint layers, jint flags) {
		return toImage(self).create((Image::Type)type, (Format)format, toSize(size), (uint32_t)layers, (Image::Flags)flags);
	}
	static jboolean image_create2d(TS_JNI_ARGS, jlong self, jint format, jint size, jint flags) {
		return toImage(self).create2D((Format)format, (uint32_t)size, (Image::Flags)flags);
	}
	static jboolean image_create3d(TS_JNI_ARGS, jlong self, jint format, jint size, jint flags) {
		return toImage(self).create3D((Format)format, (uint32_t)size, (Image::Flags)flags);
	}
	static jboolean image_create_cube(TS_JNI_ARGS, jlong self, jint format, jint size, jint flags) {
		return toImage(self).createCube((Format)format, (uint32_t)size, (Image::Flags)flags);
	}
	static jboolean image_create2d_1(TS_JNI_ARGS, jlong self, jint format, jint width, jint height, jint flags) {
		return toImage(self).create2D((Format)format, (uint32_t)width, (uint32_t)height, (Image::Flags)flags);
	}
	static jboolean image_create3d_1(TS_JNI_ARGS, jlong self, jint format, jint width, jint height, jint depth, jint flags) {
		return toImage(self).create3D((Format)format, (uint32_t)width, (uint32_t)height, (uint32_t)depth, (Image::Flags)flags);
	}
	static jboolean image_create2d_2(TS_JNI_ARGS, jlong self, jint format, jint width, jint height, jint layers, jint flags) {
		return toImage(self).create2D((Format)format, (uint32_t)width, (uint32_t)height, (uint32_t)layers, (Image::Flags)flags);
	}
	static jboolean image_create_cube_1(TS_JNI_ARGS, jlong self, jint format, jint size, jint layers, jint flags) {
		return toImage(self).createCube((Format)format, (uint32_t)size, (uint32_t)layers, (Image::Flags)flags);
	}
	static jboolean image_info(TS_JNI_ARGS, jlong self, jstring name, jint flags, jint offset, jlong async) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toImage(self).info(name_, (Image::Flags)flags, (uint32_t)offset, (Async*)async);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean image_info_1(TS_JNI_ARGS, jlong self, jlong name, jint flags, jint offset, jlong async) {
		return toImage(self).info(toString(name), (Image::Flags)flags, (uint32_t)offset, (Async*)async);
	}
	static jboolean image_info_2(TS_JNI_ARGS, jlong self, jlong stream, jint flags, jint offset, jlong async) {
		return toImage(self).info(toStream(stream), (Image::Flags)flags, (uint32_t)offset, (Async*)async);
	}
	static jboolean image_info_3(TS_JNI_ARGS, jlong self, jstring name, jlong async) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toImage(self).info(name_, (Async*)async);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean image_info_4(TS_JNI_ARGS, jlong self, jlong name, jlong async) {
		return toImage(self).info(toString(name), (Async*)async);
	}
	static jboolean image_info_5(TS_JNI_ARGS, jlong self, jlong stream, jlong async) {
		return toImage(self).info(toStream(stream), (Async*)async);
	}
	static jboolean image_load(TS_JNI_ARGS, jlong self, jstring name, jint flags, jint offset, jlong async) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toImage(self).load(name_, (Image::Flags)flags, (uint32_t)offset, (Async*)async);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean image_load_1(TS_JNI_ARGS, jlong self, jlong name, jint flags, jint offset, jlong async) {
		return toImage(self).load(toString(name), (Image::Flags)flags, (uint32_t)offset, (Async*)async);
	}
	static jboolean image_load_2(TS_JNI_ARGS, jlong self, jlong stream, jint flags, jint offset, jlong async) {
		return toImage(self).load(toStream(stream), (Image::Flags)flags, (uint32_t)offset, (Async*)async);
	}
	static jboolean image_load_3(TS_JNI_ARGS, jlong self, jstring name, jlong async) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toImage(self).load(name_, (Async*)async);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean image_load_4(TS_JNI_ARGS, jlong self, jlong name, jlong async) {
		return toImage(self).load(toString(name), (Async*)async);
	}
	static jboolean image_load_5(TS_JNI_ARGS, jlong self, jlong stream, jlong async) {
		return toImage(self).load(toStream(stream), (Async*)async);
	}
	static jboolean image_save(TS_JNI_ARGS, jlong self, jstring name, jint flags, jint quality) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toImage(self).save(name_, (Image::Flags)flags, (uint32_t)quality);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean image_save_1(TS_JNI_ARGS, jlong self, jlong name, jint flags, jint quality) {
		return toImage(self).save(toString(name), (Image::Flags)flags, (uint32_t)quality);
	}
	static jboolean image_save_2(TS_JNI_ARGS, jlong self, jlong stream, jint flags, jint quality) {
		return toImage(self).save(toStream(stream), (Image::Flags)flags, (uint32_t)quality);
	}
	static jboolean image_swap(TS_JNI_ARGS, jlong self, jint component_0, jint component_1) {
		return toImage(self).swap((uint32_t)component_0, (uint32_t)component_1);
	}
	static jboolean image_copy(TS_JNI_ARGS, jlong self, jlong src, jint dest_component, jint src_component) {
		return toImage(self).copy(toImage(src), (uint32_t)dest_component, (uint32_t)src_component);
	}
	static jboolean image_flip_x(TS_JNI_ARGS, jlong self, jlong region, jlong slice) {
		return toImage(self).flipX(toRegion(region), toSlice(slice));
	}
	static jboolean image_flip_x_1(TS_JNI_ARGS, jlong self, jlong region) {
		return toImage(self).flipX(toRegion(region));
	}
	static jboolean image_flip_x_2(TS_JNI_ARGS, jlong self) {
		return toImage(self).flipX();
	}
	static jboolean image_flip_y(TS_JNI_ARGS, jlong self, jlong region, jlong slice) {
		return toImage(self).flipY(toRegion(region), toSlice(slice));
	}
	static jboolean image_flip_y_1(TS_JNI_ARGS, jlong self, jlong region) {
		return toImage(self).flipY(toRegion(region));
	}
	static jboolean image_flip_y_2(TS_JNI_ARGS, jlong self) {
		return toImage(self).flipY();
	}
	static jboolean image_copy_1(TS_JNI_ARGS, jlong self, jlong src, jlong dest_origin, jlong src_region, jlong dest_slice, jlong src_slice) {
		return toImage(self).copy(toImage(src), toOrigin(dest_origin), toRegion(src_region), toSlice(dest_slice), toSlice(src_slice));
	}
	static jboolean image_copy_2(TS_JNI_ARGS, jlong self, jlong src, jlong dest_origin, jlong src_region) {
		return toImage(self).copy(toImage(src), toOrigin(dest_origin), toRegion(src_region));
	}
	static jboolean image_copy_3(TS_JNI_ARGS, jlong self, jlong src, jlong dest_origin, jlong dest_slice) {
		return toImage(self).copy(toImage(src), toOrigin(dest_origin), toSlice(dest_slice));
	}
	static jboolean image_copy_4(TS_JNI_ARGS, jlong self, jlong src, jlong dest_slice, jlong src_slice) {
		return toImage(self).copy(toImage(src), toSlice(dest_slice), toSlice(src_slice));
	}
	static jboolean image_copy_5(TS_JNI_ARGS, jlong self, jlong src, jlong dest_origin) {
		return toImage(self).copy(toImage(src), toOrigin(dest_origin));
	}
	static jboolean image_copy_6(TS_JNI_ARGS, jlong self, jlong src, jlong dest_slice) {
		return toImage(self).copy(toImage(src), toSlice(dest_slice));
	}
	static jlong image_to_type(TS_JNI_ARGS, jlong self, jint type, jint flags, jlong async) {
		return newImage(toImage(self).toType((Image::Type)type, (Image::Flags)flags, (Async*)async));
	}
	static jlong image_to_type_1(TS_JNI_ARGS, jlong self, jint type, jlong async) {
		return newImage(toImage(self).toType((Image::Type)type, (Async*)async));
	}
	static jlong image_to_format(TS_JNI_ARGS, jlong self, jint format, jint flags, jlong async) {
		return newImage(toImage(self).toFormat((Format)format, (Image::Flags)flags, (Async*)async));
	}
	static jlong image_to_format_1(TS_JNI_ARGS, jlong self, jint format, jlong async) {
		return newImage(toImage(self).toFormat((Format)format, (Async*)async));
	}
	static jlong image_get_slice_2(TS_JNI_ARGS, jlong self, jlong slice) {
		return newImage(toImage(self).getSlice(toSlice(slice)));
	}
	static jlong image_get_component(TS_JNI_ARGS, jlong self, jint component) {
		return newImage(toImage(self).getComponent((uint32_t)component));
	}
	static jlong image_get_region_2(TS_JNI_ARGS, jlong self, jlong region, jlong slice) {
		return newImage(toImage(self).getRegion(toRegion(region), toSlice(slice)));
	}
	static jlong image_get_region_3(TS_JNI_ARGS, jlong self, jlong region) {
		return newImage(toImage(self).getRegion(toRegion(region)));
	}
	static jlong image_get_rotated(TS_JNI_ARGS, jlong self, jint angle, jlong slice) {
		return newImage(toImage(self).getRotated(angle, toSlice(slice)));
	}
	static jlong image_get_rotated_1(TS_JNI_ARGS, jlong self, jint angle) {
		return newImage(toImage(self).getRotated(angle));
	}
	static jlong image_get_resized(TS_JNI_ARGS, jlong self, jlong size, jint min, jint mag, jint flags, jlong async) {
		return newImage(toImage(self).getResized(toSize(size), (Image::Filter)min, (Image::Filter)mag, (Image::Flags)flags, (Async*)async));
	}
	static jlong image_get_resized_1(TS_JNI_ARGS, jlong self, jlong size, jint min, jint mag, jlong async) {
		return newImage(toImage(self).getResized(toSize(size), (Image::Filter)min, (Image::Filter)mag, (Async*)async));
	}
	static jlong image_get_resized_2(TS_JNI_ARGS, jlong self, jlong size, jlong async) {
		return newImage(toImage(self).getResized(toSize(size), (Async*)async));
	}
	static jlong image_get_mipmapped(TS_JNI_ARGS, jlong self, jint filter, jint flags, jlong async) {
		return newImage(toImage(self).getMipmapped((Image::Filter)filter, (Image::Flags)flags, (Async*)async));
	}
	static jlong image_get_mipmapped_1(TS_JNI_ARGS, jlong self, jint filter, jlong async) {
		return newImage(toImage(self).getMipmapped((Image::Filter)filter, (Async*)async));
	}
	static jlong image_get_mipmapped_2(TS_JNI_ARGS, jlong self, jlong async) {
		return newImage(toImage(self).getMipmapped((Async*)async));
	}
	static jint image_compare(TS_JNI_ARGS, jlong self, jlong image) {
		return toImage(self).compare(toImage(image));
	}
	static jlong image_get_data(TS_JNI_ARGS, jlong self, jlong slice) {
		return (jlong)toImage(self).getData(toSlice(slice));
	}
	static jlong image_get_data_1(TS_JNI_ARGS, jlong self, jlong slice) {
		return (jlong)toImage(self).getData(toSlice(slice));
	}
	static jlong image_get_data_2(TS_JNI_ARGS, jlong self, jlong origin, jlong slice) {
		return (jlong)toImage(self).getData(toOrigin(origin), toSlice(slice));
	}
	static jlong image_get_data_3(TS_JNI_ARGS, jlong self, jlong origin, jlong slice) {
		return (jlong)toImage(self).getData(toOrigin(origin), toSlice(slice));
	}
	static jboolean image_set_data(TS_JNI_ARGS, jlong self, jlong src, jlong slice, jint alignment, jlong stride) {
		return toImage(self).setData((const void*)src, toSlice(slice), (uint32_t)alignment, (size_t)stride);
	}
	static jboolean image_get_data_4(TS_JNI_ARGS, jlong self, jlong dest, jlong slice, jint alignment, jlong stride) {
		return toImage(self).getData((void*)dest, toSlice(slice), (uint32_t)alignment, (size_t)stride);
	}
	static jlong image_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toImage(self).getMemory();
	}
	static const JNINativeMethod image_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)image_new },
		{ (char*)"new_1", (char*)"(Ljava/lang/String;II)J", (void*)image_new_1 },
		{ (char*)"new_2", (char*)"(JII)J", (void*)image_new_2 },
		{ (char*)"new_3", (char*)"(IIJI)J", (void*)image_new_3 },
		{ (char*)"new_4", (char*)"(IIJII)J", (void*)image_new_4 },
		{ (char*)"delete_", (char*)"(J)V", (void*)image_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)image_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)image_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)image_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)image_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)image_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)image_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)image_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)image_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)image_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)image_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)image_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)image_clear },
		{ (char*)"is_loaded", (char*)"(J)Z", (void*)image_is_loaded },
		{ (char*)"is_allocated", (char*)"(J)Z", (void*)image_is_allocated },
		{ (char*)"get_type", (char*)"(J)I", (void*)image_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)image_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)image_get_type_name_1 },
		{ (char*)"is2d_type", (char*)"(J)Z", (void*)image_is2d_type },
		{ (char*)"is3d_type", (char*)"(J)Z", (void*)image_is3d_type },
		{ (char*)"is_cube_type", (char*)"(J)Z", (void*)image_is_cube_type },
		{ (char*)"get_format", (char*)"(J)I", (void*)image_get_format },
		{ (char*)"get_format_name", (char*)"(J)Ljava/lang/String;", (void*)image_get_format_name },
		{ (char*)"is_color_format", (char*)"(J)Z", (void*)image_is_color_format },
		{ (char*)"is_depth_format", (char*)"(J)Z", (void*)image_is_depth_format },
		{ (char*)"is_pixel_format", (char*)"(J)Z", (void*)image_is_pixel_format },
		{ (char*)"is_plain_format", (char*)"(J)Z", (void*)image_is_plain_format },
		{ (char*)"is_mixed_format", (char*)"(J)Z", (void*)image_is_mixed_format },
		{ (char*)"is_block_format", (char*)"(J)Z", (void*)image_is_block_format },
		{ (char*)"is_stencil_format", (char*)"(J)Z", (void*)image_is_stencil_format },
		{ (char*)"is_norm_format", (char*)"(J)Z", (void*)image_is_norm_format },
		{ (char*)"is_srgb_format", (char*)"(J)Z", (void*)image_is_srgb_format },
		{ (char*)"is_float_format", (char*)"(J)Z", (void*)image_is_float_format },
		{ (char*)"is_signed_format", (char*)"(J)Z", (void*)image_is_signed_format },
		{ (char*)"is_unsigned_format", (char*)"(J)Z", (void*)image_is_unsigned_format },
		{ (char*)"is_integer_format", (char*)"(J)Z", (void*)image_is_integer_format },
		{ (char*)"isi8_format", (char*)"(J)Z", (void*)image_isi8_format },
		{ (char*)"isu8_format", (char*)"(J)Z", (void*)image_isu8_format },
		{ (char*)"is8_bit_format", (char*)"(J)Z", (void*)image_is8_bit_format },
		{ (char*)"isi16_format", (char*)"(J)Z", (void*)image_isi16_format },
		{ (char*)"isu16_format", (char*)"(J)Z", (void*)image_isu16_format },
		{ (char*)"isf16_format", (char*)"(J)Z", (void*)image_isf16_format },
		{ (char*)"is16_bit_format", (char*)"(J)Z", (void*)image_is16_bit_format },
		{ (char*)"isi32_format", (char*)"(J)Z", (void*)image_isi32_format },
		{ (char*)"isu32_format", (char*)"(J)Z", (void*)image_isu32_format },
		{ (char*)"isf32_format", (char*)"(J)Z", (void*)image_isf32_format },
		{ (char*)"is32_bit_format", (char*)"(J)Z", (void*)image_is32_bit_format },
		{ (char*)"isi64_format", (char*)"(J)Z", (void*)image_isi64_format },
		{ (char*)"isu64_format", (char*)"(J)Z", (void*)image_isu64_format },
		{ (char*)"isf64_format", (char*)"(J)Z", (void*)image_isf64_format },
		{ (char*)"is64_bit_format", (char*)"(J)Z", (void*)image_is64_bit_format },
		{ (char*)"is_bc15_format", (char*)"(J)Z", (void*)image_is_bc15_format },
		{ (char*)"is_bc67_format", (char*)"(J)Z", (void*)image_is_bc67_format },
		{ (char*)"is_etc2_format", (char*)"(J)Z", (void*)image_is_etc2_format },
		{ (char*)"is_astc_format", (char*)"(J)Z", (void*)image_is_astc_format },
		{ (char*)"get_components", (char*)"(J)I", (void*)image_get_components },
		{ (char*)"get_pixel_size", (char*)"(J)I", (void*)image_get_pixel_size },
		{ (char*)"get_block_size", (char*)"(J)I", (void*)image_get_block_size },
		{ (char*)"get_block_width", (char*)"(J)I", (void*)image_get_block_width },
		{ (char*)"get_block_height", (char*)"(J)I", (void*)image_get_block_height },
		{ (char*)"get_width", (char*)"(J)I", (void*)image_get_width },
		{ (char*)"get_height", (char*)"(J)I", (void*)image_get_height },
		{ (char*)"get_depth", (char*)"(J)I", (void*)image_get_depth },
		{ (char*)"get_faces", (char*)"(J)I", (void*)image_get_faces },
		{ (char*)"get_layers", (char*)"(J)I", (void*)image_get_layers },
		{ (char*)"get_mipmaps", (char*)"(J)I", (void*)image_get_mipmaps },
		{ (char*)"find_mipmap", (char*)"(JJ)I", (void*)image_find_mipmap },
		{ (char*)"get_width_1", (char*)"(JI)I", (void*)image_get_width_1 },
		{ (char*)"get_height_1", (char*)"(JI)I", (void*)image_get_height_1 },
		{ (char*)"get_depth_1", (char*)"(JI)I", (void*)image_get_depth_1 },
		{ (char*)"has_layers", (char*)"(J)Z", (void*)image_has_layers },
		{ (char*)"has_mipmaps", (char*)"(J)Z", (void*)image_has_mipmaps },
		{ (char*)"get_size", (char*)"(J)J", (void*)image_get_size },
		{ (char*)"get_region", (char*)"(J)J", (void*)image_get_region },
		{ (char*)"get_slice", (char*)"(J)J", (void*)image_get_slice },
		{ (char*)"get_size_1", (char*)"(JI)J", (void*)image_get_size_1 },
		{ (char*)"get_region_1", (char*)"(JI)J", (void*)image_get_region_1 },
		{ (char*)"get_slice_1", (char*)"(JI)J", (void*)image_get_slice_1 },
		{ (char*)"set_meta_info", (char*)"(JJ)V", (void*)image_set_meta_info },
		{ (char*)"get_meta_info", (char*)"(J)Ljava/lang/String;", (void*)image_get_meta_info },
		{ (char*)"get_description", (char*)"(J)Ljava/lang/String;", (void*)image_get_description },
		{ (char*)"get_offset", (char*)"(JJI)J", (void*)image_get_offset },
		{ (char*)"get_stride", (char*)"(JII)J", (void*)image_get_stride },
		{ (char*)"get_mipmap_size", (char*)"(JII)J", (void*)image_get_mipmap_size },
		{ (char*)"get_layer_size", (char*)"(JI)J", (void*)image_get_layer_size },
		{ (char*)"get_data_size", (char*)"(JI)J", (void*)image_get_data_size },
		{ (char*)"create_", (char*)"(JIIJI)Z", (void*)image_create },
		{ (char*)"create_1", (char*)"(JIIJII)Z", (void*)image_create_1 },
		{ (char*)"create2d_", (char*)"(JIII)Z", (void*)image_create2d },
		{ (char*)"create3d_", (char*)"(JIII)Z", (void*)image_create3d },
		{ (char*)"create_cube", (char*)"(JIII)Z", (void*)image_create_cube },
		{ (char*)"create2d_1", (char*)"(JIIII)Z", (void*)image_create2d_1 },
		{ (char*)"create3d_1", (char*)"(JIIIII)Z", (void*)image_create3d_1 },
		{ (char*)"create2d_2", (char*)"(JIIIII)Z", (void*)image_create2d_2 },
		{ (char*)"create_cube_1", (char*)"(JIIII)Z", (void*)image_create_cube_1 },
		{ (char*)"info_", (char*)"(JLjava/lang/String;IIJ)Z", (void*)image_info },
		{ (char*)"info_1", (char*)"(JJIIJ)Z", (void*)image_info_1 },
		{ (char*)"info_2", (char*)"(JJIIJ)Z", (void*)image_info_2 },
		{ (char*)"info_3", (char*)"(JLjava/lang/String;J)Z", (void*)image_info_3 },
		{ (char*)"info_4", (char*)"(JJJ)Z", (void*)image_info_4 },
		{ (char*)"info_5", (char*)"(JJJ)Z", (void*)image_info_5 },
		{ (char*)"load_", (char*)"(JLjava/lang/String;IIJ)Z", (void*)image_load },
		{ (char*)"load_1", (char*)"(JJIIJ)Z", (void*)image_load_1 },
		{ (char*)"load_2", (char*)"(JJIIJ)Z", (void*)image_load_2 },
		{ (char*)"load_3", (char*)"(JLjava/lang/String;J)Z", (void*)image_load_3 },
		{ (char*)"load_4", (char*)"(JJJ)Z", (void*)image_load_4 },
		{ (char*)"load_5", (char*)"(JJJ)Z", (void*)image_load_5 },
		{ (char*)"save_", (char*)"(JLjava/lang/String;II)Z", (void*)image_save },
		{ (char*)"save_1", (char*)"(JJII)Z", (void*)image_save_1 },
		{ (char*)"save_2", (char*)"(JJII)Z", (void*)image_save_2 },
		{ (char*)"swap_", (char*)"(JII)Z", (void*)image_swap },
		{ (char*)"copy_", (char*)"(JJII)Z", (void*)image_copy },
		{ (char*)"flip_x", (char*)"(JJJ)Z", (void*)image_flip_x },
		{ (char*)"flip_x_1", (char*)"(JJ)Z", (void*)image_flip_x_1 },
		{ (char*)"flip_x_2", (char*)"(J)Z", (void*)image_flip_x_2 },
		{ (char*)"flip_y", (char*)"(JJJ)Z", (void*)image_flip_y },
		{ (char*)"flip_y_1", (char*)"(JJ)Z", (void*)image_flip_y_1 },
		{ (char*)"flip_y_2", (char*)"(J)Z", (void*)image_flip_y_2 },
		{ (char*)"copy_1", (char*)"(JJJJJJ)Z", (void*)image_copy_1 },
		{ (char*)"copy_2", (char*)"(JJJJ)Z", (void*)image_copy_2 },
		{ (char*)"copy_3", (char*)"(JJJJ)Z", (void*)image_copy_3 },
		{ (char*)"copy_4", (char*)"(JJJJ)Z", (void*)image_copy_4 },
		{ (char*)"copy_5", (char*)"(JJJ)Z", (void*)image_copy_5 },
		{ (char*)"copy_6", (char*)"(JJJ)Z", (void*)image_copy_6 },
		{ (char*)"to_type", (char*)"(JIIJ)J", (void*)image_to_type },
		{ (char*)"to_type_1", (char*)"(JIJ)J", (void*)image_to_type_1 },
		{ (char*)"to_format", (char*)"(JIIJ)J", (void*)image_to_format },
		{ (char*)"to_format_1", (char*)"(JIJ)J", (void*)image_to_format_1 },
		{ (char*)"get_slice_2", (char*)"(JJ)J", (void*)image_get_slice_2 },
		{ (char*)"get_component", (char*)"(JI)J", (void*)image_get_component },
		{ (char*)"get_region_2", (char*)"(JJJ)J", (void*)image_get_region_2 },
		{ (char*)"get_region_3", (char*)"(JJ)J", (void*)image_get_region_3 },
		{ (char*)"get_rotated", (char*)"(JIJ)J", (void*)image_get_rotated },
		{ (char*)"get_rotated_1", (char*)"(JI)J", (void*)image_get_rotated_1 },
		{ (char*)"get_resized", (char*)"(JJIIIJ)J", (void*)image_get_resized },
		{ (char*)"get_resized_1", (char*)"(JJIIJ)J", (void*)image_get_resized_1 },
		{ (char*)"get_resized_2", (char*)"(JJJ)J", (void*)image_get_resized_2 },
		{ (char*)"get_mipmapped", (char*)"(JIIJ)J", (void*)image_get_mipmapped },
		{ (char*)"get_mipmapped_1", (char*)"(JIJ)J", (void*)image_get_mipmapped_1 },
		{ (char*)"get_mipmapped_2", (char*)"(JJ)J", (void*)image_get_mipmapped_2 },
		{ (char*)"compare_", (char*)"(JJ)I", (void*)image_compare },
		{ (char*)"get_data", (char*)"(JJ)J", (void*)image_get_data },
		{ (char*)"get_data_1", (char*)"(JJ)J", (void*)image_get_data_1 },
		{ (char*)"get_data_2", (char*)"(JJJ)J", (void*)image_get_data_2 },
		{ (char*)"get_data_3", (char*)"(JJJ)J", (void*)image_get_data_3 },
		{ (char*)"set_data", (char*)"(JJJIJ)Z", (void*)image_set_data },
		{ (char*)"get_data_4", (char*)"(JJJIJ)Z", (void*)image_get_data_4 },
		{ (char*)"get_memory", (char*)"(J)J", (void*)image_get_memory },
	};
	
	// Tellusim::ImageSampler
	static jlong image_sampler_new(TS_JNI_ARGS) {
		return newImageSampler();
	}
	static jlong image_sampler_new_1(TS_JNI_ARGS, jlong image, jlong slice) {
		return newImageSampler(toImage(image), toSlice(slice));
	}
	static jlong image_sampler_new_2(TS_JNI_ARGS, jlong image, jlong slice) {
		return newImageSampler(toImage(image), toSlice(slice));
	}
	static void image_sampler_delete(TS_JNI_ARGS, jlong self) {
		delete (ImageSampler*)self;
	}
	static void image_sampler_clear(TS_JNI_ARGS, jlong self) {
		toImageSampler(self).clear();
	}
	static jboolean image_sampler_is_created(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).isCreated();
	}
	static jint image_sampler_get_type(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).getType();
	}
	static jboolean image_sampler_is2d_type(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).is2DType();
	}
	static jboolean image_sampler_is3d_type(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).is3DType();
	}
	static jboolean image_sampler_is_cube_type(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).isCubeType();
	}
	static jint image_sampler_get_format(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).getFormat();
	}
	static jstring image_sampler_get_format_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toImageSampler(self).getFormatName());
	}
	static jint image_sampler_get_width(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).getWidth();
	}
	static jint image_sampler_get_height(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).getHeight();
	}
	static jint image_sampler_get_depth(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).getDepth();
	}
	static jint image_sampler_get_faces(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).getFaces();
	}
	static jlong image_sampler_get_texels(TS_JNI_ARGS, jlong self) {
		return (jlong)toImageSampler(self).getTexels();
	}
	static jlong image_sampler_get_size(TS_JNI_ARGS, jlong self) {
		return newSize(toImageSampler(self).getSize());
	}
	static jlong image_sampler_get_region(TS_JNI_ARGS, jlong self) {
		return newRegion(toImageSampler(self).getRegion());
	}
	static jlong image_sampler_get_stride(TS_JNI_ARGS, jlong self) {
		return (jlong)toImageSampler(self).getStride();
	}
	static jlong image_sampler_get_layer_size(TS_JNI_ARGS, jlong self) {
		return (jlong)toImageSampler(self).getLayerSize();
	}
	static jint image_sampler_get_pixel_size(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).getPixelSize();
	}
	static jint image_sampler_get_components(TS_JNI_ARGS, jlong self) {
		return toImageSampler(self).getComponents();
	}
	static jlong image_sampler_get_data(TS_JNI_ARGS, jlong self) {
		return (jlong)toImageSampler(self).getData();
	}
	static jlong image_sampler_get_data_1(TS_JNI_ARGS, jlong self) {
		return (jlong)toImageSampler(self).getData();
	}
	static jboolean image_sampler_create(TS_JNI_ARGS, jlong self, jlong image, jlong slice) {
		return toImageSampler(self).create(toImage(image), toSlice(slice));
	}
	static jboolean image_sampler_create_1(TS_JNI_ARGS, jlong self, jlong image, jlong slice) {
		return toImageSampler(self).create(toImage(image), toSlice(slice));
	}
	static jboolean image_sampler_create_2(TS_JNI_ARGS, jlong self, jint type, jint format, jlong size, jlong stride, jlong data) {
		return toImageSampler(self).create((Image::Type)type, (Format)format, toSize(size), (size_t)stride, (void*)data);
	}
	static jboolean image_sampler_create_3(TS_JNI_ARGS, jlong self, jint type, jint format, jlong size, jlong stride, jlong data) {
		return toImageSampler(self).create((Image::Type)type, (Format)format, toSize(size), (size_t)stride, (const void*)data);
	}
	static jboolean image_sampler_create_4(TS_JNI_ARGS, jlong self, jint type, jint format, jlong size, jlong stride, jlong layer_size, jlong data) {
		return toImageSampler(self).create((Image::Type)type, (Format)format, toSize(size), (size_t)stride, (size_t)layer_size, (void*)data);
	}
	static jboolean image_sampler_create_5(TS_JNI_ARGS, jlong self, jint type, jint format, jlong size, jlong stride, jlong layer_size, jlong data) {
		return toImageSampler(self).create((Image::Type)type, (Format)format, toSize(size), (size_t)stride, (size_t)layer_size, (const void*)data);
	}
	static jboolean image_sampler_clear_1(TS_JNI_ARGS, jlong self, jlong color) {
		return toImageSampler(self).clear(toColor(color));
	}
	static jboolean image_sampler_clear_2(TS_JNI_ARGS, jlong self, jlong color) {
		return toImageSampler(self).clear(toImageColor(color));
	}
	static jboolean image_sampler_mad(TS_JNI_ARGS, jlong self, jlong m, jlong a) {
		return toImageSampler(self).mad(toColor(m), toColor(a));
	}
	static void image_sampler_set2d(TS_JNI_ARGS, jlong self, jint x, jint y, jlong color) {
		toImageSampler(self).set2D((uint32_t)x, (uint32_t)y, toImageColor(color));
	}
	static jlong image_sampler_get2d(TS_JNI_ARGS, jlong self, jint x, jint y, jboolean repeat) {
		return newImageColor(toImageSampler(self).get2D((uint32_t)x, (uint32_t)y, (bool)repeat));
	}
	static jlong image_sampler_get2d_1(TS_JNI_ARGS, jlong self, jdouble x, jdouble y, jboolean repeat, jint filter) {
		return newImageColor(toImageSampler(self).get2D(x, y, (bool)repeat, (Image::Filter)filter));
	}
	static void image_sampler_set3d(TS_JNI_ARGS, jlong self, jint x, jint y, jint z, jlong color) {
		toImageSampler(self).set3D((uint32_t)x, (uint32_t)y, (uint32_t)z, toImageColor(color));
	}
	static jlong image_sampler_get3d(TS_JNI_ARGS, jlong self, jint x, jint y, jint z, jboolean repeat) {
		return newImageColor(toImageSampler(self).get3D((uint32_t)x, (uint32_t)y, (uint32_t)z, (bool)repeat));
	}
	static jlong image_sampler_get3d_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z, jboolean repeat, jint filter) {
		return newImageColor(toImageSampler(self).get3D(x, y, z, (bool)repeat, (Image::Filter)filter));
	}
	static void image_sampler_set_cube(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z, jlong color) {
		toImageSampler(self).setCube(x, y, z, toImageColor(color));
	}
	static jlong image_sampler_get_cube(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z, jint filter) {
		return newImageColor(toImageSampler(self).getCube(x, y, z, (Image::Filter)filter));
	}
	static jint image_sampler_get_cube_face(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z, jfloatArray tx, jfloatArray ty) {
		float32_t *tx_ = env->GetFloatArrayElements(tx, nullptr);
		float32_t *ty_ = env->GetFloatArrayElements(ty, nullptr);
		uint32_t ret_ = toImageSampler(self).getCubeFace(x, y, z, tx_[0], ty_[0]);
		env->ReleaseFloatArrayElements(tx, tx_, 0);
		env->ReleaseFloatArrayElements(ty, ty_, 0);
		return ret_;
	}
	static void image_sampler_set_texel(TS_JNI_ARGS, jlong self, jlong t, jlong color) {
		toImageSampler(self).setTexel((size_t)t, toImageColor(color));
	}
	static jlong image_sampler_get_texel(TS_JNI_ARGS, jlong self, jlong t) {
		return newImageColor(toImageSampler(self).getTexel((size_t)t));
	}
	static const JNINativeMethod image_sampler_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)image_sampler_new },
		{ (char*)"new_1", (char*)"(JJ)J", (void*)image_sampler_new_1 },
		{ (char*)"new_2", (char*)"(JJ)J", (void*)image_sampler_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)image_sampler_delete },
		{ (char*)"clear_", (char*)"(J)V", (void*)image_sampler_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)image_sampler_is_created },
		{ (char*)"get_type", (char*)"(J)I", (void*)image_sampler_get_type },
		{ (char*)"is2d_type", (char*)"(J)Z", (void*)image_sampler_is2d_type },
		{ (char*)"is3d_type", (char*)"(J)Z", (void*)image_sampler_is3d_type },
		{ (char*)"is_cube_type", (char*)"(J)Z", (void*)image_sampler_is_cube_type },
		{ (char*)"get_format", (char*)"(J)I", (void*)image_sampler_get_format },
		{ (char*)"get_format_name", (char*)"(J)Ljava/lang/String;", (void*)image_sampler_get_format_name },
		{ (char*)"get_width", (char*)"(J)I", (void*)image_sampler_get_width },
		{ (char*)"get_height", (char*)"(J)I", (void*)image_sampler_get_height },
		{ (char*)"get_depth", (char*)"(J)I", (void*)image_sampler_get_depth },
		{ (char*)"get_faces", (char*)"(J)I", (void*)image_sampler_get_faces },
		{ (char*)"get_texels", (char*)"(J)J", (void*)image_sampler_get_texels },
		{ (char*)"get_size", (char*)"(J)J", (void*)image_sampler_get_size },
		{ (char*)"get_region", (char*)"(J)J", (void*)image_sampler_get_region },
		{ (char*)"get_stride", (char*)"(J)J", (void*)image_sampler_get_stride },
		{ (char*)"get_layer_size", (char*)"(J)J", (void*)image_sampler_get_layer_size },
		{ (char*)"get_pixel_size", (char*)"(J)I", (void*)image_sampler_get_pixel_size },
		{ (char*)"get_components", (char*)"(J)I", (void*)image_sampler_get_components },
		{ (char*)"get_data", (char*)"(J)J", (void*)image_sampler_get_data },
		{ (char*)"get_data_1", (char*)"(J)J", (void*)image_sampler_get_data_1 },
		{ (char*)"create_", (char*)"(JJJ)Z", (void*)image_sampler_create },
		{ (char*)"create_1", (char*)"(JJJ)Z", (void*)image_sampler_create_1 },
		{ (char*)"create_2", (char*)"(JIIJJJ)Z", (void*)image_sampler_create_2 },
		{ (char*)"create_3", (char*)"(JIIJJJ)Z", (void*)image_sampler_create_3 },
		{ (char*)"create_4", (char*)"(JIIJJJJ)Z", (void*)image_sampler_create_4 },
		{ (char*)"create_5", (char*)"(JIIJJJJ)Z", (void*)image_sampler_create_5 },
		{ (char*)"clear_1", (char*)"(JJ)Z", (void*)image_sampler_clear_1 },
		{ (char*)"clear_2", (char*)"(JJ)Z", (void*)image_sampler_clear_2 },
		{ (char*)"mad_", (char*)"(JJJ)Z", (void*)image_sampler_mad },
		{ (char*)"set2d_", (char*)"(JIIJ)V", (void*)image_sampler_set2d },
		{ (char*)"get2d_", (char*)"(JIIZ)J", (void*)image_sampler_get2d },
		{ (char*)"get2d_1", (char*)"(JDDZI)J", (void*)image_sampler_get2d_1 },
		{ (char*)"set3d_", (char*)"(JIIIJ)V", (void*)image_sampler_set3d },
		{ (char*)"get3d_", (char*)"(JIIIZ)J", (void*)image_sampler_get3d },
		{ (char*)"get3d_1", (char*)"(JFFFZI)J", (void*)image_sampler_get3d_1 },
		{ (char*)"set_cube", (char*)"(JFFFJ)V", (void*)image_sampler_set_cube },
		{ (char*)"get_cube", (char*)"(JFFFI)J", (void*)image_sampler_get_cube },
		{ (char*)"get_cube_face", (char*)"(JFFF[F[F)I", (void*)image_sampler_get_cube_face },
		{ (char*)"set_texel", (char*)"(JJJ)V", (void*)image_sampler_set_texel },
		{ (char*)"get_texel", (char*)"(JJ)J", (void*)image_sampler_get_texel },
	};
	
	// Tellusim::MeshNode
	static jlong mesh_node_new(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshNode(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_node_new_1(TS_JNI_ARGS, jlong mesh, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshNode(toMesh(mesh), name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_node_new_2(TS_JNI_ARGS, jlongArray parent, jstring name) {
		Array<MeshNode> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toMeshNode(parent__[i]);
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshNode(parent_.get(), name_);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_node_new_3(TS_JNI_ARGS, jlong mesh, jlongArray parent, jstring name) {
		Array<MeshNode> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toMeshNode(parent__[i]);
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshNode(toMesh(mesh), parent_.get(), name_);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void mesh_node_delete(TS_JNI_ARGS, jlong self) {
		delete (MeshNode*)self;
	}
	static jboolean mesh_node_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toMeshNode(self) == toMeshNode(ptr));
	}
	static jlong mesh_node_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newMeshNode(toMeshNode(self).clonePtr());
	}
	static void mesh_node_clear_ptr(TS_JNI_ARGS, jlong self) {
		toMeshNode(self).clearPtr();
	}
	static void mesh_node_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toMeshNode(self).destroyPtr();
	}
	static void mesh_node_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshNode(self).acquirePtr();
	}
	static void mesh_node_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshNode(self).unacquirePtr();
	}
	static jboolean mesh_node_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshNode(self).isValidPtr();
	}
	static jboolean mesh_node_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshNode(self).isOwnerPtr();
	}
	static jboolean mesh_node_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshNode(self).isConstPtr();
	}
	static jint mesh_node_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshNode(self).getCountPtr();
	}
	static jlong mesh_node_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshNode(self).getInternalPtr();
	}
	static void mesh_node_clear(TS_JNI_ARGS, jlong self) {
		toMeshNode(self).clear();
	}
	static jlong mesh_node_clone(TS_JNI_ARGS, jlong self, jlong mesh) {
		return newMeshNode(toMeshNode(self).clone(toMesh(mesh)));
	}
	static void mesh_node_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toMeshNode(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring mesh_node_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshNode(self).getName().get());
	}
	static jint mesh_node_get_index(TS_JNI_ARGS, jlong self) {
		return toMeshNode(self).getIndex();
	}
	static void mesh_node_set_mesh(TS_JNI_ARGS, jlong self, jlong mesh, jboolean check) {
		toMeshNode(self).setMesh(toMesh(mesh), (bool)check);
	}
	static jlong mesh_node_get_mesh(TS_JNI_ARGS, jlong self) {
		return newMesh(toMeshNode(self).getMesh());
	}
	static jlong mesh_node_get_mesh_1(TS_JNI_ARGS, jlong self) {
		return newMesh(toMeshNode(self).getMesh());
	}
	static jint mesh_node_set_parent(TS_JNI_ARGS, jlong self, jlong parent, jboolean check) {
		return toMeshNode(self).setParent(toMeshNode(parent), (bool)check);
	}
	static jlong mesh_node_get_parent(TS_JNI_ARGS, jlong self) {
		return newMeshNode(toMeshNode(self).getParent());
	}
	static jlong mesh_node_get_parent_1(TS_JNI_ARGS, jlong self) {
		return newMeshNode(toMeshNode(self).getParent());
	}
	static jboolean mesh_node_is_root(TS_JNI_ARGS, jlong self) {
		return toMeshNode(self).isRoot();
	}
	static void mesh_node_reserve_children(TS_JNI_ARGS, jlong self, jint num_children) {
		toMeshNode(self).reserveChildren((uint32_t)num_children);
	}
	static jint mesh_node_add_child(TS_JNI_ARGS, jlong self, jlong child, jboolean check) {
		return toMeshNode(self).addChild(toMeshNode(child), (bool)check);
	}
	static jboolean mesh_node_remove_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toMeshNode(self).removeChild(toMeshNode(child));
	}
	static void mesh_node_release_children(TS_JNI_ARGS, jlong self) {
		toMeshNode(self).releaseChildren();
	}
	static jint mesh_node_find_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toMeshNode(self).findChild(toMeshNode(child));
	}
	static jint mesh_node_get_num_children(TS_JNI_ARGS, jlong self) {
		return toMeshNode(self).getNumChildren();
	}
	static jlong mesh_node_get_child(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshNode(toMeshNode(self).getChild((uint32_t)index));
	}
	static jlong mesh_node_get_child_1(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshNode(toMeshNode(self).getChild((uint32_t)index));
	}
	static void mesh_node_clear_geometries(TS_JNI_ARGS, jlong self) {
		toMeshNode(self).clearGeometries();
	}
	static void mesh_node_reserve_geometries(TS_JNI_ARGS, jlong self, jint num_geometries) {
		toMeshNode(self).reserveGeometries((uint32_t)num_geometries);
	}
	static jint mesh_node_add_geometry(TS_JNI_ARGS, jlong self, jlong geometry, jboolean check) {
		return toMeshNode(self).addGeometry(toMeshGeometry(geometry), (bool)check);
	}
	static jboolean mesh_node_remove_geometry(TS_JNI_ARGS, jlong self, jlong geometry) {
		return toMeshNode(self).removeGeometry(toMeshGeometry(geometry));
	}
	static jboolean mesh_node_replace_geometry(TS_JNI_ARGS, jlong self, jlong old_geometry, jlong geometry) {
		return toMeshNode(self).replaceGeometry(toMeshGeometry(old_geometry), toMeshGeometry(geometry));
	}
	static jint mesh_node_find_geometry(TS_JNI_ARGS, jlong self, jlong geometry) {
		return toMeshNode(self).findGeometry(toMeshGeometry(geometry));
	}
	static jint mesh_node_get_num_geometries(TS_JNI_ARGS, jlong self) {
		return toMeshNode(self).getNumGeometries();
	}
	static jlong mesh_node_get_geometry(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshGeometry(toMeshNode(self).getGeometry((uint32_t)index));
	}
	static jlong mesh_node_get_geometry_1(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshGeometry(toMeshNode(self).getGeometry((uint32_t)index));
	}
	static void mesh_node_clear_attachments(TS_JNI_ARGS, jlong self) {
		toMeshNode(self).clearAttachments();
	}
	static void mesh_node_reserve_attachments(TS_JNI_ARGS, jlong self, jint num_attachments) {
		toMeshNode(self).reserveAttachments((uint32_t)num_attachments);
	}
	static jint mesh_node_add_attachment(TS_JNI_ARGS, jlong self, jlong attachment, jboolean check) {
		return toMeshNode(self).addAttachment(toMeshAttachment(attachment), (bool)check);
	}
	static jboolean mesh_node_remove_attachment(TS_JNI_ARGS, jlong self, jlong attachment) {
		return toMeshNode(self).removeAttachment(toMeshAttachment(attachment));
	}
	static jboolean mesh_node_replace_attachment(TS_JNI_ARGS, jlong self, jlong old_attachment, jlong attachment) {
		return toMeshNode(self).replaceAttachment(toMeshAttachment(old_attachment), toMeshAttachment(attachment));
	}
	static jint mesh_node_find_attachment(TS_JNI_ARGS, jlong self, jlong attachment) {
		return toMeshNode(self).findAttachment(toMeshAttachment(attachment));
	}
	static jint mesh_node_find_attachment_1(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toMeshNode(self).findAttachment(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint mesh_node_get_num_attachments(TS_JNI_ARGS, jlong self) {
		return toMeshNode(self).getNumAttachments();
	}
	static jlong mesh_node_get_attachment(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshAttachment(toMeshNode(self).getAttachment((uint32_t)index));
	}
	static jlong mesh_node_get_attachment_1(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshAttachment(toMeshNode(self).getAttachment((uint32_t)index));
	}
	static void mesh_node_set_local_transform(TS_JNI_ARGS, jlong self, jlong transform) {
		toMeshNode(self).setLocalTransform(toMatrix4x3d(transform));
	}
	static jlong mesh_node_get_local_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3d(toMeshNode(self).getLocalTransform());
	}
	static void mesh_node_set_global_transform(TS_JNI_ARGS, jlong self, jlong transform) {
		toMeshNode(self).setGlobalTransform(toMatrix4x3d(transform));
	}
	static jlong mesh_node_get_global_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3d(toMeshNode(self).getGlobalTransform());
	}
	static void mesh_node_set_pivot_transform(TS_JNI_ARGS, jlong self, jlong transform) {
		toMeshNode(self).setPivotTransform(toMatrix4x3d(transform));
	}
	static jlong mesh_node_get_pivot_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3d(toMeshNode(self).getPivotTransform());
	}
	static void mesh_node_set_morph_transform(TS_JNI_ARGS, jlong self, jlong transform) {
		toMeshNode(self).setMorphTransform(toVector4f(transform));
	}
	static jlong mesh_node_get_morph_transform(TS_JNI_ARGS, jlong self) {
		return newVector4f(toMeshNode(self).getMorphTransform());
	}
	static void mesh_node_create_local_transforms(TS_JNI_ARGS, jlong self, jlong itransform) {
		toMeshNode(self).createLocalTransforms(toMatrix4x3d(itransform));
	}
	static void mesh_node_create_global_transforms(TS_JNI_ARGS, jlong self, jlong transform) {
		toMeshNode(self).createGlobalTransforms(toMatrix4x3d(transform));
	}
	static void mesh_node_set_transform(TS_JNI_ARGS, jlong self, jlong scale) {
		toMeshNode(self).setTransform(toVector3d(scale));
	}
	static jlong mesh_node_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshNode(self).getMemory();
	}
	static const JNINativeMethod mesh_node_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;)J", (void*)mesh_node_new },
		{ (char*)"new_1", (char*)"(JLjava/lang/String;)J", (void*)mesh_node_new_1 },
		{ (char*)"new_2", (char*)"([JLjava/lang/String;)J", (void*)mesh_node_new_2 },
		{ (char*)"new_3", (char*)"(J[JLjava/lang/String;)J", (void*)mesh_node_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_node_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)mesh_node_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)mesh_node_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)mesh_node_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)mesh_node_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)mesh_node_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)mesh_node_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)mesh_node_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)mesh_node_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)mesh_node_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)mesh_node_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)mesh_node_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_node_clear },
		{ (char*)"clone_", (char*)"(JJ)J", (void*)mesh_node_clone },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)mesh_node_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_node_get_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)mesh_node_get_index },
		{ (char*)"set_mesh", (char*)"(JJZ)V", (void*)mesh_node_set_mesh },
		{ (char*)"get_mesh", (char*)"(J)J", (void*)mesh_node_get_mesh },
		{ (char*)"get_mesh_1", (char*)"(J)J", (void*)mesh_node_get_mesh_1 },
		{ (char*)"set_parent", (char*)"(JJZ)I", (void*)mesh_node_set_parent },
		{ (char*)"get_parent", (char*)"(J)J", (void*)mesh_node_get_parent },
		{ (char*)"get_parent_1", (char*)"(J)J", (void*)mesh_node_get_parent_1 },
		{ (char*)"is_root", (char*)"(J)Z", (void*)mesh_node_is_root },
		{ (char*)"reserve_children", (char*)"(JI)V", (void*)mesh_node_reserve_children },
		{ (char*)"add_child", (char*)"(JJZ)I", (void*)mesh_node_add_child },
		{ (char*)"remove_child", (char*)"(JJ)Z", (void*)mesh_node_remove_child },
		{ (char*)"release_children", (char*)"(J)V", (void*)mesh_node_release_children },
		{ (char*)"find_child", (char*)"(JJ)I", (void*)mesh_node_find_child },
		{ (char*)"get_num_children", (char*)"(J)I", (void*)mesh_node_get_num_children },
		{ (char*)"get_child", (char*)"(JI)J", (void*)mesh_node_get_child },
		{ (char*)"get_child_1", (char*)"(JI)J", (void*)mesh_node_get_child_1 },
		{ (char*)"clear_geometries", (char*)"(J)V", (void*)mesh_node_clear_geometries },
		{ (char*)"reserve_geometries", (char*)"(JI)V", (void*)mesh_node_reserve_geometries },
		{ (char*)"add_geometry", (char*)"(JJZ)I", (void*)mesh_node_add_geometry },
		{ (char*)"remove_geometry", (char*)"(JJ)Z", (void*)mesh_node_remove_geometry },
		{ (char*)"replace_geometry", (char*)"(JJJ)Z", (void*)mesh_node_replace_geometry },
		{ (char*)"find_geometry", (char*)"(JJ)I", (void*)mesh_node_find_geometry },
		{ (char*)"get_num_geometries", (char*)"(J)I", (void*)mesh_node_get_num_geometries },
		{ (char*)"get_geometry", (char*)"(JI)J", (void*)mesh_node_get_geometry },
		{ (char*)"get_geometry_1", (char*)"(JI)J", (void*)mesh_node_get_geometry_1 },
		{ (char*)"clear_attachments", (char*)"(J)V", (void*)mesh_node_clear_attachments },
		{ (char*)"reserve_attachments", (char*)"(JI)V", (void*)mesh_node_reserve_attachments },
		{ (char*)"add_attachment", (char*)"(JJZ)I", (void*)mesh_node_add_attachment },
		{ (char*)"remove_attachment", (char*)"(JJ)Z", (void*)mesh_node_remove_attachment },
		{ (char*)"replace_attachment", (char*)"(JJJ)Z", (void*)mesh_node_replace_attachment },
		{ (char*)"find_attachment", (char*)"(JJ)I", (void*)mesh_node_find_attachment },
		{ (char*)"find_attachment_1", (char*)"(JLjava/lang/String;)I", (void*)mesh_node_find_attachment_1 },
		{ (char*)"get_num_attachments", (char*)"(J)I", (void*)mesh_node_get_num_attachments },
		{ (char*)"get_attachment", (char*)"(JI)J", (void*)mesh_node_get_attachment },
		{ (char*)"get_attachment_1", (char*)"(JI)J", (void*)mesh_node_get_attachment_1 },
		{ (char*)"set_local_transform", (char*)"(JJ)V", (void*)mesh_node_set_local_transform },
		{ (char*)"get_local_transform", (char*)"(J)J", (void*)mesh_node_get_local_transform },
		{ (char*)"set_global_transform", (char*)"(JJ)V", (void*)mesh_node_set_global_transform },
		{ (char*)"get_global_transform", (char*)"(J)J", (void*)mesh_node_get_global_transform },
		{ (char*)"set_pivot_transform", (char*)"(JJ)V", (void*)mesh_node_set_pivot_transform },
		{ (char*)"get_pivot_transform", (char*)"(J)J", (void*)mesh_node_get_pivot_transform },
		{ (char*)"set_morph_transform", (char*)"(JJ)V", (void*)mesh_node_set_morph_transform },
		{ (char*)"get_morph_transform", (char*)"(J)J", (void*)mesh_node_get_morph_transform },
		{ (char*)"create_local_transforms", (char*)"(JJ)V", (void*)mesh_node_create_local_transforms },
		{ (char*)"create_global_transforms", (char*)"(JJ)V", (void*)mesh_node_create_global_transforms },
		{ (char*)"set_transform", (char*)"(JJ)V", (void*)mesh_node_set_transform },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_node_get_memory },
	};
	
	// Tellusim::MeshIndices
	static jlong mesh_indices_new(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshIndices(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_indices_new_1(TS_JNI_ARGS, jint type, jint format, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshIndices((MeshIndices::Type)type, (Format)format, name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_indices_new_2(TS_JNI_ARGS, jint type, jint format, jint size, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshIndices((MeshIndices::Type)type, (Format)format, (uint32_t)size, name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void mesh_indices_delete(TS_JNI_ARGS, jlong self) {
		delete (MeshIndices*)self;
	}
	static jboolean mesh_indices_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toMeshIndices(self) == toMeshIndices(ptr));
	}
	static jlong mesh_indices_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newMeshIndices(toMeshIndices(self).clonePtr());
	}
	static void mesh_indices_clear_ptr(TS_JNI_ARGS, jlong self) {
		toMeshIndices(self).clearPtr();
	}
	static void mesh_indices_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toMeshIndices(self).destroyPtr();
	}
	static void mesh_indices_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshIndices(self).acquirePtr();
	}
	static void mesh_indices_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshIndices(self).unacquirePtr();
	}
	static jboolean mesh_indices_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isValidPtr();
	}
	static jboolean mesh_indices_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isOwnerPtr();
	}
	static jboolean mesh_indices_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isConstPtr();
	}
	static jint mesh_indices_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).getCountPtr();
	}
	static jlong mesh_indices_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshIndices(self).getInternalPtr();
	}
	static void mesh_indices_clear(TS_JNI_ARGS, jlong self) {
		toMeshIndices(self).clear();
	}
	static void mesh_indices_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toMeshIndices(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring mesh_indices_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshIndices(self).getName().get());
	}
	static void mesh_indices_create(TS_JNI_ARGS, jlong self, jint type, jint format, jint size) {
		toMeshIndices(self).create((MeshIndices::Type)type, (Format)format, (uint32_t)size);
	}
	static jint mesh_indices_get_type(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).getType();
	}
	static jstring mesh_indices_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(MeshIndices::getTypeName((MeshIndices::Type)type));
	}
	static jstring mesh_indices_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshIndices(self).getTypeName());
	}
	static jboolean mesh_indices_is_unknown(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isUnknown();
	}
	static jboolean mesh_indices_is_point(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isPoint();
	}
	static jboolean mesh_indices_is_line(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isLine();
	}
	static jboolean mesh_indices_is_triangle(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isTriangle();
	}
	static jboolean mesh_indices_is_quadrilateral(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isQuadrilateral();
	}
	static jboolean mesh_indices_is_tetrahedron(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isTetrahedron();
	}
	static jboolean mesh_indices_is_primitive(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isPrimitive();
	}
	static jboolean mesh_indices_is_solid(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isSolid();
	}
	static jboolean mesh_indices_is_volume(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isVolume();
	}
	static jboolean mesh_indices_is_material(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isMaterial();
	}
	static jboolean mesh_indices_is_group(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isGroup();
	}
	static jboolean mesh_indices_is_joint(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isJoint();
	}
	static jboolean mesh_indices_is_edge(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isEdge();
	}
	static jint mesh_indices_get_primitive_size(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).getPrimitiveSize();
	}
	static jint mesh_indices_get_format(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).getFormat();
	}
	static jstring mesh_indices_get_format_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshIndices(self).getFormatName());
	}
	static void mesh_indices_set_geometry(TS_JNI_ARGS, jlong self, jlong geometry, jboolean check) {
		toMeshIndices(self).setGeometry(toMeshGeometry(geometry), (bool)check);
	}
	static jlong mesh_indices_get_geometry(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshIndices(self).getGeometry());
	}
	static jlong mesh_indices_get_geometry_1(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshIndices(self).getGeometry());
	}
	static void mesh_indices_set_size(TS_JNI_ARGS, jlong self, jint size, jboolean discard, jboolean clear) {
		toMeshIndices(self).setSize((uint32_t)size, (bool)discard, (bool)clear);
	}
	static jint mesh_indices_get_size(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).getSize();
	}
	static jint mesh_indices_get_stride(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).getStride();
	}
	static jlong mesh_indices_get_bytes(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshIndices(self).getBytes();
	}
	static void mesh_indices_set_data(TS_JNI_ARGS, jlong self, jint value, jint size, jint offset) {
		toMeshIndices(self).setData((uint32_t)value, (uint32_t)size, (uint32_t)offset);
	}
	static void mesh_indices_set_data_1(TS_JNI_ARGS, jlong self, jlong src, jint format, jint size, jint repeat) {
		toMeshIndices(self).setData((const void*)src, (Format)format, (uint32_t)size, (uint32_t)repeat);
	}
	static void mesh_indices_get_data(TS_JNI_ARGS, jlong self, jlong dest, jint format, jint size, jint repeat) {
		toMeshIndices(self).getData((void*)dest, (Format)format, (uint32_t)size, (uint32_t)repeat);
	}
	static jlong mesh_indices_get_data_1(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshIndices(self).getData();
	}
	static jlong mesh_indices_get_data_2(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshIndices(self).getData();
	}
	static void mesh_indices_set(TS_JNI_ARGS, jlong self, jint index, jint value) {
		toMeshIndices(self).set((uint32_t)index, (uint32_t)value);
	}
	static void mesh_indices_set_1(TS_JNI_ARGS, jlong self, jint index, jint value_0, jint value_1) {
		toMeshIndices(self).set((uint32_t)index, (uint32_t)value_0, (uint32_t)value_1);
	}
	static void mesh_indices_set_2(TS_JNI_ARGS, jlong self, jint index, jint value_0, jint value_1, jint value_2) {
		toMeshIndices(self).set((uint32_t)index, (uint32_t)value_0, (uint32_t)value_1, (uint32_t)value_2);
	}
	static void mesh_indices_set_3(TS_JNI_ARGS, jlong self, jint index, jint value_0, jint value_1, jint value_2, jint value_3) {
		toMeshIndices(self).set((uint32_t)index, (uint32_t)value_0, (uint32_t)value_1, (uint32_t)value_2, (uint32_t)value_3);
	}
	static jint mesh_indices_get(TS_JNI_ARGS, jlong self, jint index) {
		return toMeshIndices(self).get((uint32_t)index);
	}
	static void mesh_indices_get_1(TS_JNI_ARGS, jlong self, jint index, jintArray value_0, jintArray value_1) {
		uint32_t *value_0_ = (uint32_t*)env->GetIntArrayElements(value_0, nullptr);
		uint32_t *value_1_ = (uint32_t*)env->GetIntArrayElements(value_1, nullptr);
		toMeshIndices(self).get((uint32_t)index, value_0_[0], value_1_[0]);
		env->ReleaseIntArrayElements(value_0, (jint*)value_0_, 0);
		env->ReleaseIntArrayElements(value_1, (jint*)value_1_, 0);
	}
	static void mesh_indices_get_2(TS_JNI_ARGS, jlong self, jint index, jintArray value_0, jintArray value_1, jintArray value_2) {
		uint32_t *value_0_ = (uint32_t*)env->GetIntArrayElements(value_0, nullptr);
		uint32_t *value_1_ = (uint32_t*)env->GetIntArrayElements(value_1, nullptr);
		uint32_t *value_2_ = (uint32_t*)env->GetIntArrayElements(value_2, nullptr);
		toMeshIndices(self).get((uint32_t)index, value_0_[0], value_1_[0], value_2_[0]);
		env->ReleaseIntArrayElements(value_0, (jint*)value_0_, 0);
		env->ReleaseIntArrayElements(value_1, (jint*)value_1_, 0);
		env->ReleaseIntArrayElements(value_2, (jint*)value_2_, 0);
	}
	static void mesh_indices_get_3(TS_JNI_ARGS, jlong self, jint index, jintArray value_0, jintArray value_1, jintArray value_2, jintArray value_3) {
		uint32_t *value_0_ = (uint32_t*)env->GetIntArrayElements(value_0, nullptr);
		uint32_t *value_1_ = (uint32_t*)env->GetIntArrayElements(value_1, nullptr);
		uint32_t *value_2_ = (uint32_t*)env->GetIntArrayElements(value_2, nullptr);
		uint32_t *value_3_ = (uint32_t*)env->GetIntArrayElements(value_3, nullptr);
		toMeshIndices(self).get((uint32_t)index, value_0_[0], value_1_[0], value_2_[0], value_3_[0]);
		env->ReleaseIntArrayElements(value_0, (jint*)value_0_, 0);
		env->ReleaseIntArrayElements(value_1, (jint*)value_1_, 0);
		env->ReleaseIntArrayElements(value_2, (jint*)value_2_, 0);
		env->ReleaseIntArrayElements(value_3, (jint*)value_3_, 0);
	}
	static jlong mesh_indices_get_ptr(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toMeshIndices(self).getPtr((uint32_t)index);
	}
	static jlong mesh_indices_get_ptr_1(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toMeshIndices(self).getPtr((uint32_t)index);
	}
	static jboolean mesh_indices_is_direct(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isDirect();
	}
	static jboolean mesh_indices_is_uniform(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).isUniform();
	}
	static jint mesh_indices_get_min_index(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).getMinIndex();
	}
	static jint mesh_indices_get_max_index(TS_JNI_ARGS, jlong self) {
		return toMeshIndices(self).getMaxIndex();
	}
	static jint mesh_indices_compare(TS_JNI_ARGS, jlong self, jlong indices) {
		return toMeshIndices(self).compare(toMeshIndices(indices));
	}
	static void mesh_indices_add_indices(TS_JNI_ARGS, jlong self, jlong indices, jint offset, jboolean expand) {
		toMeshIndices(self).addIndices(toMeshIndices(indices), (uint32_t)offset, (bool)expand);
	}
	static jlong mesh_indices_to_format(TS_JNI_ARGS, jlong self, jint format) {
		return newMeshIndices(toMeshIndices(self).toFormat((Format)format));
	}
	static jlong mesh_indices_to_type(TS_JNI_ARGS, jlong self, jint type) {
		return newMeshIndices(toMeshIndices(self).toType((MeshIndices::Type)type));
	}
	static jlong mesh_indices_to_type_1(TS_JNI_ARGS, jlong self, jint type, jlong position_attribute) {
		return newMeshIndices(toMeshIndices(self).toType((MeshIndices::Type)type, toMeshAttribute(position_attribute)));
	}
	static jlong mesh_indices_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshIndices(self).getMemory();
	}
	static const JNINativeMethod mesh_indices_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;)J", (void*)mesh_indices_new },
		{ (char*)"new_1", (char*)"(IILjava/lang/String;)J", (void*)mesh_indices_new_1 },
		{ (char*)"new_2", (char*)"(IIILjava/lang/String;)J", (void*)mesh_indices_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_indices_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)mesh_indices_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)mesh_indices_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)mesh_indices_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)mesh_indices_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)mesh_indices_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)mesh_indices_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)mesh_indices_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)mesh_indices_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)mesh_indices_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)mesh_indices_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)mesh_indices_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_indices_clear },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)mesh_indices_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_indices_get_name },
		{ (char*)"create_", (char*)"(JIII)V", (void*)mesh_indices_create },
		{ (char*)"get_type", (char*)"(J)I", (void*)mesh_indices_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)mesh_indices_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)mesh_indices_get_type_name_1 },
		{ (char*)"is_unknown", (char*)"(J)Z", (void*)mesh_indices_is_unknown },
		{ (char*)"is_point", (char*)"(J)Z", (void*)mesh_indices_is_point },
		{ (char*)"is_line", (char*)"(J)Z", (void*)mesh_indices_is_line },
		{ (char*)"is_triangle", (char*)"(J)Z", (void*)mesh_indices_is_triangle },
		{ (char*)"is_quadrilateral", (char*)"(J)Z", (void*)mesh_indices_is_quadrilateral },
		{ (char*)"is_tetrahedron", (char*)"(J)Z", (void*)mesh_indices_is_tetrahedron },
		{ (char*)"is_primitive", (char*)"(J)Z", (void*)mesh_indices_is_primitive },
		{ (char*)"is_solid", (char*)"(J)Z", (void*)mesh_indices_is_solid },
		{ (char*)"is_volume", (char*)"(J)Z", (void*)mesh_indices_is_volume },
		{ (char*)"is_material", (char*)"(J)Z", (void*)mesh_indices_is_material },
		{ (char*)"is_group", (char*)"(J)Z", (void*)mesh_indices_is_group },
		{ (char*)"is_joint", (char*)"(J)Z", (void*)mesh_indices_is_joint },
		{ (char*)"is_edge", (char*)"(J)Z", (void*)mesh_indices_is_edge },
		{ (char*)"get_primitive_size", (char*)"(J)I", (void*)mesh_indices_get_primitive_size },
		{ (char*)"get_format", (char*)"(J)I", (void*)mesh_indices_get_format },
		{ (char*)"get_format_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_indices_get_format_name },
		{ (char*)"set_geometry", (char*)"(JJZ)V", (void*)mesh_indices_set_geometry },
		{ (char*)"get_geometry", (char*)"(J)J", (void*)mesh_indices_get_geometry },
		{ (char*)"get_geometry_1", (char*)"(J)J", (void*)mesh_indices_get_geometry_1 },
		{ (char*)"set_size", (char*)"(JIZZ)V", (void*)mesh_indices_set_size },
		{ (char*)"get_size", (char*)"(J)I", (void*)mesh_indices_get_size },
		{ (char*)"get_stride", (char*)"(J)I", (void*)mesh_indices_get_stride },
		{ (char*)"get_bytes", (char*)"(J)J", (void*)mesh_indices_get_bytes },
		{ (char*)"set_data", (char*)"(JIII)V", (void*)mesh_indices_set_data },
		{ (char*)"set_data_1", (char*)"(JJIII)V", (void*)mesh_indices_set_data_1 },
		{ (char*)"get_data", (char*)"(JJIII)V", (void*)mesh_indices_get_data },
		{ (char*)"get_data_1", (char*)"(J)J", (void*)mesh_indices_get_data_1 },
		{ (char*)"get_data_2", (char*)"(J)J", (void*)mesh_indices_get_data_2 },
		{ (char*)"set_", (char*)"(JII)V", (void*)mesh_indices_set },
		{ (char*)"set_1", (char*)"(JIII)V", (void*)mesh_indices_set_1 },
		{ (char*)"set_2", (char*)"(JIIII)V", (void*)mesh_indices_set_2 },
		{ (char*)"set_3", (char*)"(JIIIII)V", (void*)mesh_indices_set_3 },
		{ (char*)"get_", (char*)"(JI)I", (void*)mesh_indices_get },
		{ (char*)"get_1", (char*)"(JI[I[I)V", (void*)mesh_indices_get_1 },
		{ (char*)"get_2", (char*)"(JI[I[I[I)V", (void*)mesh_indices_get_2 },
		{ (char*)"get_3", (char*)"(JI[I[I[I[I)V", (void*)mesh_indices_get_3 },
		{ (char*)"get_ptr", (char*)"(JI)J", (void*)mesh_indices_get_ptr },
		{ (char*)"get_ptr_1", (char*)"(JI)J", (void*)mesh_indices_get_ptr_1 },
		{ (char*)"is_direct", (char*)"(J)Z", (void*)mesh_indices_is_direct },
		{ (char*)"is_uniform", (char*)"(J)Z", (void*)mesh_indices_is_uniform },
		{ (char*)"get_min_index", (char*)"(J)I", (void*)mesh_indices_get_min_index },
		{ (char*)"get_max_index", (char*)"(J)I", (void*)mesh_indices_get_max_index },
		{ (char*)"compare_", (char*)"(JJ)I", (void*)mesh_indices_compare },
		{ (char*)"add_indices", (char*)"(JJIZ)V", (void*)mesh_indices_add_indices },
		{ (char*)"to_format", (char*)"(JI)J", (void*)mesh_indices_to_format },
		{ (char*)"to_type", (char*)"(JI)J", (void*)mesh_indices_to_type },
		{ (char*)"to_type_1", (char*)"(JIJ)J", (void*)mesh_indices_to_type_1 },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_indices_get_memory },
	};
	
	// Tellusim::MeshAttribute
	static jlong mesh_attribute_new(TS_JNI_ARGS, jstring name, jint index) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshAttribute(name_, (uint32_t)index);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_attribute_new_1(TS_JNI_ARGS, jint type, jint format, jstring name, jint index) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshAttribute((MeshAttribute::Type)type, (Format)format, name_, (uint32_t)index);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_attribute_new_2(TS_JNI_ARGS, jint type, jint format, jint size, jstring name, jint index) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshAttribute((MeshAttribute::Type)type, (Format)format, (uint32_t)size, name_, (uint32_t)index);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_attribute_new_3(TS_JNI_ARGS, jint type, jint format, jint size, jint index) {
		return newMeshAttribute((MeshAttribute::Type)type, (Format)format, (uint32_t)size, (uint32_t)index);
	}
	static void mesh_attribute_delete(TS_JNI_ARGS, jlong self) {
		delete (MeshAttribute*)self;
	}
	static jboolean mesh_attribute_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toMeshAttribute(self) == toMeshAttribute(ptr));
	}
	static jlong mesh_attribute_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newMeshAttribute(toMeshAttribute(self).clonePtr());
	}
	static void mesh_attribute_clear_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAttribute(self).clearPtr();
	}
	static void mesh_attribute_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAttribute(self).destroyPtr();
	}
	static void mesh_attribute_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAttribute(self).acquirePtr();
	}
	static void mesh_attribute_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAttribute(self).unacquirePtr();
	}
	static jboolean mesh_attribute_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isValidPtr();
	}
	static jboolean mesh_attribute_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isOwnerPtr();
	}
	static jboolean mesh_attribute_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isConstPtr();
	}
	static jint mesh_attribute_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).getCountPtr();
	}
	static jlong mesh_attribute_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshAttribute(self).getInternalPtr();
	}
	static void mesh_attribute_clear(TS_JNI_ARGS, jlong self) {
		toMeshAttribute(self).clear();
	}
	static void mesh_attribute_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toMeshAttribute(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring mesh_attribute_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshAttribute(self).getName().get());
	}
	static void mesh_attribute_create(TS_JNI_ARGS, jlong self, jint type, jint format, jint size) {
		toMeshAttribute(self).create((MeshAttribute::Type)type, (Format)format, (uint32_t)size);
	}
	static jint mesh_attribute_get_type(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).getType();
	}
	static jstring mesh_attribute_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(MeshAttribute::getTypeName((MeshAttribute::Type)type));
	}
	static jstring mesh_attribute_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshAttribute(self).getTypeName());
	}
	static jboolean mesh_attribute_is_unknown(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isUnknown();
	}
	static jboolean mesh_attribute_is_position(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isPosition();
	}
	static jboolean mesh_attribute_is_basis(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isBasis();
	}
	static jboolean mesh_attribute_is_normal(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isNormal();
	}
	static jboolean mesh_attribute_is_tangent(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isTangent();
	}
	static jboolean mesh_attribute_is_binormal(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isBinormal();
	}
	static jboolean mesh_attribute_is_spatial(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isSpatial();
	}
	static jboolean mesh_attribute_is_normalized(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isNormalized();
	}
	static jboolean mesh_attribute_is_tex_coord(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isTexCoord();
	}
	static jboolean mesh_attribute_is_weights(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isWeights();
	}
	static jboolean mesh_attribute_is_joints(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isJoints();
	}
	static jboolean mesh_attribute_is_color(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isColor();
	}
	static jboolean mesh_attribute_is_vertex(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isVertex();
	}
	static jboolean mesh_attribute_is_crease(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isCrease();
	}
	static jint mesh_attribute_get_format(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).getFormat();
	}
	static jstring mesh_attribute_get_format_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshAttribute(self).getFormatName());
	}
	static jint mesh_attribute_get_components(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).getComponents();
	}
	static jboolean mesh_attribute_is_packed(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).isPacked();
	}
	static void mesh_attribute_set_index(TS_JNI_ARGS, jlong self, jint index) {
		toMeshAttribute(self).setIndex((uint32_t)index);
	}
	static jint mesh_attribute_get_index(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).getIndex();
	}
	static void mesh_attribute_set_indices(TS_JNI_ARGS, jlong self, jlong indices) {
		toMeshAttribute(self).setIndices(toMeshIndices(indices));
	}
	static jlong mesh_attribute_get_indices(TS_JNI_ARGS, jlong self) {
		return newMeshIndices(toMeshAttribute(self).getIndices());
	}
	static jlong mesh_attribute_get_indices_1(TS_JNI_ARGS, jlong self) {
		return newMeshIndices(toMeshAttribute(self).getIndices());
	}
	static void mesh_attribute_set_geometry(TS_JNI_ARGS, jlong self, jlong geometry, jboolean check) {
		toMeshAttribute(self).setGeometry(toMeshGeometry(geometry), (bool)check);
	}
	static jlong mesh_attribute_get_geometry(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshAttribute(self).getGeometry());
	}
	static jlong mesh_attribute_get_geometry_1(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshAttribute(self).getGeometry());
	}
	static void mesh_attribute_set_size(TS_JNI_ARGS, jlong self, jint size, jboolean discard, jboolean clear) {
		toMeshAttribute(self).setSize((uint32_t)size, (bool)discard, (bool)clear);
	}
	static jint mesh_attribute_get_size(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).getSize();
	}
	static jint mesh_attribute_get_stride(TS_JNI_ARGS, jlong self) {
		return toMeshAttribute(self).getStride();
	}
	static jlong mesh_attribute_get_bytes(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshAttribute(self).getBytes();
	}
	static void mesh_attribute_set_data(TS_JNI_ARGS, jlong self, jlong src, jint size, jint stride) {
		toMeshAttribute(self).setData((const void*)src, (uint32_t)size, (uint32_t)stride);
	}
	static void mesh_attribute_set_data_1(TS_JNI_ARGS, jlong self, jlong src, jintArray indices, jint stride) {
		uint32_t *indices__ = (uint32_t*)env->GetIntArrayElements(indices, nullptr);
		Array<uint32_t> indices_((uint32_t)env->GetArrayLength(indices), indices__);
		toMeshAttribute(self).setData((const void*)src, indices_, (uint32_t)stride);
		if(indices_) env->ReleaseIntArrayElements(indices, (jint*)indices__, 0);
	}
	static void mesh_attribute_get_data(TS_JNI_ARGS, jlong self, jlong dest, jint size, jint stride) {
		toMeshAttribute(self).getData((void*)dest, (uint32_t)size, (uint32_t)stride);
	}
	static void mesh_attribute_get_data_1(TS_JNI_ARGS, jlong self, jlong dest, jlong indices, jint stride) {
		toMeshAttribute(self).getData((void*)dest, toMeshIndices(indices), (uint32_t)stride);
	}
	static void mesh_attribute_get_data_2(TS_JNI_ARGS, jlong self, jlong dest, jintArray indices, jint stride) {
		uint32_t *indices__ = (uint32_t*)env->GetIntArrayElements(indices, nullptr);
		Array<uint32_t> indices_((uint32_t)env->GetArrayLength(indices), indices__);
		toMeshAttribute(self).getData((void*)dest, indices_, (uint32_t)stride);
		if(indices_) env->ReleaseIntArrayElements(indices, (jint*)indices__, 0);
	}
	static jlong mesh_attribute_get_data_3(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshAttribute(self).getData();
	}
	static jlong mesh_attribute_get_data_4(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshAttribute(self).getData();
	}
	static void mesh_attribute_set_value(TS_JNI_ARGS, jlong self, jint index, jbyteArray src) {
		toMeshAttribute(self).setValue((uint32_t)index, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static void mesh_attribute_get_value(TS_JNI_ARGS, jlong self, jint index, jbyteArray dest) {
		toMeshAttribute(self).getValue((uint32_t)index, ByteArray(env, dest).get(), env->GetArrayLength(dest));
	}
	static jlong mesh_attribute_get_ptr(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toMeshAttribute(self).getPtr((uint32_t)index);
	}
	static jlong mesh_attribute_get_ptr_1(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toMeshAttribute(self).getPtr((uint32_t)index);
	}
	static jint mesh_attribute_compare(TS_JNI_ARGS, jlong self, jlong attribute, jlong transform, jfloat threshold, jboolean spatial) {
		return toMeshAttribute(self).compare(toMeshAttribute(attribute), toMatrix4x3f(transform), threshold, (bool)spatial);
	}
	static void mesh_attribute_add_attribute(TS_JNI_ARGS, jlong self, jlong attribute) {
		toMeshAttribute(self).addAttribute(toMeshAttribute(attribute));
	}
	static jboolean mesh_attribute_set_transform(TS_JNI_ARGS, jlong self, jlong transform) {
		return toMeshAttribute(self).setTransform(toMatrix4x3f(transform));
	}
	static jboolean mesh_attribute_morph_attribute(TS_JNI_ARGS, jlong self, jlong attribute, jfloat k) {
		return toMeshAttribute(self).morphAttribute(toMeshAttribute(attribute), k);
	}
	static jboolean mesh_attribute_pack_attributes(TS_JNI_ARGS, jlong self, jlong attribute_0, jlong attribute_1, jint format) {
		return toMeshAttribute(self).packAttributes(toMeshAttribute(attribute_0), toMeshAttribute(attribute_1), (Format)format);
	}
	static jboolean mesh_attribute_unpack_attributes(TS_JNI_ARGS, jlong self, jlong attribute_0, jlong attribute_1) {
		return toMeshAttribute(self).unpackAttributes(toMeshAttribute(attribute_0), toMeshAttribute(attribute_1));
	}
	static jlong mesh_attribute_optimize_attribute(TS_JNI_ARGS, jlong self, jlong indices) {
		return newMeshAttribute(toMeshAttribute(self).optimizeAttribute(toMeshIndices(indices)));
	}
	static jlong mesh_attribute_to_direct(TS_JNI_ARGS, jlong self, jlong indices) {
		return newMeshAttribute(toMeshAttribute(self).toDirect(toMeshIndices(indices)));
	}
	static jlong mesh_attribute_to_format(TS_JNI_ARGS, jlong self, jint format) {
		return newMeshAttribute(toMeshAttribute(self).toFormat((Format)format));
	}
	static jlong mesh_attribute_to_type(TS_JNI_ARGS, jlong self, jint type) {
		return newMeshAttribute(toMeshAttribute(self).toType((MeshAttribute::Type)type));
	}
	static jlong mesh_attribute_get_covariance_matrix(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3f(toMeshAttribute(self).getCovarianceMatrix());
	}
	static jlong mesh_attribute_get_min_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3f(toMeshAttribute(self).getMinTransform());
	}
	static jlong mesh_attribute_get_bound_box(TS_JNI_ARGS, jlong self) {
		return newBoundBoxf(toMeshAttribute(self).getBoundBox());
	}
	static jlong mesh_attribute_get_bound_sphere(TS_JNI_ARGS, jlong self) {
		return newBoundSpheref(toMeshAttribute(self).getBoundSphere());
	}
	static jlong mesh_attribute_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshAttribute(self).getMemory();
	}
	static const JNINativeMethod mesh_attribute_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;I)J", (void*)mesh_attribute_new },
		{ (char*)"new_1", (char*)"(IILjava/lang/String;I)J", (void*)mesh_attribute_new_1 },
		{ (char*)"new_2", (char*)"(IIILjava/lang/String;I)J", (void*)mesh_attribute_new_2 },
		{ (char*)"new_3", (char*)"(IIII)J", (void*)mesh_attribute_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_attribute_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)mesh_attribute_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)mesh_attribute_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)mesh_attribute_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)mesh_attribute_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)mesh_attribute_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)mesh_attribute_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)mesh_attribute_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)mesh_attribute_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)mesh_attribute_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)mesh_attribute_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)mesh_attribute_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_attribute_clear },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)mesh_attribute_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_attribute_get_name },
		{ (char*)"create_", (char*)"(JIII)V", (void*)mesh_attribute_create },
		{ (char*)"get_type", (char*)"(J)I", (void*)mesh_attribute_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)mesh_attribute_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)mesh_attribute_get_type_name_1 },
		{ (char*)"is_unknown", (char*)"(J)Z", (void*)mesh_attribute_is_unknown },
		{ (char*)"is_position", (char*)"(J)Z", (void*)mesh_attribute_is_position },
		{ (char*)"is_basis", (char*)"(J)Z", (void*)mesh_attribute_is_basis },
		{ (char*)"is_normal", (char*)"(J)Z", (void*)mesh_attribute_is_normal },
		{ (char*)"is_tangent", (char*)"(J)Z", (void*)mesh_attribute_is_tangent },
		{ (char*)"is_binormal", (char*)"(J)Z", (void*)mesh_attribute_is_binormal },
		{ (char*)"is_spatial", (char*)"(J)Z", (void*)mesh_attribute_is_spatial },
		{ (char*)"is_normalized", (char*)"(J)Z", (void*)mesh_attribute_is_normalized },
		{ (char*)"is_tex_coord", (char*)"(J)Z", (void*)mesh_attribute_is_tex_coord },
		{ (char*)"is_weights", (char*)"(J)Z", (void*)mesh_attribute_is_weights },
		{ (char*)"is_joints", (char*)"(J)Z", (void*)mesh_attribute_is_joints },
		{ (char*)"is_color", (char*)"(J)Z", (void*)mesh_attribute_is_color },
		{ (char*)"is_vertex", (char*)"(J)Z", (void*)mesh_attribute_is_vertex },
		{ (char*)"is_crease", (char*)"(J)Z", (void*)mesh_attribute_is_crease },
		{ (char*)"get_format", (char*)"(J)I", (void*)mesh_attribute_get_format },
		{ (char*)"get_format_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_attribute_get_format_name },
		{ (char*)"get_components", (char*)"(J)I", (void*)mesh_attribute_get_components },
		{ (char*)"is_packed", (char*)"(J)Z", (void*)mesh_attribute_is_packed },
		{ (char*)"set_index", (char*)"(JI)V", (void*)mesh_attribute_set_index },
		{ (char*)"get_index", (char*)"(J)I", (void*)mesh_attribute_get_index },
		{ (char*)"set_indices", (char*)"(JJ)V", (void*)mesh_attribute_set_indices },
		{ (char*)"get_indices", (char*)"(J)J", (void*)mesh_attribute_get_indices },
		{ (char*)"get_indices_1", (char*)"(J)J", (void*)mesh_attribute_get_indices_1 },
		{ (char*)"set_geometry", (char*)"(JJZ)V", (void*)mesh_attribute_set_geometry },
		{ (char*)"get_geometry", (char*)"(J)J", (void*)mesh_attribute_get_geometry },
		{ (char*)"get_geometry_1", (char*)"(J)J", (void*)mesh_attribute_get_geometry_1 },
		{ (char*)"set_size", (char*)"(JIZZ)V", (void*)mesh_attribute_set_size },
		{ (char*)"get_size", (char*)"(J)I", (void*)mesh_attribute_get_size },
		{ (char*)"get_stride", (char*)"(J)I", (void*)mesh_attribute_get_stride },
		{ (char*)"get_bytes", (char*)"(J)J", (void*)mesh_attribute_get_bytes },
		{ (char*)"set_data", (char*)"(JJII)V", (void*)mesh_attribute_set_data },
		{ (char*)"set_data_1", (char*)"(JJ[II)V", (void*)mesh_attribute_set_data_1 },
		{ (char*)"get_data", (char*)"(JJII)V", (void*)mesh_attribute_get_data },
		{ (char*)"get_data_1", (char*)"(JJJI)V", (void*)mesh_attribute_get_data_1 },
		{ (char*)"get_data_2", (char*)"(JJ[II)V", (void*)mesh_attribute_get_data_2 },
		{ (char*)"get_data_3", (char*)"(J)J", (void*)mesh_attribute_get_data_3 },
		{ (char*)"get_data_4", (char*)"(J)J", (void*)mesh_attribute_get_data_4 },
		{ (char*)"set_value", (char*)"(JI[B)V", (void*)mesh_attribute_set_value },
		{ (char*)"get_value", (char*)"(JI[B)V", (void*)mesh_attribute_get_value },
		{ (char*)"get_ptr", (char*)"(JI)J", (void*)mesh_attribute_get_ptr },
		{ (char*)"get_ptr_1", (char*)"(JI)J", (void*)mesh_attribute_get_ptr_1 },
		{ (char*)"compare_", (char*)"(JJJFZ)I", (void*)mesh_attribute_compare },
		{ (char*)"add_attribute", (char*)"(JJ)V", (void*)mesh_attribute_add_attribute },
		{ (char*)"set_transform", (char*)"(JJ)Z", (void*)mesh_attribute_set_transform },
		{ (char*)"morph_attribute", (char*)"(JJF)Z", (void*)mesh_attribute_morph_attribute },
		{ (char*)"pack_attributes", (char*)"(JJJI)Z", (void*)mesh_attribute_pack_attributes },
		{ (char*)"unpack_attributes", (char*)"(JJJ)Z", (void*)mesh_attribute_unpack_attributes },
		{ (char*)"optimize_attribute", (char*)"(JJ)J", (void*)mesh_attribute_optimize_attribute },
		{ (char*)"to_direct", (char*)"(JJ)J", (void*)mesh_attribute_to_direct },
		{ (char*)"to_format", (char*)"(JI)J", (void*)mesh_attribute_to_format },
		{ (char*)"to_type", (char*)"(JI)J", (void*)mesh_attribute_to_type },
		{ (char*)"get_covariance_matrix", (char*)"(J)J", (void*)mesh_attribute_get_covariance_matrix },
		{ (char*)"get_min_transform", (char*)"(J)J", (void*)mesh_attribute_get_min_transform },
		{ (char*)"get_bound_box", (char*)"(J)J", (void*)mesh_attribute_get_bound_box },
		{ (char*)"get_bound_sphere", (char*)"(J)J", (void*)mesh_attribute_get_bound_sphere },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_attribute_get_memory },
	};
	
	// Tellusim::MeshJoint
	static jlong mesh_joint_new(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshJoint(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_joint_new_1(TS_JNI_ARGS, jlong geometry, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshJoint(toMeshGeometry(geometry), name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void mesh_joint_delete(TS_JNI_ARGS, jlong self) {
		delete (MeshJoint*)self;
	}
	static jboolean mesh_joint_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toMeshJoint(self) == toMeshJoint(ptr));
	}
	static jlong mesh_joint_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newMeshJoint(toMeshJoint(self).clonePtr());
	}
	static void mesh_joint_clear_ptr(TS_JNI_ARGS, jlong self) {
		toMeshJoint(self).clearPtr();
	}
	static void mesh_joint_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toMeshJoint(self).destroyPtr();
	}
	static void mesh_joint_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshJoint(self).acquirePtr();
	}
	static void mesh_joint_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshJoint(self).unacquirePtr();
	}
	static jboolean mesh_joint_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshJoint(self).isValidPtr();
	}
	static jboolean mesh_joint_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshJoint(self).isOwnerPtr();
	}
	static jboolean mesh_joint_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshJoint(self).isConstPtr();
	}
	static jint mesh_joint_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshJoint(self).getCountPtr();
	}
	static jlong mesh_joint_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshJoint(self).getInternalPtr();
	}
	static void mesh_joint_clear(TS_JNI_ARGS, jlong self) {
		toMeshJoint(self).clear();
	}
	static void mesh_joint_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toMeshJoint(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring mesh_joint_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshJoint(self).getName().get());
	}
	static void mesh_joint_set_node(TS_JNI_ARGS, jlong self, jlong node) {
		toMeshJoint(self).setNode(toMeshNode(node));
	}
	static jlong mesh_joint_get_node(TS_JNI_ARGS, jlong self) {
		return newMeshNode(toMeshJoint(self).getNode());
	}
	static jlong mesh_joint_get_node_1(TS_JNI_ARGS, jlong self) {
		return newMeshNode(toMeshJoint(self).getNode());
	}
	static jint mesh_joint_get_node_index(TS_JNI_ARGS, jlong self) {
		return toMeshJoint(self).getNodeIndex();
	}
	static jlong mesh_joint_get_local_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3d(toMeshJoint(self).getLocalTransform());
	}
	static jlong mesh_joint_get_global_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3d(toMeshJoint(self).getGlobalTransform());
	}
	static void mesh_joint_set_indices(TS_JNI_ARGS, jlong self, jlong indices) {
		toMeshJoint(self).setIndices(toMeshIndices(indices));
	}
	static jlong mesh_joint_get_indices(TS_JNI_ARGS, jlong self) {
		return newMeshIndices(toMeshJoint(self).getIndices());
	}
	static jlong mesh_joint_get_indices_1(TS_JNI_ARGS, jlong self) {
		return newMeshIndices(toMeshJoint(self).getIndices());
	}
	static void mesh_joint_set_geometry(TS_JNI_ARGS, jlong self, jlong geometry, jboolean check) {
		toMeshJoint(self).setGeometry(toMeshGeometry(geometry), (bool)check);
	}
	static jlong mesh_joint_get_geometry(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshJoint(self).getGeometry());
	}
	static jlong mesh_joint_get_geometry_1(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshJoint(self).getGeometry());
	}
	static void mesh_joint_set_bound_box(TS_JNI_ARGS, jlong self, jlong box) {
		toMeshJoint(self).setBoundBox(toBoundBoxf(box));
	}
	static jlong mesh_joint_get_bound_box(TS_JNI_ARGS, jlong self) {
		return newBoundBoxf(toMeshJoint(self).getBoundBox());
	}
	static void mesh_joint_set_bound_sphere(TS_JNI_ARGS, jlong self, jlong sphere) {
		toMeshJoint(self).setBoundSphere(toBoundSpheref(sphere));
	}
	static jlong mesh_joint_get_bound_sphere(TS_JNI_ARGS, jlong self) {
		return newBoundSpheref(toMeshJoint(self).getBoundSphere());
	}
	static void mesh_joint_set_itransform(TS_JNI_ARGS, jlong self, jlong itransform) {
		toMeshJoint(self).setITransform(toMatrix4x3f(itransform));
	}
	static jlong mesh_joint_get_itransform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3f(toMeshJoint(self).getITransform());
	}
	static jint mesh_joint_compare(TS_JNI_ARGS, jlong self, jlong joint) {
		return toMeshJoint(self).compare(toMeshJoint(joint));
	}
	static jlong mesh_joint_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshJoint(self).getMemory();
	}
	static const JNINativeMethod mesh_joint_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;)J", (void*)mesh_joint_new },
		{ (char*)"new_1", (char*)"(JLjava/lang/String;)J", (void*)mesh_joint_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_joint_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)mesh_joint_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)mesh_joint_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)mesh_joint_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)mesh_joint_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)mesh_joint_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)mesh_joint_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)mesh_joint_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)mesh_joint_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)mesh_joint_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)mesh_joint_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)mesh_joint_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_joint_clear },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)mesh_joint_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_joint_get_name },
		{ (char*)"set_node", (char*)"(JJ)V", (void*)mesh_joint_set_node },
		{ (char*)"get_node", (char*)"(J)J", (void*)mesh_joint_get_node },
		{ (char*)"get_node_1", (char*)"(J)J", (void*)mesh_joint_get_node_1 },
		{ (char*)"get_node_index", (char*)"(J)I", (void*)mesh_joint_get_node_index },
		{ (char*)"get_local_transform", (char*)"(J)J", (void*)mesh_joint_get_local_transform },
		{ (char*)"get_global_transform", (char*)"(J)J", (void*)mesh_joint_get_global_transform },
		{ (char*)"set_indices", (char*)"(JJ)V", (void*)mesh_joint_set_indices },
		{ (char*)"get_indices", (char*)"(J)J", (void*)mesh_joint_get_indices },
		{ (char*)"get_indices_1", (char*)"(J)J", (void*)mesh_joint_get_indices_1 },
		{ (char*)"set_geometry", (char*)"(JJZ)V", (void*)mesh_joint_set_geometry },
		{ (char*)"get_geometry", (char*)"(J)J", (void*)mesh_joint_get_geometry },
		{ (char*)"get_geometry_1", (char*)"(J)J", (void*)mesh_joint_get_geometry_1 },
		{ (char*)"set_bound_box", (char*)"(JJ)V", (void*)mesh_joint_set_bound_box },
		{ (char*)"get_bound_box", (char*)"(J)J", (void*)mesh_joint_get_bound_box },
		{ (char*)"set_bound_sphere", (char*)"(JJ)V", (void*)mesh_joint_set_bound_sphere },
		{ (char*)"get_bound_sphere", (char*)"(J)J", (void*)mesh_joint_get_bound_sphere },
		{ (char*)"set_itransform", (char*)"(JJ)V", (void*)mesh_joint_set_itransform },
		{ (char*)"get_itransform", (char*)"(J)J", (void*)mesh_joint_get_itransform },
		{ (char*)"compare_", (char*)"(JJ)I", (void*)mesh_joint_compare },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_joint_get_memory },
	};
	
	// Tellusim::MeshMaterial
	static jlong mesh_material_new(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshMaterial(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_material_new_1(TS_JNI_ARGS, jlong geometry, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshMaterial(toMeshGeometry(geometry), name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void mesh_material_delete(TS_JNI_ARGS, jlong self) {
		delete (MeshMaterial*)self;
	}
	static jboolean mesh_material_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toMeshMaterial(self) == toMeshMaterial(ptr));
	}
	static jlong mesh_material_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newMeshMaterial(toMeshMaterial(self).clonePtr());
	}
	static void mesh_material_clear_ptr(TS_JNI_ARGS, jlong self) {
		toMeshMaterial(self).clearPtr();
	}
	static void mesh_material_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toMeshMaterial(self).destroyPtr();
	}
	static void mesh_material_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshMaterial(self).acquirePtr();
	}
	static void mesh_material_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshMaterial(self).unacquirePtr();
	}
	static jboolean mesh_material_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshMaterial(self).isValidPtr();
	}
	static jboolean mesh_material_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshMaterial(self).isOwnerPtr();
	}
	static jboolean mesh_material_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshMaterial(self).isConstPtr();
	}
	static jint mesh_material_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshMaterial(self).getCountPtr();
	}
	static jlong mesh_material_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshMaterial(self).getInternalPtr();
	}
	static void mesh_material_clear(TS_JNI_ARGS, jlong self) {
		toMeshMaterial(self).clear();
	}
	static void mesh_material_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toMeshMaterial(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring mesh_material_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshMaterial(self).getName().get());
	}
	static jint mesh_material_get_index(TS_JNI_ARGS, jlong self) {
		return toMeshMaterial(self).getIndex();
	}
	static void mesh_material_set_indices(TS_JNI_ARGS, jlong self, jlong indices) {
		toMeshMaterial(self).setIndices(toMeshIndices(indices));
	}
	static jlong mesh_material_get_indices(TS_JNI_ARGS, jlong self) {
		return newMeshIndices(toMeshMaterial(self).getIndices());
	}
	static jlong mesh_material_get_indices_1(TS_JNI_ARGS, jlong self) {
		return newMeshIndices(toMeshMaterial(self).getIndices());
	}
	static void mesh_material_set_geometry(TS_JNI_ARGS, jlong self, jlong geometry, jboolean check) {
		toMeshMaterial(self).setGeometry(toMeshGeometry(geometry), (bool)check);
	}
	static jlong mesh_material_get_geometry(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshMaterial(self).getGeometry());
	}
	static jlong mesh_material_get_geometry_1(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshMaterial(self).getGeometry());
	}
	static void mesh_material_set_data(TS_JNI_ARGS, jlong self, jstring data) {
		const char *data_ = (data) ? env->GetStringUTFChars(data, nullptr) : nullptr;
		toMeshMaterial(self).setData(data_);
		env->ReleaseStringUTFChars(data, data_);
	}
	static void mesh_material_set_data_1(TS_JNI_ARGS, jlong self, jlong data) {
		toMeshMaterial(self).setData(toString(data));
	}
	static jstring mesh_material_get_data(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshMaterial(self).getData().get());
	}
	static void mesh_material_clear_parameters(TS_JNI_ARGS, jlong self) {
		toMeshMaterial(self).clearParameters();
	}
	static jboolean mesh_material_remove_parameter(TS_JNI_ARGS, jlong self, jstring type) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toMeshMaterial(self).removeParameter(type_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static void mesh_material_copy_parameters(TS_JNI_ARGS, jlong self, jlong material) {
		toMeshMaterial(self).copyParameters(toMeshMaterial(material));
	}
	static jint mesh_material_find_parameter(TS_JNI_ARGS, jlong self, jstring type) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		uint32_t ret_ = toMeshMaterial(self).findParameter(type_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jboolean mesh_material_has_parameter(TS_JNI_ARGS, jlong self, jstring type) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toMeshMaterial(self).hasParameter(type_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jint mesh_material_get_num_parameters(TS_JNI_ARGS, jlong self) {
		return toMeshMaterial(self).getNumParameters();
	}
	static jstring mesh_material_get_parameter_type(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toMeshMaterial(self).getParameterType((uint32_t)index).get());
	}
	static void mesh_material_add_parameter(TS_JNI_ARGS, jlong self, jstring type, jboolean value) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		toMeshMaterial(self).addParameter(type_, (bool)value);
		env->ReleaseStringUTFChars(type, type_);
	}
	static void mesh_material_add_parameter_1(TS_JNI_ARGS, jlong self, jstring type, jfloat value) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		toMeshMaterial(self).addParameter(type_, value);
		env->ReleaseStringUTFChars(type, type_);
	}
	static void mesh_material_add_parameter_2(TS_JNI_ARGS, jlong self, jstring type, jlong value) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		toMeshMaterial(self).addParameter(type_, toVector4f(value));
		env->ReleaseStringUTFChars(type, type_);
	}
	static void mesh_material_add_parameter_3(TS_JNI_ARGS, jlong self, jstring type, jlong value) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		toMeshMaterial(self).addParameter(type_, toMatrix3x2f(value));
		env->ReleaseStringUTFChars(type, type_);
	}
	static void mesh_material_add_parameter_4(TS_JNI_ARGS, jlong self, jstring type, jlong color) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		toMeshMaterial(self).addParameter(type_, toColor(color));
		env->ReleaseStringUTFChars(type, type_);
	}
	static void mesh_material_add_parameter_5(TS_JNI_ARGS, jlong self, jstring type, jstring name, jstring layout) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *layout_ = (layout) ? env->GetStringUTFChars(layout, nullptr) : nullptr;
		toMeshMaterial(self).addParameter(type_, name_, layout_);
		env->ReleaseStringUTFChars(type, type_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(layout, layout_);
	}
	static void mesh_material_add_parameter_6(TS_JNI_ARGS, jlong self, jstring type, jlong name, jstring layout) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		const char *layout_ = (layout) ? env->GetStringUTFChars(layout, nullptr) : nullptr;
		toMeshMaterial(self).addParameter(type_, toString(name), layout_);
		env->ReleaseStringUTFChars(type, type_);
		env->ReleaseStringUTFChars(layout, layout_);
	}
	static void mesh_material_add_parameter_7(TS_JNI_ARGS, jlong self, jstring type, jlong image, jstring layout) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		const char *layout_ = (layout) ? env->GetStringUTFChars(layout, nullptr) : nullptr;
		toMeshMaterial(self).addParameter(type_, toImage(image), layout_);
		env->ReleaseStringUTFChars(type, type_);
		env->ReleaseStringUTFChars(layout, layout_);
	}
	static void mesh_material_add_parameter_8(TS_JNI_ARGS, jlong self, jstring type, jlong blob, jstring layout) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		const char *layout_ = (layout) ? env->GetStringUTFChars(layout, nullptr) : nullptr;
		toMeshMaterial(self).addParameter(type_, toBlob(blob), layout_);
		env->ReleaseStringUTFChars(type, type_);
		env->ReleaseStringUTFChars(layout, layout_);
	}
	static jint mesh_material_get_parameter_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toMeshMaterial(self).getParameterFlags((uint32_t)index);
	}
	static jboolean mesh_material_has_parameter_flag(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return toMeshMaterial(self).hasParameterFlag((uint32_t)index, (MeshMaterial::Flags)flags);
	}
	static jboolean mesh_material_has_parameter_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return toMeshMaterial(self).hasParameterFlags((uint32_t)index, (MeshMaterial::Flags)flags);
	}
	static jboolean mesh_material_get_parameter_bool(TS_JNI_ARGS, jlong self, jint index, jboolean value) {
		return toMeshMaterial(self).getParameterBool((uint32_t)index, (bool)value);
	}
	static jfloat mesh_material_get_parameter_scalarf32(TS_JNI_ARGS, jlong self, jint index, jfloat value) {
		return toMeshMaterial(self).getParameterScalarf32((uint32_t)index, value);
	}
	static jlong mesh_material_get_parameter_vector4f(TS_JNI_ARGS, jlong self, jint index, jlong vector) {
		return newVector4f(toMeshMaterial(self).getParameterVector4f((uint32_t)index, toVector4f(vector)));
	}
	static jlong mesh_material_get_parameter_matrix3x2f(TS_JNI_ARGS, jlong self, jint index, jlong matrix) {
		return newMatrix3x2f(toMeshMaterial(self).getParameterMatrix3x2f((uint32_t)index, toMatrix3x2f(matrix)));
	}
	static jlong mesh_material_get_parameter_color(TS_JNI_ARGS, jlong self, jint index, jlong color) {
		return newColor(toMeshMaterial(self).getParameterColor((uint32_t)index, toColor(color)));
	}
	static jstring mesh_material_get_parameter_name(TS_JNI_ARGS, jlong self, jint index, jlong name) {
		return env->NewStringUTF(toMeshMaterial(self).getParameterName((uint32_t)index, toString(name)).get());
	}
	static jstring mesh_material_get_parameter_layout(TS_JNI_ARGS, jlong self, jint index, jlong layout) {
		return env->NewStringUTF(toMeshMaterial(self).getParameterLayout((uint32_t)index, toString(layout)).get());
	}
	static jlong mesh_material_get_parameter_image(TS_JNI_ARGS, jlong self, jint index) {
		return newImage(toMeshMaterial(self).getParameterImage((uint32_t)index));
	}
	static jlong mesh_material_get_parameter_blob(TS_JNI_ARGS, jlong self, jint index) {
		return newBlob(toMeshMaterial(self).getParameterBlob((uint32_t)index));
	}
	static jlong mesh_material_get_parameter_image_1(TS_JNI_ARGS, jlong self, jint index) {
		return newImage(toMeshMaterial(self).getParameterImage((uint32_t)index));
	}
	static jlong mesh_material_get_parameter_blob_1(TS_JNI_ARGS, jlong self, jint index) {
		return newBlob(toMeshMaterial(self).getParameterBlob((uint32_t)index));
	}
	static jint mesh_material_get_parameter_flags_1(TS_JNI_ARGS, jlong self, jstring type) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		MeshMaterial::Flags ret_ = toMeshMaterial(self).getParameterFlags(type_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jboolean mesh_material_has_parameter_flag_1(TS_JNI_ARGS, jlong self, jstring type, jint flags) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toMeshMaterial(self).hasParameterFlag(type_, (MeshMaterial::Flags)flags);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jboolean mesh_material_has_parameter_flags_1(TS_JNI_ARGS, jlong self, jstring type, jint flags) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toMeshMaterial(self).hasParameterFlags(type_, (MeshMaterial::Flags)flags);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jboolean mesh_material_get_parameter_bool_1(TS_JNI_ARGS, jlong self, jstring type, jboolean value) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toMeshMaterial(self).getParameterBool(type_, (bool)value);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jfloat mesh_material_get_parameter_scalarf32_1(TS_JNI_ARGS, jlong self, jstring type, jfloat value) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		float32_t ret_ = toMeshMaterial(self).getParameterScalarf32(type_, value);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jlong mesh_material_get_parameter_vector4f_1(TS_JNI_ARGS, jlong self, jstring type, jlong vector) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		const Vector4f ret_ = toMeshMaterial(self).getParameterVector4f(type_, toVector4f(vector));
		env->ReleaseStringUTFChars(type, type_);
		return newVector4f(ret_);
	}
	static jlong mesh_material_get_parameter_matrix3x2f_1(TS_JNI_ARGS, jlong self, jstring type, jlong matrix) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		const Matrix3x2f ret_ = toMeshMaterial(self).getParameterMatrix3x2f(type_, toMatrix3x2f(matrix));
		env->ReleaseStringUTFChars(type, type_);
		return newMatrix3x2f(ret_);
	}
	static jlong mesh_material_get_parameter_color_1(TS_JNI_ARGS, jlong self, jstring type, jlong color) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		const Color ret_ = toMeshMaterial(self).getParameterColor(type_, toColor(color));
		env->ReleaseStringUTFChars(type, type_);
		return newColor(ret_);
	}
	static jstring mesh_material_get_parameter_name_1(TS_JNI_ARGS, jlong self, jstring type, jlong name) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		String ret_ = toMeshMaterial(self).getParameterName(type_, toString(name));
		env->ReleaseStringUTFChars(type, type_);
		return env->NewStringUTF(ret_.get());
	}
	static jstring mesh_material_get_parameter_layout_1(TS_JNI_ARGS, jlong self, jstring type, jlong layout) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		String ret_ = toMeshMaterial(self).getParameterLayout(type_, toString(layout));
		env->ReleaseStringUTFChars(type, type_);
		return env->NewStringUTF(ret_.get());
	}
	static jint mesh_material_compare(TS_JNI_ARGS, jlong self, jlong material) {
		return toMeshMaterial(self).compare(toMeshMaterial(material));
	}
	static jlong mesh_material_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshMaterial(self).getMemory();
	}
	static const JNINativeMethod mesh_material_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;)J", (void*)mesh_material_new },
		{ (char*)"new_1", (char*)"(JLjava/lang/String;)J", (void*)mesh_material_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_material_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)mesh_material_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)mesh_material_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)mesh_material_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)mesh_material_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)mesh_material_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)mesh_material_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)mesh_material_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)mesh_material_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)mesh_material_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)mesh_material_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)mesh_material_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_material_clear },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)mesh_material_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_material_get_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)mesh_material_get_index },
		{ (char*)"set_indices", (char*)"(JJ)V", (void*)mesh_material_set_indices },
		{ (char*)"get_indices", (char*)"(J)J", (void*)mesh_material_get_indices },
		{ (char*)"get_indices_1", (char*)"(J)J", (void*)mesh_material_get_indices_1 },
		{ (char*)"set_geometry", (char*)"(JJZ)V", (void*)mesh_material_set_geometry },
		{ (char*)"get_geometry", (char*)"(J)J", (void*)mesh_material_get_geometry },
		{ (char*)"get_geometry_1", (char*)"(J)J", (void*)mesh_material_get_geometry_1 },
		{ (char*)"set_data", (char*)"(JLjava/lang/String;)V", (void*)mesh_material_set_data },
		{ (char*)"set_data_1", (char*)"(JJ)V", (void*)mesh_material_set_data_1 },
		{ (char*)"get_data", (char*)"(J)Ljava/lang/String;", (void*)mesh_material_get_data },
		{ (char*)"clear_parameters", (char*)"(J)V", (void*)mesh_material_clear_parameters },
		{ (char*)"remove_parameter", (char*)"(JLjava/lang/String;)Z", (void*)mesh_material_remove_parameter },
		{ (char*)"copy_parameters", (char*)"(JJ)V", (void*)mesh_material_copy_parameters },
		{ (char*)"find_parameter", (char*)"(JLjava/lang/String;)I", (void*)mesh_material_find_parameter },
		{ (char*)"has_parameter", (char*)"(JLjava/lang/String;)Z", (void*)mesh_material_has_parameter },
		{ (char*)"get_num_parameters", (char*)"(J)I", (void*)mesh_material_get_num_parameters },
		{ (char*)"get_parameter_type", (char*)"(JI)Ljava/lang/String;", (void*)mesh_material_get_parameter_type },
		{ (char*)"add_parameter", (char*)"(JLjava/lang/String;Z)V", (void*)mesh_material_add_parameter },
		{ (char*)"add_parameter_1", (char*)"(JLjava/lang/String;F)V", (void*)mesh_material_add_parameter_1 },
		{ (char*)"add_parameter_2", (char*)"(JLjava/lang/String;J)V", (void*)mesh_material_add_parameter_2 },
		{ (char*)"add_parameter_3", (char*)"(JLjava/lang/String;J)V", (void*)mesh_material_add_parameter_3 },
		{ (char*)"add_parameter_4", (char*)"(JLjava/lang/String;J)V", (void*)mesh_material_add_parameter_4 },
		{ (char*)"add_parameter_5", (char*)"(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", (void*)mesh_material_add_parameter_5 },
		{ (char*)"add_parameter_6", (char*)"(JLjava/lang/String;JLjava/lang/String;)V", (void*)mesh_material_add_parameter_6 },
		{ (char*)"add_parameter_7", (char*)"(JLjava/lang/String;JLjava/lang/String;)V", (void*)mesh_material_add_parameter_7 },
		{ (char*)"add_parameter_8", (char*)"(JLjava/lang/String;JLjava/lang/String;)V", (void*)mesh_material_add_parameter_8 },
		{ (char*)"get_parameter_flags", (char*)"(JI)I", (void*)mesh_material_get_parameter_flags },
		{ (char*)"has_parameter_flag", (char*)"(JII)Z", (void*)mesh_material_has_parameter_flag },
		{ (char*)"has_parameter_flags", (char*)"(JII)Z", (void*)mesh_material_has_parameter_flags },
		{ (char*)"get_parameter_bool", (char*)"(JIZ)Z", (void*)mesh_material_get_parameter_bool },
		{ (char*)"get_parameter_scalarf32", (char*)"(JIF)F", (void*)mesh_material_get_parameter_scalarf32 },
		{ (char*)"get_parameter_vector4f", (char*)"(JIJ)J", (void*)mesh_material_get_parameter_vector4f },
		{ (char*)"get_parameter_matrix3x2f", (char*)"(JIJ)J", (void*)mesh_material_get_parameter_matrix3x2f },
		{ (char*)"get_parameter_color", (char*)"(JIJ)J", (void*)mesh_material_get_parameter_color },
		{ (char*)"get_parameter_name", (char*)"(JIJ)Ljava/lang/String;", (void*)mesh_material_get_parameter_name },
		{ (char*)"get_parameter_layout", (char*)"(JIJ)Ljava/lang/String;", (void*)mesh_material_get_parameter_layout },
		{ (char*)"get_parameter_image", (char*)"(JI)J", (void*)mesh_material_get_parameter_image },
		{ (char*)"get_parameter_blob", (char*)"(JI)J", (void*)mesh_material_get_parameter_blob },
		{ (char*)"get_parameter_image_1", (char*)"(JI)J", (void*)mesh_material_get_parameter_image_1 },
		{ (char*)"get_parameter_blob_1", (char*)"(JI)J", (void*)mesh_material_get_parameter_blob_1 },
		{ (char*)"get_parameter_flags_1", (char*)"(JLjava/lang/String;)I", (void*)mesh_material_get_parameter_flags_1 },
		{ (char*)"has_parameter_flag_1", (char*)"(JLjava/lang/String;I)Z", (void*)mesh_material_has_parameter_flag_1 },
		{ (char*)"has_parameter_flags_1", (char*)"(JLjava/lang/String;I)Z", (void*)mesh_material_has_parameter_flags_1 },
		{ (char*)"get_parameter_bool_1", (char*)"(JLjava/lang/String;Z)Z", (void*)mesh_material_get_parameter_bool_1 },
		{ (char*)"get_parameter_scalarf32_1", (char*)"(JLjava/lang/String;F)F", (void*)mesh_material_get_parameter_scalarf32_1 },
		{ (char*)"get_parameter_vector4f_1", (char*)"(JLjava/lang/String;J)J", (void*)mesh_material_get_parameter_vector4f_1 },
		{ (char*)"get_parameter_matrix3x2f_1", (char*)"(JLjava/lang/String;J)J", (void*)mesh_material_get_parameter_matrix3x2f_1 },
		{ (char*)"get_parameter_color_1", (char*)"(JLjava/lang/String;J)J", (void*)mesh_material_get_parameter_color_1 },
		{ (char*)"get_parameter_name_1", (char*)"(JLjava/lang/String;J)Ljava/lang/String;", (void*)mesh_material_get_parameter_name_1 },
		{ (char*)"get_parameter_layout_1", (char*)"(JLjava/lang/String;J)Ljava/lang/String;", (void*)mesh_material_get_parameter_layout_1 },
		{ (char*)"compare_", (char*)"(JJ)I", (void*)mesh_material_compare },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_material_get_memory },
	};
	
	// Tellusim::MeshGeometry
	static jlong mesh_geometry_new(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshGeometry(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_geometry_new_1(TS_JNI_ARGS, jlong mesh, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshGeometry(toMesh(mesh), name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void mesh_geometry_delete(TS_JNI_ARGS, jlong self) {
		delete (MeshGeometry*)self;
	}
	static jboolean mesh_geometry_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toMeshGeometry(self) == toMeshGeometry(ptr));
	}
	static jlong mesh_geometry_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshGeometry(self).clonePtr());
	}
	static void mesh_geometry_clear_ptr(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).clearPtr();
	}
	static void mesh_geometry_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).destroyPtr();
	}
	static void mesh_geometry_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).acquirePtr();
	}
	static void mesh_geometry_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).unacquirePtr();
	}
	static jboolean mesh_geometry_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).isValidPtr();
	}
	static jboolean mesh_geometry_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).isOwnerPtr();
	}
	static jboolean mesh_geometry_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).isConstPtr();
	}
	static jint mesh_geometry_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).getCountPtr();
	}
	static jlong mesh_geometry_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshGeometry(self).getInternalPtr();
	}
	static void mesh_geometry_clear(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).clear();
	}
	static void mesh_geometry_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toMeshGeometry(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring mesh_geometry_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshGeometry(self).getName().get());
	}
	static jint mesh_geometry_get_index(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).getIndex();
	}
	static void mesh_geometry_set_mesh(TS_JNI_ARGS, jlong self, jlong mesh, jboolean check) {
		toMeshGeometry(self).setMesh(toMesh(mesh), (bool)check);
	}
	static jlong mesh_geometry_get_mesh(TS_JNI_ARGS, jlong self) {
		return newMesh(toMeshGeometry(self).getMesh());
	}
	static jlong mesh_geometry_get_mesh_1(TS_JNI_ARGS, jlong self) {
		return newMesh(toMeshGeometry(self).getMesh());
	}
	static jint mesh_geometry_set_parent0(TS_JNI_ARGS, jlong self, jlong parent, jboolean check) {
		return toMeshGeometry(self).setParent0(toMeshGeometry(parent), (bool)check);
	}
	static jint mesh_geometry_set_parent1(TS_JNI_ARGS, jlong self, jlong parent, jboolean check) {
		return toMeshGeometry(self).setParent1(toMeshGeometry(parent), (bool)check);
	}
	static jlong mesh_geometry_get_parent0(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshGeometry(self).getParent0());
	}
	static jlong mesh_geometry_get_parent1(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshGeometry(self).getParent1());
	}
	static jlong mesh_geometry_get_parent0_1(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshGeometry(self).getParent0());
	}
	static jlong mesh_geometry_get_parent1_1(TS_JNI_ARGS, jlong self) {
		return newMeshGeometry(toMeshGeometry(self).getParent1());
	}
	static jboolean mesh_geometry_is_root(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).isRoot();
	}
	static void mesh_geometry_reserve_children(TS_JNI_ARGS, jlong self, jint num_children) {
		toMeshGeometry(self).reserveChildren((uint32_t)num_children);
	}
	static jint mesh_geometry_add_child0(TS_JNI_ARGS, jlong self, jlong child, jboolean check) {
		return toMeshGeometry(self).addChild0(toMeshGeometry(child), (bool)check);
	}
	static jint mesh_geometry_add_child1(TS_JNI_ARGS, jlong self, jlong child, jboolean check) {
		return toMeshGeometry(self).addChild1(toMeshGeometry(child), (bool)check);
	}
	static jboolean mesh_geometry_remove_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toMeshGeometry(self).removeChild(toMeshGeometry(child));
	}
	static void mesh_geometry_release_children(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).releaseChildren();
	}
	static jint mesh_geometry_find_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toMeshGeometry(self).findChild(toMeshGeometry(child));
	}
	static jint mesh_geometry_get_num_children(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).getNumChildren();
	}
	static jlong mesh_geometry_get_child(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshGeometry(toMeshGeometry(self).getChild((uint32_t)index));
	}
	static jlong mesh_geometry_get_child_1(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshGeometry(toMeshGeometry(self).getChild((uint32_t)index));
	}
	static void mesh_geometry_clear_indices(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).clearIndices();
	}
	static void mesh_geometry_reserve_indices(TS_JNI_ARGS, jlong self, jint num_indices) {
		toMeshGeometry(self).reserveIndices((uint32_t)num_indices);
	}
	static jint mesh_geometry_add_indices(TS_JNI_ARGS, jlong self, jlong indices, jboolean check) {
		return toMeshGeometry(self).addIndices(toMeshIndices(indices), (bool)check);
	}
	static jboolean mesh_geometry_remove_indices(TS_JNI_ARGS, jlong self, jlong indices) {
		return toMeshGeometry(self).removeIndices(toMeshIndices(indices));
	}
	static jboolean mesh_geometry_replace_indices(TS_JNI_ARGS, jlong self, jlong old_indices, jlong indices) {
		return toMeshGeometry(self).replaceIndices(toMeshIndices(old_indices), toMeshIndices(indices));
	}
	static jint mesh_geometry_find_indices(TS_JNI_ARGS, jlong self, jlong indices) {
		return toMeshGeometry(self).findIndices(toMeshIndices(indices));
	}
	static jint mesh_geometry_find_indices_1(TS_JNI_ARGS, jlong self, jint type) {
		return toMeshGeometry(self).findIndices((MeshIndices::Type)type);
	}
	static jboolean mesh_geometry_has_indices(TS_JNI_ARGS, jlong self, jint type) {
		return toMeshGeometry(self).hasIndices((MeshIndices::Type)type);
	}
	static jboolean mesh_geometry_has_solid_indices(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).hasSolidIndices();
	}
	static jint mesh_geometry_get_num_indices(TS_JNI_ARGS, jlong self, jint type) {
		return toMeshGeometry(self).getNumIndices((MeshIndices::Type)type);
	}
	static jlong mesh_geometry_get_indices(TS_JNI_ARGS, jlong self, jint type) {
		return newMeshIndices(toMeshGeometry(self).getIndices((MeshIndices::Type)type));
	}
	static jlong mesh_geometry_get_indices_1(TS_JNI_ARGS, jlong self, jint type) {
		return newMeshIndices(toMeshGeometry(self).getIndices((MeshIndices::Type)type));
	}
	static jint mesh_geometry_get_num_indices_1(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).getNumIndices();
	}
	static jlong mesh_geometry_get_indices_2(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshIndices(toMeshGeometry(self).getIndices((uint32_t)index));
	}
	static jlong mesh_geometry_get_indices_3(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshIndices(toMeshGeometry(self).getIndices((uint32_t)index));
	}
	static void mesh_geometry_clear_attributes(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).clearAttributes();
	}
	static void mesh_geometry_reserve_attributes(TS_JNI_ARGS, jlong self, jint num_attributes) {
		toMeshGeometry(self).reserveAttributes((uint32_t)num_attributes);
	}
	static jint mesh_geometry_add_attribute(TS_JNI_ARGS, jlong self, jlong attribute, jboolean check) {
		return toMeshGeometry(self).addAttribute(toMeshAttribute(attribute), (bool)check);
	}
	static jint mesh_geometry_add_attribute_1(TS_JNI_ARGS, jlong self, jlong attribute, jlong indices, jboolean check) {
		return toMeshGeometry(self).addAttribute(toMeshAttribute(attribute), toMeshIndices(indices), (bool)check);
	}
	static jboolean mesh_geometry_remove_attribute(TS_JNI_ARGS, jlong self, jlong attribute) {
		return toMeshGeometry(self).removeAttribute(toMeshAttribute(attribute));
	}
	static jboolean mesh_geometry_replace_attribute(TS_JNI_ARGS, jlong self, jlong old_attribute, jlong attribute) {
		return toMeshGeometry(self).replaceAttribute(toMeshAttribute(old_attribute), toMeshAttribute(attribute));
	}
	static jboolean mesh_geometry_replace_attribute_indices(TS_JNI_ARGS, jlong self, jlong old_indices, jlong indices) {
		return toMeshGeometry(self).replaceAttributeIndices(toMeshIndices(old_indices), toMeshIndices(indices));
	}
	static jint mesh_geometry_find_attribute(TS_JNI_ARGS, jlong self, jint type, jint format, jint index) {
		return toMeshGeometry(self).findAttribute((MeshAttribute::Type)type, (Format)format, (uint32_t)index);
	}
	static jint mesh_geometry_find_attribute_1(TS_JNI_ARGS, jlong self, jint type, jint index) {
		return toMeshGeometry(self).findAttribute((MeshAttribute::Type)type, (uint32_t)index);
	}
	static jint mesh_geometry_find_attribute_2(TS_JNI_ARGS, jlong self, jstring name, jint index) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toMeshGeometry(self).findAttribute(name_, (uint32_t)index);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint mesh_geometry_find_attribute_3(TS_JNI_ARGS, jlong self, jlong attribute) {
		return toMeshGeometry(self).findAttribute(toMeshAttribute(attribute));
	}
	static jboolean mesh_geometry_has_attribute(TS_JNI_ARGS, jlong self, jint type, jint format, jint index) {
		return toMeshGeometry(self).hasAttribute((MeshAttribute::Type)type, (Format)format, (uint32_t)index);
	}
	static jboolean mesh_geometry_has_attribute_1(TS_JNI_ARGS, jlong self, jint type, jint index) {
		return toMeshGeometry(self).hasAttribute((MeshAttribute::Type)type, (uint32_t)index);
	}
	static jboolean mesh_geometry_has_attribute_2(TS_JNI_ARGS, jlong self, jstring name, jint index) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toMeshGeometry(self).hasAttribute(name_, (uint32_t)index);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean mesh_geometry_has_attribute_3(TS_JNI_ARGS, jlong self, jlong attribute) {
		return toMeshGeometry(self).hasAttribute(toMeshAttribute(attribute));
	}
	static jint mesh_geometry_get_num_attributes(TS_JNI_ARGS, jlong self, jint type) {
		return toMeshGeometry(self).getNumAttributes((MeshAttribute::Type)type);
	}
	static jint mesh_geometry_get_num_attributes_1(TS_JNI_ARGS, jlong self, jlong indices) {
		return toMeshGeometry(self).getNumAttributes(toMeshIndices(indices));
	}
	static jlong mesh_geometry_get_attribute(TS_JNI_ARGS, jlong self, jint type, jint index) {
		return newMeshAttribute(toMeshGeometry(self).getAttribute((MeshAttribute::Type)type, (uint32_t)index));
	}
	static jlong mesh_geometry_get_attribute_1(TS_JNI_ARGS, jlong self, jint type, jint index) {
		return newMeshAttribute(toMeshGeometry(self).getAttribute((MeshAttribute::Type)type, (uint32_t)index));
	}
	static jint mesh_geometry_get_num_attributes_2(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).getNumAttributes();
	}
	static jlong mesh_geometry_get_attribute_2(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshAttribute(toMeshGeometry(self).getAttribute((uint32_t)index));
	}
	static jlong mesh_geometry_get_attribute_3(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshAttribute(toMeshGeometry(self).getAttribute((uint32_t)index));
	}
	static void mesh_geometry_clear_joints(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).clearJoints();
	}
	static void mesh_geometry_reserve_joints(TS_JNI_ARGS, jlong self, jint num_joints) {
		toMeshGeometry(self).reserveJoints((uint32_t)num_joints);
	}
	static jint mesh_geometry_add_joint(TS_JNI_ARGS, jlong self, jlong joint, jboolean check) {
		return toMeshGeometry(self).addJoint(toMeshJoint(joint), (bool)check);
	}
	static jint mesh_geometry_add_joint_1(TS_JNI_ARGS, jlong self, jlong joint, jlong node, jboolean check) {
		return toMeshGeometry(self).addJoint(toMeshJoint(joint), toMeshNode(node), (bool)check);
	}
	static jboolean mesh_geometry_remove_joint(TS_JNI_ARGS, jlong self, jlong joint) {
		return toMeshGeometry(self).removeJoint(toMeshJoint(joint));
	}
	static jboolean mesh_geometry_replace_joint(TS_JNI_ARGS, jlong self, jlong old_joint, jlong joint) {
		return toMeshGeometry(self).replaceJoint(toMeshJoint(old_joint), toMeshJoint(joint));
	}
	static jint mesh_geometry_find_joint(TS_JNI_ARGS, jlong self, jlong joint) {
		return toMeshGeometry(self).findJoint(toMeshJoint(joint));
	}
	static jint mesh_geometry_find_joint_1(TS_JNI_ARGS, jlong self, jlong node) {
		return toMeshGeometry(self).findJoint(toMeshNode(node));
	}
	static jint mesh_geometry_find_joint_2(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toMeshGeometry(self).findJoint(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint mesh_geometry_get_num_joints(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).getNumJoints();
	}
	static jlong mesh_geometry_get_joint(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshJoint(toMeshGeometry(self).getJoint((uint32_t)index));
	}
	static jlong mesh_geometry_get_joint_1(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshJoint(toMeshGeometry(self).getJoint((uint32_t)index));
	}
	static void mesh_geometry_clear_materials(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).clearMaterials();
	}
	static void mesh_geometry_reserve_materials(TS_JNI_ARGS, jlong self, jint num_materials) {
		toMeshGeometry(self).reserveMaterials((uint32_t)num_materials);
	}
	static jint mesh_geometry_add_material(TS_JNI_ARGS, jlong self, jlong material, jboolean check) {
		return toMeshGeometry(self).addMaterial(toMeshMaterial(material), (bool)check);
	}
	static jint mesh_geometry_add_material_1(TS_JNI_ARGS, jlong self, jlong material, jlong indices, jboolean check) {
		return toMeshGeometry(self).addMaterial(toMeshMaterial(material), toMeshIndices(indices), (bool)check);
	}
	static jboolean mesh_geometry_remove_material(TS_JNI_ARGS, jlong self, jlong material) {
		return toMeshGeometry(self).removeMaterial(toMeshMaterial(material));
	}
	static jboolean mesh_geometry_replace_material(TS_JNI_ARGS, jlong self, jlong old_material, jlong material) {
		return toMeshGeometry(self).replaceMaterial(toMeshMaterial(old_material), toMeshMaterial(material));
	}
	static jint mesh_geometry_find_material(TS_JNI_ARGS, jlong self, jlong material) {
		return toMeshGeometry(self).findMaterial(toMeshMaterial(material));
	}
	static jint mesh_geometry_find_material_1(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toMeshGeometry(self).findMaterial(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint mesh_geometry_get_num_materials(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).getNumMaterials();
	}
	static jlong mesh_geometry_get_material(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshMaterial(toMeshGeometry(self).getMaterial((uint32_t)index));
	}
	static jlong mesh_geometry_get_material_1(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshMaterial(toMeshGeometry(self).getMaterial((uint32_t)index));
	}
	static void mesh_geometry_set_bound_box(TS_JNI_ARGS, jlong self, jlong box) {
		toMeshGeometry(self).setBoundBox(toBoundBoxf(box));
	}
	static jlong mesh_geometry_get_bound_box(TS_JNI_ARGS, jlong self) {
		return newBoundBoxf(toMeshGeometry(self).getBoundBox());
	}
	static void mesh_geometry_set_bound_sphere(TS_JNI_ARGS, jlong self, jlong sphere) {
		toMeshGeometry(self).setBoundSphere(toBoundSpheref(sphere));
	}
	static jlong mesh_geometry_get_bound_sphere(TS_JNI_ARGS, jlong self) {
		return newBoundSpheref(toMeshGeometry(self).getBoundSphere());
	}
	static jboolean mesh_geometry_set_transform(TS_JNI_ARGS, jlong self, jlong scale) {
		return toMeshGeometry(self).setTransform(toVector3f(scale));
	}
	static jboolean mesh_geometry_set_transform_1(TS_JNI_ARGS, jlong self, jlong transform, jboolean apply) {
		return toMeshGeometry(self).setTransform(toMatrix4x3f(transform), (bool)apply);
	}
	static jlong mesh_geometry_get_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3f(toMeshGeometry(self).getTransform());
	}
	static void mesh_geometry_set_joint_itransform(TS_JNI_ARGS, jlong self, jlong itransform) {
		toMeshGeometry(self).setJointITransform(toMatrix4x3f(itransform));
	}
	static jlong mesh_geometry_get_joint_itransform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3f(toMeshGeometry(self).getJointITransform());
	}
	static void mesh_geometry_set_min_visibility(TS_JNI_ARGS, jlong self, jfloat distance) {
		toMeshGeometry(self).setMinVisibility(distance);
	}
	static void mesh_geometry_set_max_visibility(TS_JNI_ARGS, jlong self, jfloat distance) {
		toMeshGeometry(self).setMaxVisibility(distance);
	}
	static void mesh_geometry_set_visibility_range(TS_JNI_ARGS, jlong self, jfloat min, jfloat max) {
		toMeshGeometry(self).setVisibilityRange(min, max);
	}
	static jfloat mesh_geometry_get_min_visibility(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).getMinVisibility();
	}
	static jfloat mesh_geometry_get_max_visibility(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).getMaxVisibility();
	}
	static jboolean mesh_geometry_has_visibility_range(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).hasVisibilityRange();
	}
	static void mesh_geometry_set_visibility_error(TS_JNI_ARGS, jlong self, jfloat error) {
		toMeshGeometry(self).setVisibilityError(error);
	}
	static jfloat mesh_geometry_get_visibility_error(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).getVisibilityError();
	}
	static jboolean mesh_geometry_create_bounds(TS_JNI_ARGS, jlong self, jboolean force, jint position) {
		return toMeshGeometry(self).createBounds((bool)force, (uint32_t)position);
	}
	static jint mesh_geometry_create_basis(TS_JNI_ARGS, jlong self, jboolean force, jint position, jint normal, jint tangent, jboolean append) {
		return toMeshGeometry(self).createBasis((bool)force, (uint32_t)position, (uint32_t)normal, (uint32_t)tangent, (bool)append);
	}
	static jint mesh_geometry_create_basis_1(TS_JNI_ARGS, jlong self, jfloat angle, jboolean force, jint position, jint normal, jint tangent, jboolean append) {
		return toMeshGeometry(self).createBasis(angle, (bool)force, (uint32_t)position, (uint32_t)normal, (uint32_t)tangent, (bool)append);
	}
	static jint mesh_geometry_create_normals(TS_JNI_ARGS, jlong self, jboolean force, jint position, jboolean append) {
		return toMeshGeometry(self).createNormals((bool)force, (uint32_t)position, (bool)append);
	}
	static jint mesh_geometry_create_normals_1(TS_JNI_ARGS, jlong self, jfloat angle, jboolean force, jint position, jboolean append) {
		return toMeshGeometry(self).createNormals(angle, (bool)force, (uint32_t)position, (bool)append);
	}
	static jint mesh_geometry_create_tangents(TS_JNI_ARGS, jlong self, jboolean force, jint position, jint normal, jint texcoord, jboolean append) {
		return toMeshGeometry(self).createTangents((bool)force, (uint32_t)position, (uint32_t)normal, (uint32_t)texcoord, (bool)append);
	}
	static jint mesh_geometry_create_islands(TS_JNI_ARGS, jlong self, jint max_attributes, jint max_primitives, jboolean force, jint index, jint position, jboolean append) {
		return toMeshGeometry(self).createIslands((uint32_t)max_attributes, (uint32_t)max_primitives, (bool)force, (uint32_t)index, (uint32_t)position, (bool)append);
	}
	static jboolean mesh_geometry_optimize_indices(TS_JNI_ARGS, jlong self, jint cache, jboolean transparent, jint index, jint position) {
		return toMeshGeometry(self).optimizeIndices((uint32_t)cache, (bool)transparent, (uint32_t)index, (uint32_t)position);
	}
	static jboolean mesh_geometry_optimize_attributes(TS_JNI_ARGS, jlong self, jint material) {
		return toMeshGeometry(self).optimizeAttributes((uint32_t)material);
	}
	static void mesh_geometry_optimize_materials(TS_JNI_ARGS, jlong self) {
		toMeshGeometry(self).optimizeMaterials();
	}
	static jboolean mesh_geometry_pack_attributes(TS_JNI_ARGS, jlong self, jboolean remove) {
		return toMeshGeometry(self).packAttributes((bool)remove);
	}
	static jboolean mesh_geometry_unpack_attributes(TS_JNI_ARGS, jlong self, jboolean remove) {
		return toMeshGeometry(self).unpackAttributes((bool)remove);
	}
	static jint mesh_geometry_compare(TS_JNI_ARGS, jlong self, jlong geometry, jlong transform, jfloat threshold, jboolean spatial) {
		return toMeshGeometry(self).compare(toMeshGeometry(geometry), toMatrix4x3f(transform), threshold, (bool)spatial);
	}
	static jboolean mesh_geometry_is_optimized(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).isOptimized();
	}
	static jboolean mesh_geometry_validate(TS_JNI_ARGS, jlong self) {
		return toMeshGeometry(self).validate();
	}
	static jlong mesh_geometry_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshGeometry(self).getMemory();
	}
	static const JNINativeMethod mesh_geometry_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;)J", (void*)mesh_geometry_new },
		{ (char*)"new_1", (char*)"(JLjava/lang/String;)J", (void*)mesh_geometry_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_geometry_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)mesh_geometry_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)mesh_geometry_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)mesh_geometry_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)mesh_geometry_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)mesh_geometry_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)mesh_geometry_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)mesh_geometry_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)mesh_geometry_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)mesh_geometry_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)mesh_geometry_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)mesh_geometry_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_geometry_clear },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)mesh_geometry_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_geometry_get_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)mesh_geometry_get_index },
		{ (char*)"set_mesh", (char*)"(JJZ)V", (void*)mesh_geometry_set_mesh },
		{ (char*)"get_mesh", (char*)"(J)J", (void*)mesh_geometry_get_mesh },
		{ (char*)"get_mesh_1", (char*)"(J)J", (void*)mesh_geometry_get_mesh_1 },
		{ (char*)"set_parent0", (char*)"(JJZ)I", (void*)mesh_geometry_set_parent0 },
		{ (char*)"set_parent1", (char*)"(JJZ)I", (void*)mesh_geometry_set_parent1 },
		{ (char*)"get_parent0", (char*)"(J)J", (void*)mesh_geometry_get_parent0 },
		{ (char*)"get_parent1", (char*)"(J)J", (void*)mesh_geometry_get_parent1 },
		{ (char*)"get_parent0_1", (char*)"(J)J", (void*)mesh_geometry_get_parent0_1 },
		{ (char*)"get_parent1_1", (char*)"(J)J", (void*)mesh_geometry_get_parent1_1 },
		{ (char*)"is_root", (char*)"(J)Z", (void*)mesh_geometry_is_root },
		{ (char*)"reserve_children", (char*)"(JI)V", (void*)mesh_geometry_reserve_children },
		{ (char*)"add_child0", (char*)"(JJZ)I", (void*)mesh_geometry_add_child0 },
		{ (char*)"add_child1", (char*)"(JJZ)I", (void*)mesh_geometry_add_child1 },
		{ (char*)"remove_child", (char*)"(JJ)Z", (void*)mesh_geometry_remove_child },
		{ (char*)"release_children", (char*)"(J)V", (void*)mesh_geometry_release_children },
		{ (char*)"find_child", (char*)"(JJ)I", (void*)mesh_geometry_find_child },
		{ (char*)"get_num_children", (char*)"(J)I", (void*)mesh_geometry_get_num_children },
		{ (char*)"get_child", (char*)"(JI)J", (void*)mesh_geometry_get_child },
		{ (char*)"get_child_1", (char*)"(JI)J", (void*)mesh_geometry_get_child_1 },
		{ (char*)"clear_indices", (char*)"(J)V", (void*)mesh_geometry_clear_indices },
		{ (char*)"reserve_indices", (char*)"(JI)V", (void*)mesh_geometry_reserve_indices },
		{ (char*)"add_indices", (char*)"(JJZ)I", (void*)mesh_geometry_add_indices },
		{ (char*)"remove_indices", (char*)"(JJ)Z", (void*)mesh_geometry_remove_indices },
		{ (char*)"replace_indices", (char*)"(JJJ)Z", (void*)mesh_geometry_replace_indices },
		{ (char*)"find_indices", (char*)"(JJ)I", (void*)mesh_geometry_find_indices },
		{ (char*)"find_indices_1", (char*)"(JI)I", (void*)mesh_geometry_find_indices_1 },
		{ (char*)"has_indices", (char*)"(JI)Z", (void*)mesh_geometry_has_indices },
		{ (char*)"has_solid_indices", (char*)"(J)Z", (void*)mesh_geometry_has_solid_indices },
		{ (char*)"get_num_indices", (char*)"(JI)I", (void*)mesh_geometry_get_num_indices },
		{ (char*)"get_indices", (char*)"(JI)J", (void*)mesh_geometry_get_indices },
		{ (char*)"get_indices_1", (char*)"(JI)J", (void*)mesh_geometry_get_indices_1 },
		{ (char*)"get_num_indices_1", (char*)"(J)I", (void*)mesh_geometry_get_num_indices_1 },
		{ (char*)"get_indices_2", (char*)"(JI)J", (void*)mesh_geometry_get_indices_2 },
		{ (char*)"get_indices_3", (char*)"(JI)J", (void*)mesh_geometry_get_indices_3 },
		{ (char*)"clear_attributes", (char*)"(J)V", (void*)mesh_geometry_clear_attributes },
		{ (char*)"reserve_attributes", (char*)"(JI)V", (void*)mesh_geometry_reserve_attributes },
		{ (char*)"add_attribute", (char*)"(JJZ)I", (void*)mesh_geometry_add_attribute },
		{ (char*)"add_attribute_1", (char*)"(JJJZ)I", (void*)mesh_geometry_add_attribute_1 },
		{ (char*)"remove_attribute", (char*)"(JJ)Z", (void*)mesh_geometry_remove_attribute },
		{ (char*)"replace_attribute", (char*)"(JJJ)Z", (void*)mesh_geometry_replace_attribute },
		{ (char*)"replace_attribute_indices", (char*)"(JJJ)Z", (void*)mesh_geometry_replace_attribute_indices },
		{ (char*)"find_attribute", (char*)"(JIII)I", (void*)mesh_geometry_find_attribute },
		{ (char*)"find_attribute_1", (char*)"(JII)I", (void*)mesh_geometry_find_attribute_1 },
		{ (char*)"find_attribute_2", (char*)"(JLjava/lang/String;I)I", (void*)mesh_geometry_find_attribute_2 },
		{ (char*)"find_attribute_3", (char*)"(JJ)I", (void*)mesh_geometry_find_attribute_3 },
		{ (char*)"has_attribute", (char*)"(JIII)Z", (void*)mesh_geometry_has_attribute },
		{ (char*)"has_attribute_1", (char*)"(JII)Z", (void*)mesh_geometry_has_attribute_1 },
		{ (char*)"has_attribute_2", (char*)"(JLjava/lang/String;I)Z", (void*)mesh_geometry_has_attribute_2 },
		{ (char*)"has_attribute_3", (char*)"(JJ)Z", (void*)mesh_geometry_has_attribute_3 },
		{ (char*)"get_num_attributes", (char*)"(JI)I", (void*)mesh_geometry_get_num_attributes },
		{ (char*)"get_num_attributes_1", (char*)"(JJ)I", (void*)mesh_geometry_get_num_attributes_1 },
		{ (char*)"get_attribute", (char*)"(JII)J", (void*)mesh_geometry_get_attribute },
		{ (char*)"get_attribute_1", (char*)"(JII)J", (void*)mesh_geometry_get_attribute_1 },
		{ (char*)"get_num_attributes_2", (char*)"(J)I", (void*)mesh_geometry_get_num_attributes_2 },
		{ (char*)"get_attribute_2", (char*)"(JI)J", (void*)mesh_geometry_get_attribute_2 },
		{ (char*)"get_attribute_3", (char*)"(JI)J", (void*)mesh_geometry_get_attribute_3 },
		{ (char*)"clear_joints", (char*)"(J)V", (void*)mesh_geometry_clear_joints },
		{ (char*)"reserve_joints", (char*)"(JI)V", (void*)mesh_geometry_reserve_joints },
		{ (char*)"add_joint", (char*)"(JJZ)I", (void*)mesh_geometry_add_joint },
		{ (char*)"add_joint_1", (char*)"(JJJZ)I", (void*)mesh_geometry_add_joint_1 },
		{ (char*)"remove_joint", (char*)"(JJ)Z", (void*)mesh_geometry_remove_joint },
		{ (char*)"replace_joint", (char*)"(JJJ)Z", (void*)mesh_geometry_replace_joint },
		{ (char*)"find_joint", (char*)"(JJ)I", (void*)mesh_geometry_find_joint },
		{ (char*)"find_joint_1", (char*)"(JJ)I", (void*)mesh_geometry_find_joint_1 },
		{ (char*)"find_joint_2", (char*)"(JLjava/lang/String;)I", (void*)mesh_geometry_find_joint_2 },
		{ (char*)"get_num_joints", (char*)"(J)I", (void*)mesh_geometry_get_num_joints },
		{ (char*)"get_joint", (char*)"(JI)J", (void*)mesh_geometry_get_joint },
		{ (char*)"get_joint_1", (char*)"(JI)J", (void*)mesh_geometry_get_joint_1 },
		{ (char*)"clear_materials", (char*)"(J)V", (void*)mesh_geometry_clear_materials },
		{ (char*)"reserve_materials", (char*)"(JI)V", (void*)mesh_geometry_reserve_materials },
		{ (char*)"add_material", (char*)"(JJZ)I", (void*)mesh_geometry_add_material },
		{ (char*)"add_material_1", (char*)"(JJJZ)I", (void*)mesh_geometry_add_material_1 },
		{ (char*)"remove_material", (char*)"(JJ)Z", (void*)mesh_geometry_remove_material },
		{ (char*)"replace_material", (char*)"(JJJ)Z", (void*)mesh_geometry_replace_material },
		{ (char*)"find_material", (char*)"(JJ)I", (void*)mesh_geometry_find_material },
		{ (char*)"find_material_1", (char*)"(JLjava/lang/String;)I", (void*)mesh_geometry_find_material_1 },
		{ (char*)"get_num_materials", (char*)"(J)I", (void*)mesh_geometry_get_num_materials },
		{ (char*)"get_material", (char*)"(JI)J", (void*)mesh_geometry_get_material },
		{ (char*)"get_material_1", (char*)"(JI)J", (void*)mesh_geometry_get_material_1 },
		{ (char*)"set_bound_box", (char*)"(JJ)V", (void*)mesh_geometry_set_bound_box },
		{ (char*)"get_bound_box", (char*)"(J)J", (void*)mesh_geometry_get_bound_box },
		{ (char*)"set_bound_sphere", (char*)"(JJ)V", (void*)mesh_geometry_set_bound_sphere },
		{ (char*)"get_bound_sphere", (char*)"(J)J", (void*)mesh_geometry_get_bound_sphere },
		{ (char*)"set_transform", (char*)"(JJ)Z", (void*)mesh_geometry_set_transform },
		{ (char*)"set_transform_1", (char*)"(JJZ)Z", (void*)mesh_geometry_set_transform_1 },
		{ (char*)"get_transform", (char*)"(J)J", (void*)mesh_geometry_get_transform },
		{ (char*)"set_joint_itransform", (char*)"(JJ)V", (void*)mesh_geometry_set_joint_itransform },
		{ (char*)"get_joint_itransform", (char*)"(J)J", (void*)mesh_geometry_get_joint_itransform },
		{ (char*)"set_min_visibility", (char*)"(JF)V", (void*)mesh_geometry_set_min_visibility },
		{ (char*)"set_max_visibility", (char*)"(JF)V", (void*)mesh_geometry_set_max_visibility },
		{ (char*)"set_visibility_range", (char*)"(JFF)V", (void*)mesh_geometry_set_visibility_range },
		{ (char*)"get_min_visibility", (char*)"(J)F", (void*)mesh_geometry_get_min_visibility },
		{ (char*)"get_max_visibility", (char*)"(J)F", (void*)mesh_geometry_get_max_visibility },
		{ (char*)"has_visibility_range", (char*)"(J)Z", (void*)mesh_geometry_has_visibility_range },
		{ (char*)"set_visibility_error", (char*)"(JF)V", (void*)mesh_geometry_set_visibility_error },
		{ (char*)"get_visibility_error", (char*)"(J)F", (void*)mesh_geometry_get_visibility_error },
		{ (char*)"create_bounds", (char*)"(JZI)Z", (void*)mesh_geometry_create_bounds },
		{ (char*)"create_basis", (char*)"(JZIIIZ)I", (void*)mesh_geometry_create_basis },
		{ (char*)"create_basis_1", (char*)"(JFZIIIZ)I", (void*)mesh_geometry_create_basis_1 },
		{ (char*)"create_normals", (char*)"(JZIZ)I", (void*)mesh_geometry_create_normals },
		{ (char*)"create_normals_1", (char*)"(JFZIZ)I", (void*)mesh_geometry_create_normals_1 },
		{ (char*)"create_tangents", (char*)"(JZIIIZ)I", (void*)mesh_geometry_create_tangents },
		{ (char*)"create_islands", (char*)"(JIIZIIZ)I", (void*)mesh_geometry_create_islands },
		{ (char*)"optimize_indices", (char*)"(JIZII)Z", (void*)mesh_geometry_optimize_indices },
		{ (char*)"optimize_attributes", (char*)"(JI)Z", (void*)mesh_geometry_optimize_attributes },
		{ (char*)"optimize_materials", (char*)"(J)V", (void*)mesh_geometry_optimize_materials },
		{ (char*)"pack_attributes", (char*)"(JZ)Z", (void*)mesh_geometry_pack_attributes },
		{ (char*)"unpack_attributes", (char*)"(JZ)Z", (void*)mesh_geometry_unpack_attributes },
		{ (char*)"compare_", (char*)"(JJJFZ)I", (void*)mesh_geometry_compare },
		{ (char*)"is_optimized", (char*)"(J)Z", (void*)mesh_geometry_is_optimized },
		{ (char*)"validate_", (char*)"(J)Z", (void*)mesh_geometry_validate },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_geometry_get_memory },
	};
	
	// Tellusim::MeshTransform
	static jlong mesh_transform_new(TS_JNI_ARGS) {
		return newMeshTransform();
	}
	static void mesh_transform_delete(TS_JNI_ARGS, jlong self) {
		delete (MeshTransform*)self;
	}
	static jboolean mesh_transform_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toMeshTransform(self) == toMeshTransform(ptr));
	}
	static jlong mesh_transform_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newMeshTransform(toMeshTransform(self).clonePtr());
	}
	static void mesh_transform_clear_ptr(TS_JNI_ARGS, jlong self) {
		toMeshTransform(self).clearPtr();
	}
	static void mesh_transform_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toMeshTransform(self).destroyPtr();
	}
	static void mesh_transform_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshTransform(self).acquirePtr();
	}
	static void mesh_transform_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshTransform(self).unacquirePtr();
	}
	static jboolean mesh_transform_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).isValidPtr();
	}
	static jboolean mesh_transform_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).isOwnerPtr();
	}
	static jboolean mesh_transform_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).isConstPtr();
	}
	static jint mesh_transform_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).getCountPtr();
	}
	static jlong mesh_transform_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshTransform(self).getInternalPtr();
	}
	static void mesh_transform_clear(TS_JNI_ARGS, jlong self) {
		toMeshTransform(self).clear();
	}
	static jdouble mesh_transform_get_min_time(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).getMinTime();
	}
	static jdouble mesh_transform_get_max_time(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).getMaxTime();
	}
	static void mesh_transform_set_transform(TS_JNI_ARGS, jlong self, jdouble time, jlong transform, jfloat threshold) {
		toMeshTransform(self).setTransform(time, toMatrix4x3d(transform), threshold);
	}
	static void mesh_transform_set_translate(TS_JNI_ARGS, jlong self, jdouble time, jlong translate, jfloat threshold) {
		toMeshTransform(self).setTranslate(time, toVector3d(translate), threshold);
	}
	static void mesh_transform_set_rotate(TS_JNI_ARGS, jlong self, jdouble time, jlong rotate, jfloat threshold) {
		toMeshTransform(self).setRotate(time, toQuaternionf(rotate), threshold);
	}
	static void mesh_transform_set_scale(TS_JNI_ARGS, jlong self, jdouble time, jlong scale, jfloat threshold) {
		toMeshTransform(self).setScale(time, toVector3f(scale), threshold);
	}
	static void mesh_transform_set_morph(TS_JNI_ARGS, jlong self, jdouble time, jlong morph, jfloat threshold) {
		toMeshTransform(self).setMorph(time, toVector4f(morph), threshold);
	}
	static jlong mesh_transform_get_transform(TS_JNI_ARGS, jlong self, jdouble time) {
		return newMatrix4x3d(toMeshTransform(self).getTransform(time));
	}
	static jlong mesh_transform_get_translate(TS_JNI_ARGS, jlong self, jdouble time) {
		return newVector3d(toMeshTransform(self).getTranslate(time));
	}
	static jlong mesh_transform_get_rotate(TS_JNI_ARGS, jlong self, jdouble time) {
		return newQuaternionf(toMeshTransform(self).getRotate(time));
	}
	static jlong mesh_transform_get_scale(TS_JNI_ARGS, jlong self, jdouble time) {
		return newVector3f(toMeshTransform(self).getScale(time));
	}
	static jlong mesh_transform_get_morph(TS_JNI_ARGS, jlong self, jdouble time) {
		return newVector4f(toMeshTransform(self).getMorph(time));
	}
	static jboolean mesh_transform_has_transform_keys(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).hasTransformKeys();
	}
	static jboolean mesh_transform_has_translate_keys(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).hasTranslateKeys();
	}
	static jboolean mesh_transform_has_rotate_keys(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).hasRotateKeys();
	}
	static jboolean mesh_transform_has_scale_keys(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).hasScaleKeys();
	}
	static jboolean mesh_transform_has_morph_keys(TS_JNI_ARGS, jlong self) {
		return toMeshTransform(self).hasMorphKeys();
	}
	static void mesh_transform_set_transform_1(TS_JNI_ARGS, jlong self, jlong scale) {
		toMeshTransform(self).setTransform(toVector3d(scale));
	}
	static void mesh_transform_set_transform_2(TS_JNI_ARGS, jlong self, jlong transform) {
		toMeshTransform(self).setTransform(toMatrix4x3d(transform));
	}
	static jlong mesh_transform_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshTransform(self).getMemory();
	}
	static const JNINativeMethod mesh_transform_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mesh_transform_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_transform_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)mesh_transform_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)mesh_transform_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)mesh_transform_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)mesh_transform_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)mesh_transform_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)mesh_transform_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)mesh_transform_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)mesh_transform_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)mesh_transform_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)mesh_transform_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)mesh_transform_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_transform_clear },
		{ (char*)"get_min_time", (char*)"(J)D", (void*)mesh_transform_get_min_time },
		{ (char*)"get_max_time", (char*)"(J)D", (void*)mesh_transform_get_max_time },
		{ (char*)"set_transform", (char*)"(JDJF)V", (void*)mesh_transform_set_transform },
		{ (char*)"set_translate", (char*)"(JDJF)V", (void*)mesh_transform_set_translate },
		{ (char*)"set_rotate", (char*)"(JDJF)V", (void*)mesh_transform_set_rotate },
		{ (char*)"set_scale", (char*)"(JDJF)V", (void*)mesh_transform_set_scale },
		{ (char*)"set_morph", (char*)"(JDJF)V", (void*)mesh_transform_set_morph },
		{ (char*)"get_transform", (char*)"(JD)J", (void*)mesh_transform_get_transform },
		{ (char*)"get_translate", (char*)"(JD)J", (void*)mesh_transform_get_translate },
		{ (char*)"get_rotate", (char*)"(JD)J", (void*)mesh_transform_get_rotate },
		{ (char*)"get_scale", (char*)"(JD)J", (void*)mesh_transform_get_scale },
		{ (char*)"get_morph", (char*)"(JD)J", (void*)mesh_transform_get_morph },
		{ (char*)"has_transform_keys", (char*)"(J)Z", (void*)mesh_transform_has_transform_keys },
		{ (char*)"has_translate_keys", (char*)"(J)Z", (void*)mesh_transform_has_translate_keys },
		{ (char*)"has_rotate_keys", (char*)"(J)Z", (void*)mesh_transform_has_rotate_keys },
		{ (char*)"has_scale_keys", (char*)"(J)Z", (void*)mesh_transform_has_scale_keys },
		{ (char*)"has_morph_keys", (char*)"(J)Z", (void*)mesh_transform_has_morph_keys },
		{ (char*)"set_transform_1", (char*)"(JJ)V", (void*)mesh_transform_set_transform_1 },
		{ (char*)"set_transform_2", (char*)"(JJ)V", (void*)mesh_transform_set_transform_2 },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_transform_get_memory },
	};
	
	// Tellusim::MeshAnimation
	static jlong mesh_animation_new(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshAnimation(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_animation_new_1(TS_JNI_ARGS, jlong mesh, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshAnimation(toMesh(mesh), name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void mesh_animation_delete(TS_JNI_ARGS, jlong self) {
		delete (MeshAnimation*)self;
	}
	static jboolean mesh_animation_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toMeshAnimation(self) == toMeshAnimation(ptr));
	}
	static jlong mesh_animation_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newMeshAnimation(toMeshAnimation(self).clonePtr());
	}
	static void mesh_animation_clear_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAnimation(self).clearPtr();
	}
	static void mesh_animation_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAnimation(self).destroyPtr();
	}
	static void mesh_animation_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAnimation(self).acquirePtr();
	}
	static void mesh_animation_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAnimation(self).unacquirePtr();
	}
	static jboolean mesh_animation_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAnimation(self).isValidPtr();
	}
	static jboolean mesh_animation_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAnimation(self).isOwnerPtr();
	}
	static jboolean mesh_animation_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAnimation(self).isConstPtr();
	}
	static jint mesh_animation_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAnimation(self).getCountPtr();
	}
	static jlong mesh_animation_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshAnimation(self).getInternalPtr();
	}
	static void mesh_animation_clear(TS_JNI_ARGS, jlong self) {
		toMeshAnimation(self).clear();
	}
	static jint mesh_animation_get_index(TS_JNI_ARGS, jlong self) {
		return toMeshAnimation(self).getIndex();
	}
	static void mesh_animation_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toMeshAnimation(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring mesh_animation_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshAnimation(self).getName().get());
	}
	static void mesh_animation_set_mesh(TS_JNI_ARGS, jlong self, jlong mesh, jboolean check) {
		toMeshAnimation(self).setMesh(toMesh(mesh), (bool)check);
	}
	static jlong mesh_animation_get_mesh(TS_JNI_ARGS, jlong self) {
		return newMesh(toMeshAnimation(self).getMesh());
	}
	static jlong mesh_animation_get_mesh_1(TS_JNI_ARGS, jlong self) {
		return newMesh(toMeshAnimation(self).getMesh());
	}
	static jdouble mesh_animation_get_min_time(TS_JNI_ARGS, jlong self) {
		return toMeshAnimation(self).getMinTime();
	}
	static jdouble mesh_animation_get_max_time(TS_JNI_ARGS, jlong self) {
		return toMeshAnimation(self).getMaxTime();
	}
	static void mesh_animation_set_num_transforms(TS_JNI_ARGS, jlong self, jint num_transforms) {
		toMeshAnimation(self).setNumTransforms((uint32_t)num_transforms);
	}
	static jint mesh_animation_get_num_transforms(TS_JNI_ARGS, jlong self) {
		return toMeshAnimation(self).getNumTransforms();
	}
	static jlong mesh_animation_get_transform(TS_JNI_ARGS, jlong self, jint node) {
		return newMeshTransform(toMeshAnimation(self).getTransform((uint32_t)node));
	}
	static jlong mesh_animation_get_transform_1(TS_JNI_ARGS, jlong self, jint node) {
		return newMeshTransform(toMeshAnimation(self).getTransform((uint32_t)node));
	}
	static void mesh_animation_set_transform(TS_JNI_ARGS, jlong self, jdouble time, jint node, jlong transform, jfloat threshold) {
		toMeshAnimation(self).setTransform(time, (uint32_t)node, toMatrix4x3d(transform), threshold);
	}
	static void mesh_animation_set_translate(TS_JNI_ARGS, jlong self, jdouble time, jint node, jlong translate, jfloat threshold) {
		toMeshAnimation(self).setTranslate(time, (uint32_t)node, toVector3d(translate), threshold);
	}
	static void mesh_animation_set_rotate(TS_JNI_ARGS, jlong self, jdouble time, jint node, jlong rotate, jfloat threshold) {
		toMeshAnimation(self).setRotate(time, (uint32_t)node, toQuaternionf(rotate), threshold);
	}
	static void mesh_animation_set_scale(TS_JNI_ARGS, jlong self, jdouble time, jint node, jlong scale, jfloat threshold) {
		toMeshAnimation(self).setScale(time, (uint32_t)node, toVector3f(scale), threshold);
	}
	static void mesh_animation_set_morph(TS_JNI_ARGS, jlong self, jdouble time, jint node, jlong morph, jfloat threshold) {
		toMeshAnimation(self).setMorph(time, (uint32_t)node, toVector4f(morph), threshold);
	}
	static void mesh_animation_set_time(TS_JNI_ARGS, jlong self, jdouble time, jlong transform, jboolean loop, jdouble from, jdouble to) {
		toMeshAnimation(self).setTime(time, toMatrix4x3d(transform), (bool)loop, from, to);
	}
	static void mesh_animation_set_time_1(TS_JNI_ARGS, jlong self, jdouble time, jboolean loop, jdouble from, jdouble to) {
		toMeshAnimation(self).setTime(time, (bool)loop, from, to);
	}
	static jlong mesh_animation_get_local_transform(TS_JNI_ARGS, jlong self, jint node) {
		return newMatrix4x3d(toMeshAnimation(self).getLocalTransform((uint32_t)node));
	}
	static jlong mesh_animation_get_local_transform_1(TS_JNI_ARGS, jlong self, jlong node) {
		return newMatrix4x3d(toMeshAnimation(self).getLocalTransform(toMeshNode(node)));
	}
	static jlong mesh_animation_get_local_transform_2(TS_JNI_ARGS, jlong self, jlong joint) {
		return newMatrix4x3d(toMeshAnimation(self).getLocalTransform(toMeshJoint(joint)));
	}
	static jlong mesh_animation_get_global_transform(TS_JNI_ARGS, jlong self, jint node) {
		return newMatrix4x3d(toMeshAnimation(self).getGlobalTransform((uint32_t)node));
	}
	static jlong mesh_animation_get_global_transform_1(TS_JNI_ARGS, jlong self, jlong node) {
		return newMatrix4x3d(toMeshAnimation(self).getGlobalTransform(toMeshNode(node)));
	}
	static jlong mesh_animation_get_global_transform_2(TS_JNI_ARGS, jlong self, jlong joint) {
		return newMatrix4x3d(toMeshAnimation(self).getGlobalTransform(toMeshJoint(joint)));
	}
	static jlong mesh_animation_get_morph_transform(TS_JNI_ARGS, jlong self, jint node) {
		return newVector4f(toMeshAnimation(self).getMorphTransform((uint32_t)node));
	}
	static jlong mesh_animation_get_morph_transform_1(TS_JNI_ARGS, jlong self, jlong node) {
		return newVector4f(toMeshAnimation(self).getMorphTransform(toMeshNode(node)));
	}
	static jlong mesh_animation_get_bound_box(TS_JNI_ARGS, jlong self) {
		return newBoundBoxd(toMeshAnimation(self).getBoundBox());
	}
	static jlong mesh_animation_get_bound_box_1(TS_JNI_ARGS, jlong self, jlong node) {
		return newBoundBoxd(toMeshAnimation(self).getBoundBox(toMeshNode(node)));
	}
	static jlong mesh_animation_get_bound_box_2(TS_JNI_ARGS, jlong self, jlong geometry) {
		return newBoundBoxd(toMeshAnimation(self).getBoundBox(toMeshGeometry(geometry)));
	}
	static jlong mesh_animation_get_bound_box_3(TS_JNI_ARGS, jlong self, jlong geometry, jlong morph) {
		return newBoundBoxd(toMeshAnimation(self).getBoundBox(toMeshGeometry(geometry), toVector4f(morph)));
	}
	static void mesh_animation_set_transform_1(TS_JNI_ARGS, jlong self, jlong scale) {
		toMeshAnimation(self).setTransform(toVector3d(scale));
	}
	static void mesh_animation_set_transform_2(TS_JNI_ARGS, jlong self, jlong transform) {
		toMeshAnimation(self).setTransform(toMatrix4x3d(transform));
	}
	static void mesh_animation_optimize_transforms(TS_JNI_ARGS, jlong self, jfloat threshold) {
		toMeshAnimation(self).optimizeTransforms(threshold);
	}
	static jlong mesh_animation_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshAnimation(self).getMemory();
	}
	static const JNINativeMethod mesh_animation_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;)J", (void*)mesh_animation_new },
		{ (char*)"new_1", (char*)"(JLjava/lang/String;)J", (void*)mesh_animation_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_animation_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)mesh_animation_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)mesh_animation_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)mesh_animation_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)mesh_animation_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)mesh_animation_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)mesh_animation_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)mesh_animation_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)mesh_animation_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)mesh_animation_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)mesh_animation_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)mesh_animation_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_animation_clear },
		{ (char*)"get_index", (char*)"(J)I", (void*)mesh_animation_get_index },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)mesh_animation_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_animation_get_name },
		{ (char*)"set_mesh", (char*)"(JJZ)V", (void*)mesh_animation_set_mesh },
		{ (char*)"get_mesh", (char*)"(J)J", (void*)mesh_animation_get_mesh },
		{ (char*)"get_mesh_1", (char*)"(J)J", (void*)mesh_animation_get_mesh_1 },
		{ (char*)"get_min_time", (char*)"(J)D", (void*)mesh_animation_get_min_time },
		{ (char*)"get_max_time", (char*)"(J)D", (void*)mesh_animation_get_max_time },
		{ (char*)"set_num_transforms", (char*)"(JI)V", (void*)mesh_animation_set_num_transforms },
		{ (char*)"get_num_transforms", (char*)"(J)I", (void*)mesh_animation_get_num_transforms },
		{ (char*)"get_transform", (char*)"(JI)J", (void*)mesh_animation_get_transform },
		{ (char*)"get_transform_1", (char*)"(JI)J", (void*)mesh_animation_get_transform_1 },
		{ (char*)"set_transform", (char*)"(JDIJF)V", (void*)mesh_animation_set_transform },
		{ (char*)"set_translate", (char*)"(JDIJF)V", (void*)mesh_animation_set_translate },
		{ (char*)"set_rotate", (char*)"(JDIJF)V", (void*)mesh_animation_set_rotate },
		{ (char*)"set_scale", (char*)"(JDIJF)V", (void*)mesh_animation_set_scale },
		{ (char*)"set_morph", (char*)"(JDIJF)V", (void*)mesh_animation_set_morph },
		{ (char*)"set_time", (char*)"(JDJZDD)V", (void*)mesh_animation_set_time },
		{ (char*)"set_time_1", (char*)"(JDZDD)V", (void*)mesh_animation_set_time_1 },
		{ (char*)"get_local_transform", (char*)"(JI)J", (void*)mesh_animation_get_local_transform },
		{ (char*)"get_local_transform_1", (char*)"(JJ)J", (void*)mesh_animation_get_local_transform_1 },
		{ (char*)"get_local_transform_2", (char*)"(JJ)J", (void*)mesh_animation_get_local_transform_2 },
		{ (char*)"get_global_transform", (char*)"(JI)J", (void*)mesh_animation_get_global_transform },
		{ (char*)"get_global_transform_1", (char*)"(JJ)J", (void*)mesh_animation_get_global_transform_1 },
		{ (char*)"get_global_transform_2", (char*)"(JJ)J", (void*)mesh_animation_get_global_transform_2 },
		{ (char*)"get_morph_transform", (char*)"(JI)J", (void*)mesh_animation_get_morph_transform },
		{ (char*)"get_morph_transform_1", (char*)"(JJ)J", (void*)mesh_animation_get_morph_transform_1 },
		{ (char*)"get_bound_box", (char*)"(J)J", (void*)mesh_animation_get_bound_box },
		{ (char*)"get_bound_box_1", (char*)"(JJ)J", (void*)mesh_animation_get_bound_box_1 },
		{ (char*)"get_bound_box_2", (char*)"(JJ)J", (void*)mesh_animation_get_bound_box_2 },
		{ (char*)"get_bound_box_3", (char*)"(JJJ)J", (void*)mesh_animation_get_bound_box_3 },
		{ (char*)"set_transform_1", (char*)"(JJ)V", (void*)mesh_animation_set_transform_1 },
		{ (char*)"set_transform_2", (char*)"(JJ)V", (void*)mesh_animation_set_transform_2 },
		{ (char*)"optimize_transforms", (char*)"(JF)V", (void*)mesh_animation_optimize_transforms },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_animation_get_memory },
	};
	
	// Tellusim::MeshAttachment
	static jlong mesh_attachment_new(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshAttachment(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_attachment_new_1(TS_JNI_ARGS, jint type, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshAttachment((MeshAttachment::Type)type, name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong mesh_attachment_new_2(TS_JNI_ARGS, jlong node, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newMeshAttachment(toMeshNode(node), name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void mesh_attachment_delete(TS_JNI_ARGS, jlong self) {
		delete (MeshAttachment*)self;
	}
	static jboolean mesh_attachment_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toMeshAttachment(self) == toMeshAttachment(ptr));
	}
	static jlong mesh_attachment_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newMeshAttachment(toMeshAttachment(self).clonePtr());
	}
	static void mesh_attachment_clear_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAttachment(self).clearPtr();
	}
	static void mesh_attachment_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAttachment(self).destroyPtr();
	}
	static void mesh_attachment_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAttachment(self).acquirePtr();
	}
	static void mesh_attachment_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toMeshAttachment(self).unacquirePtr();
	}
	static jboolean mesh_attachment_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAttachment(self).isValidPtr();
	}
	static jboolean mesh_attachment_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAttachment(self).isOwnerPtr();
	}
	static jboolean mesh_attachment_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAttachment(self).isConstPtr();
	}
	static jint mesh_attachment_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toMeshAttachment(self).getCountPtr();
	}
	static jlong mesh_attachment_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshAttachment(self).getInternalPtr();
	}
	static void mesh_attachment_clear(TS_JNI_ARGS, jlong self) {
		toMeshAttachment(self).clear();
	}
	static void mesh_attachment_set_type(TS_JNI_ARGS, jlong self, jint type) {
		toMeshAttachment(self).setType((MeshAttachment::Type)type);
	}
	static jint mesh_attachment_get_type(TS_JNI_ARGS, jlong self) {
		return toMeshAttachment(self).getType();
	}
	static jstring mesh_attachment_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(MeshAttachment::getTypeName((MeshAttachment::Type)type));
	}
	static jstring mesh_attachment_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshAttachment(self).getTypeName());
	}
	static jboolean mesh_attachment_is_unknown(TS_JNI_ARGS, jlong self) {
		return toMeshAttachment(self).isUnknown();
	}
	static jboolean mesh_attachment_is_light(TS_JNI_ARGS, jlong self) {
		return toMeshAttachment(self).isLight();
	}
	static jboolean mesh_attachment_is_camera(TS_JNI_ARGS, jlong self) {
		return toMeshAttachment(self).isCamera();
	}
	static void mesh_attachment_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toMeshAttachment(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring mesh_attachment_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshAttachment(self).getName().get());
	}
	static void mesh_attachment_set_node(TS_JNI_ARGS, jlong self, jlong node, jboolean check) {
		toMeshAttachment(self).setNode(toMeshNode(node), (bool)check);
	}
	static jlong mesh_attachment_get_node(TS_JNI_ARGS, jlong self) {
		return newMeshNode(toMeshAttachment(self).getNode());
	}
	static jlong mesh_attachment_get_node_1(TS_JNI_ARGS, jlong self) {
		return newMeshNode(toMeshAttachment(self).getNode());
	}
	static void mesh_attachment_set_data(TS_JNI_ARGS, jlong self, jstring data) {
		const char *data_ = (data) ? env->GetStringUTFChars(data, nullptr) : nullptr;
		toMeshAttachment(self).setData(data_);
		env->ReleaseStringUTFChars(data, data_);
	}
	static void mesh_attachment_set_data_1(TS_JNI_ARGS, jlong self, jlong data) {
		toMeshAttachment(self).setData(toString(data));
	}
	static jstring mesh_attachment_get_data(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMeshAttachment(self).getData().get());
	}
	static void mesh_attachment_clear_parameters(TS_JNI_ARGS, jlong self) {
		toMeshAttachment(self).clearParameters();
	}
	static jboolean mesh_attachment_remove_parameter(TS_JNI_ARGS, jlong self, jstring type) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toMeshAttachment(self).removeParameter(type_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static void mesh_attachment_copy_parameters(TS_JNI_ARGS, jlong self, jlong attachment) {
		toMeshAttachment(self).copyParameters(toMeshAttachment(attachment));
	}
	static jint mesh_attachment_find_parameter(TS_JNI_ARGS, jlong self, jstring type) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		uint32_t ret_ = toMeshAttachment(self).findParameter(type_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jboolean mesh_attachment_has_parameter(TS_JNI_ARGS, jlong self, jstring type) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toMeshAttachment(self).hasParameter(type_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jint mesh_attachment_get_num_parameters(TS_JNI_ARGS, jlong self) {
		return toMeshAttachment(self).getNumParameters();
	}
	static jstring mesh_attachment_get_parameter_type(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toMeshAttachment(self).getParameterType((uint32_t)index).get());
	}
	static void mesh_attachment_add_parameter(TS_JNI_ARGS, jlong self, jstring type, jboolean value) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		toMeshAttachment(self).addParameter(type_, (bool)value);
		env->ReleaseStringUTFChars(type, type_);
	}
	static void mesh_attachment_add_parameter_1(TS_JNI_ARGS, jlong self, jstring type, jfloat value) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		toMeshAttachment(self).addParameter(type_, value);
		env->ReleaseStringUTFChars(type, type_);
	}
	static void mesh_attachment_add_parameter_2(TS_JNI_ARGS, jlong self, jstring type, jlong vector) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		toMeshAttachment(self).addParameter(type_, toVector4f(vector));
		env->ReleaseStringUTFChars(type, type_);
	}
	static void mesh_attachment_add_parameter_3(TS_JNI_ARGS, jlong self, jstring type, jlong color) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		toMeshAttachment(self).addParameter(type_, toColor(color));
		env->ReleaseStringUTFChars(type, type_);
	}
	static void mesh_attachment_add_parameter_4(TS_JNI_ARGS, jlong self, jstring type, jstring name) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toMeshAttachment(self).addParameter(type_, name_);
		env->ReleaseStringUTFChars(type, type_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void mesh_attachment_add_parameter_5(TS_JNI_ARGS, jlong self, jstring type, jlong name) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		toMeshAttachment(self).addParameter(type_, toString(name));
		env->ReleaseStringUTFChars(type, type_);
	}
	static jint mesh_attachment_get_parameter_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toMeshAttachment(self).getParameterFlags((uint32_t)index);
	}
	static jboolean mesh_attachment_has_parameter_flag(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return toMeshAttachment(self).hasParameterFlag((uint32_t)index, (MeshAttachment::Flags)flags);
	}
	static jboolean mesh_attachment_has_parameter_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return toMeshAttachment(self).hasParameterFlags((uint32_t)index, (MeshAttachment::Flags)flags);
	}
	static jboolean mesh_attachment_get_parameter_bool(TS_JNI_ARGS, jlong self, jint index, jboolean value) {
		return toMeshAttachment(self).getParameterBool((uint32_t)index, (bool)value);
	}
	static jfloat mesh_attachment_get_parameter_scalarf32(TS_JNI_ARGS, jlong self, jint index, jfloat value) {
		return toMeshAttachment(self).getParameterScalarf32((uint32_t)index, value);
	}
	static jlong mesh_attachment_get_parameter_vector4f(TS_JNI_ARGS, jlong self, jint index, jlong vector) {
		return newVector4f(toMeshAttachment(self).getParameterVector4f((uint32_t)index, toVector4f(vector)));
	}
	static jlong mesh_attachment_get_parameter_color(TS_JNI_ARGS, jlong self, jint index, jlong color) {
		return newColor(toMeshAttachment(self).getParameterColor((uint32_t)index, toColor(color)));
	}
	static jstring mesh_attachment_get_parameter_name(TS_JNI_ARGS, jlong self, jint index, jlong name) {
		return env->NewStringUTF(toMeshAttachment(self).getParameterName((uint32_t)index, toString(name)).get());
	}
	static jint mesh_attachment_get_parameter_flags_1(TS_JNI_ARGS, jlong self, jstring type) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		MeshAttachment::Flags ret_ = toMeshAttachment(self).getParameterFlags(type_);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jboolean mesh_attachment_has_parameter_flag_1(TS_JNI_ARGS, jlong self, jstring type, jint flags) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toMeshAttachment(self).hasParameterFlag(type_, (MeshAttachment::Flags)flags);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jboolean mesh_attachment_has_parameter_flags_1(TS_JNI_ARGS, jlong self, jstring type, jint flags) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toMeshAttachment(self).hasParameterFlags(type_, (MeshAttachment::Flags)flags);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jboolean mesh_attachment_get_parameter_bool_1(TS_JNI_ARGS, jlong self, jstring type, jboolean value) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		bool ret_ = toMeshAttachment(self).getParameterBool(type_, (bool)value);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jfloat mesh_attachment_get_parameter_scalarf32_1(TS_JNI_ARGS, jlong self, jstring type, jfloat value) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		float32_t ret_ = toMeshAttachment(self).getParameterScalarf32(type_, value);
		env->ReleaseStringUTFChars(type, type_);
		return ret_;
	}
	static jlong mesh_attachment_get_parameter_vector4f_1(TS_JNI_ARGS, jlong self, jstring type, jlong vector) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		const Vector4f ret_ = toMeshAttachment(self).getParameterVector4f(type_, toVector4f(vector));
		env->ReleaseStringUTFChars(type, type_);
		return newVector4f(ret_);
	}
	static jlong mesh_attachment_get_parameter_color_1(TS_JNI_ARGS, jlong self, jstring type, jlong color) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		const Color ret_ = toMeshAttachment(self).getParameterColor(type_, toColor(color));
		env->ReleaseStringUTFChars(type, type_);
		return newColor(ret_);
	}
	static jstring mesh_attachment_get_parameter_name_1(TS_JNI_ARGS, jlong self, jstring type, jlong name) {
		const char *type_ = (type) ? env->GetStringUTFChars(type, nullptr) : nullptr;
		String ret_ = toMeshAttachment(self).getParameterName(type_, toString(name));
		env->ReleaseStringUTFChars(type, type_);
		return env->NewStringUTF(ret_.get());
	}
	static void mesh_attachment_set_transform(TS_JNI_ARGS, jlong self, jlong scale) {
		toMeshAttachment(self).setTransform(toVector3f(scale));
	}
	static void mesh_attachment_set_transform_1(TS_JNI_ARGS, jlong self, jlong transform) {
		toMeshAttachment(self).setTransform(toMatrix4x3f(transform));
	}
	static jlong mesh_attachment_get_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3f(toMeshAttachment(self).getTransform());
	}
	static jint mesh_attachment_compare(TS_JNI_ARGS, jlong self, jlong attachment) {
		return toMeshAttachment(self).compare(toMeshAttachment(attachment));
	}
	static jlong mesh_attachment_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshAttachment(self).getMemory();
	}
	static const JNINativeMethod mesh_attachment_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;)J", (void*)mesh_attachment_new },
		{ (char*)"new_1", (char*)"(ILjava/lang/String;)J", (void*)mesh_attachment_new_1 },
		{ (char*)"new_2", (char*)"(JLjava/lang/String;)J", (void*)mesh_attachment_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_attachment_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)mesh_attachment_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)mesh_attachment_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)mesh_attachment_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)mesh_attachment_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)mesh_attachment_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)mesh_attachment_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)mesh_attachment_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)mesh_attachment_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)mesh_attachment_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)mesh_attachment_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)mesh_attachment_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_attachment_clear },
		{ (char*)"set_type", (char*)"(JI)V", (void*)mesh_attachment_set_type },
		{ (char*)"get_type", (char*)"(J)I", (void*)mesh_attachment_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)mesh_attachment_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)mesh_attachment_get_type_name_1 },
		{ (char*)"is_unknown", (char*)"(J)Z", (void*)mesh_attachment_is_unknown },
		{ (char*)"is_light", (char*)"(J)Z", (void*)mesh_attachment_is_light },
		{ (char*)"is_camera", (char*)"(J)Z", (void*)mesh_attachment_is_camera },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)mesh_attachment_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_attachment_get_name },
		{ (char*)"set_node", (char*)"(JJZ)V", (void*)mesh_attachment_set_node },
		{ (char*)"get_node", (char*)"(J)J", (void*)mesh_attachment_get_node },
		{ (char*)"get_node_1", (char*)"(J)J", (void*)mesh_attachment_get_node_1 },
		{ (char*)"set_data", (char*)"(JLjava/lang/String;)V", (void*)mesh_attachment_set_data },
		{ (char*)"set_data_1", (char*)"(JJ)V", (void*)mesh_attachment_set_data_1 },
		{ (char*)"get_data", (char*)"(J)Ljava/lang/String;", (void*)mesh_attachment_get_data },
		{ (char*)"clear_parameters", (char*)"(J)V", (void*)mesh_attachment_clear_parameters },
		{ (char*)"remove_parameter", (char*)"(JLjava/lang/String;)Z", (void*)mesh_attachment_remove_parameter },
		{ (char*)"copy_parameters", (char*)"(JJ)V", (void*)mesh_attachment_copy_parameters },
		{ (char*)"find_parameter", (char*)"(JLjava/lang/String;)I", (void*)mesh_attachment_find_parameter },
		{ (char*)"has_parameter", (char*)"(JLjava/lang/String;)Z", (void*)mesh_attachment_has_parameter },
		{ (char*)"get_num_parameters", (char*)"(J)I", (void*)mesh_attachment_get_num_parameters },
		{ (char*)"get_parameter_type", (char*)"(JI)Ljava/lang/String;", (void*)mesh_attachment_get_parameter_type },
		{ (char*)"add_parameter", (char*)"(JLjava/lang/String;Z)V", (void*)mesh_attachment_add_parameter },
		{ (char*)"add_parameter_1", (char*)"(JLjava/lang/String;F)V", (void*)mesh_attachment_add_parameter_1 },
		{ (char*)"add_parameter_2", (char*)"(JLjava/lang/String;J)V", (void*)mesh_attachment_add_parameter_2 },
		{ (char*)"add_parameter_3", (char*)"(JLjava/lang/String;J)V", (void*)mesh_attachment_add_parameter_3 },
		{ (char*)"add_parameter_4", (char*)"(JLjava/lang/String;Ljava/lang/String;)V", (void*)mesh_attachment_add_parameter_4 },
		{ (char*)"add_parameter_5", (char*)"(JLjava/lang/String;J)V", (void*)mesh_attachment_add_parameter_5 },
		{ (char*)"get_parameter_flags", (char*)"(JI)I", (void*)mesh_attachment_get_parameter_flags },
		{ (char*)"has_parameter_flag", (char*)"(JII)Z", (void*)mesh_attachment_has_parameter_flag },
		{ (char*)"has_parameter_flags", (char*)"(JII)Z", (void*)mesh_attachment_has_parameter_flags },
		{ (char*)"get_parameter_bool", (char*)"(JIZ)Z", (void*)mesh_attachment_get_parameter_bool },
		{ (char*)"get_parameter_scalarf32", (char*)"(JIF)F", (void*)mesh_attachment_get_parameter_scalarf32 },
		{ (char*)"get_parameter_vector4f", (char*)"(JIJ)J", (void*)mesh_attachment_get_parameter_vector4f },
		{ (char*)"get_parameter_color", (char*)"(JIJ)J", (void*)mesh_attachment_get_parameter_color },
		{ (char*)"get_parameter_name", (char*)"(JIJ)Ljava/lang/String;", (void*)mesh_attachment_get_parameter_name },
		{ (char*)"get_parameter_flags_1", (char*)"(JLjava/lang/String;)I", (void*)mesh_attachment_get_parameter_flags_1 },
		{ (char*)"has_parameter_flag_1", (char*)"(JLjava/lang/String;I)Z", (void*)mesh_attachment_has_parameter_flag_1 },
		{ (char*)"has_parameter_flags_1", (char*)"(JLjava/lang/String;I)Z", (void*)mesh_attachment_has_parameter_flags_1 },
		{ (char*)"get_parameter_bool_1", (char*)"(JLjava/lang/String;Z)Z", (void*)mesh_attachment_get_parameter_bool_1 },
		{ (char*)"get_parameter_scalarf32_1", (char*)"(JLjava/lang/String;F)F", (void*)mesh_attachment_get_parameter_scalarf32_1 },
		{ (char*)"get_parameter_vector4f_1", (char*)"(JLjava/lang/String;J)J", (void*)mesh_attachment_get_parameter_vector4f_1 },
		{ (char*)"get_parameter_color_1", (char*)"(JLjava/lang/String;J)J", (void*)mesh_attachment_get_parameter_color_1 },
		{ (char*)"get_parameter_name_1", (char*)"(JLjava/lang/String;J)Ljava/lang/String;", (void*)mesh_attachment_get_parameter_name_1 },
		{ (char*)"set_transform", (char*)"(JJ)V", (void*)mesh_attachment_set_transform },
		{ (char*)"set_transform_1", (char*)"(JJ)V", (void*)mesh_attachment_set_transform_1 },
		{ (char*)"get_transform", (char*)"(J)J", (void*)mesh_attachment_get_transform },
		{ (char*)"compare_", (char*)"(JJ)I", (void*)mesh_attachment_compare },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_attachment_get_memory },
	};
	
	// Tellusim::Mesh
	static jlong mesh_new(TS_JNI_ARGS) {
		return newMesh();
	}
	static void mesh_delete(TS_JNI_ARGS, jlong self) {
		delete (Mesh*)self;
	}
	static jboolean mesh_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toMesh(self) == toMesh(ptr));
	}
	static jlong mesh_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newMesh(toMesh(self).clonePtr());
	}
	static void mesh_clear_ptr(TS_JNI_ARGS, jlong self) {
		toMesh(self).clearPtr();
	}
	static void mesh_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toMesh(self).destroyPtr();
	}
	static void mesh_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toMesh(self).acquirePtr();
	}
	static void mesh_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toMesh(self).unacquirePtr();
	}
	static jboolean mesh_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toMesh(self).isValidPtr();
	}
	static jboolean mesh_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toMesh(self).isOwnerPtr();
	}
	static jboolean mesh_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toMesh(self).isConstPtr();
	}
	static jint mesh_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toMesh(self).getCountPtr();
	}
	static jlong mesh_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMesh(self).getInternalPtr();
	}
	static void mesh_clear(TS_JNI_ARGS, jlong self) {
		toMesh(self).clear();
	}
	static jboolean mesh_is_loaded(TS_JNI_ARGS, jlong self) {
		return toMesh(self).isLoaded();
	}
	static jboolean mesh_info(TS_JNI_ARGS, jlong self, jstring name, jint flags, jlong async) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toMesh(self).info(name_, (Mesh::Flags)flags, (Async*)async);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean mesh_info_1(TS_JNI_ARGS, jlong self, jlong name, jint flags, jlong async) {
		return toMesh(self).info(toString(name), (Mesh::Flags)flags, (Async*)async);
	}
	static jboolean mesh_info_2(TS_JNI_ARGS, jlong self, jlong stream, jint flags, jlong async) {
		return toMesh(self).info(toStream(stream), (Mesh::Flags)flags, (Async*)async);
	}
	static jboolean mesh_info_3(TS_JNI_ARGS, jlong self, jstring name, jlong async) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toMesh(self).info(name_, (Async*)async);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean mesh_info_4(TS_JNI_ARGS, jlong self, jlong name, jlong async) {
		return toMesh(self).info(toString(name), (Async*)async);
	}
	static jboolean mesh_info_5(TS_JNI_ARGS, jlong self, jlong stream, jlong async) {
		return toMesh(self).info(toStream(stream), (Async*)async);
	}
	static jboolean mesh_load(TS_JNI_ARGS, jlong self, jstring name, jint flags, jlong async) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toMesh(self).load(name_, (Mesh::Flags)flags, (Async*)async);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean mesh_load_1(TS_JNI_ARGS, jlong self, jlong name, jint flags, jlong async) {
		return toMesh(self).load(toString(name), (Mesh::Flags)flags, (Async*)async);
	}
	static jboolean mesh_load_2(TS_JNI_ARGS, jlong self, jlong stream, jint flags, jlong async) {
		return toMesh(self).load(toStream(stream), (Mesh::Flags)flags, (Async*)async);
	}
	static jboolean mesh_load_3(TS_JNI_ARGS, jlong self, jstring name, jlong async) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toMesh(self).load(name_, (Async*)async);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean mesh_load_4(TS_JNI_ARGS, jlong self, jlong name, jlong async) {
		return toMesh(self).load(toString(name), (Async*)async);
	}
	static jboolean mesh_load_5(TS_JNI_ARGS, jlong self, jlong stream, jlong async) {
		return toMesh(self).load(toStream(stream), (Async*)async);
	}
	static jboolean mesh_save(TS_JNI_ARGS, jlong self, jstring name, jint flags) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toMesh(self).save(name_, (Mesh::Flags)flags);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean mesh_save_1(TS_JNI_ARGS, jlong self, jlong name, jint flags) {
		return toMesh(self).save(toString(name), (Mesh::Flags)flags);
	}
	static jboolean mesh_save_2(TS_JNI_ARGS, jlong self, jlong stream, jint flags) {
		return toMesh(self).save(toStream(stream), (Mesh::Flags)flags);
	}
	static void mesh_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toMesh(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring mesh_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMesh(self).getName().get());
	}
	static jboolean mesh_set_basis(TS_JNI_ARGS, jlong self, jint front, jint right, jint up) {
		return toMesh(self).setBasis((Mesh::Axis)front, (Mesh::Axis)right, (Mesh::Axis)up);
	}
	static jboolean mesh_set_basis_1(TS_JNI_ARGS, jlong self, jint basis) {
		return toMesh(self).setBasis((Mesh::Basis)basis);
	}
	static jint mesh_get_front_axis(TS_JNI_ARGS, jlong self) {
		return toMesh(self).getFrontAxis();
	}
	static jint mesh_get_right_axis(TS_JNI_ARGS, jlong self) {
		return toMesh(self).getRightAxis();
	}
	static jint mesh_get_up_axis(TS_JNI_ARGS, jlong self) {
		return toMesh(self).getUpAxis();
	}
	static jint mesh_get_basis(TS_JNI_ARGS, jlong self) {
		return toMesh(self).getBasis();
	}
	static jstring mesh_get_front_axis_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMesh(self).getFrontAxisName());
	}
	static jstring mesh_get_right_axis_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMesh(self).getRightAxisName());
	}
	static jstring mesh_get_up_axis_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMesh(self).getUpAxisName());
	}
	static jstring mesh_get_basis_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toMesh(self).getBasisName().get());
	}
	static void mesh_clear_nodes(TS_JNI_ARGS, jlong self) {
		toMesh(self).clearNodes();
	}
	static void mesh_reserve_nodes(TS_JNI_ARGS, jlong self, jint num_nodes) {
		toMesh(self).reserveNodes((uint32_t)num_nodes);
	}
	static jint mesh_add_node(TS_JNI_ARGS, jlong self, jlong node, jboolean check) {
		return toMesh(self).addNode(toMeshNode(node), (bool)check);
	}
	static jboolean mesh_remove_node(TS_JNI_ARGS, jlong self, jlong node) {
		return toMesh(self).removeNode(toMeshNode(node));
	}
	static jint mesh_find_node(TS_JNI_ARGS, jlong self, jlong node) {
		return toMesh(self).findNode(toMeshNode(node));
	}
	static jint mesh_find_node_1(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toMesh(self).findNode(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint mesh_get_num_nodes(TS_JNI_ARGS, jlong self) {
		return toMesh(self).getNumNodes();
	}
	static jlong mesh_get_node(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshNode(toMesh(self).getNode((uint32_t)index));
	}
	static jlong mesh_get_node_1(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshNode(toMesh(self).getNode((uint32_t)index));
	}
	static void mesh_create_local_transforms(TS_JNI_ARGS, jlong self, jlong itransform) {
		toMesh(self).createLocalTransforms(toMatrix4x3d(itransform));
	}
	static void mesh_create_global_transforms(TS_JNI_ARGS, jlong self, jlong transform) {
		toMesh(self).createGlobalTransforms(toMatrix4x3d(transform));
	}
	static void mesh_clear_geometries(TS_JNI_ARGS, jlong self) {
		toMesh(self).clearGeometries();
	}
	static void mesh_reserve_geometries(TS_JNI_ARGS, jlong self, jint num_geometries) {
		toMesh(self).reserveGeometries((uint32_t)num_geometries);
	}
	static jint mesh_add_geometry(TS_JNI_ARGS, jlong self, jlong geometry, jboolean check) {
		return toMesh(self).addGeometry(toMeshGeometry(geometry), (bool)check);
	}
	static jint mesh_add_geometry_1(TS_JNI_ARGS, jlong self, jlong geometry, jlong node, jboolean check) {
		return toMesh(self).addGeometry(toMeshGeometry(geometry), toMeshNode(node), (bool)check);
	}
	static jboolean mesh_remove_geometry(TS_JNI_ARGS, jlong self, jlong geometry) {
		return toMesh(self).removeGeometry(toMeshGeometry(geometry));
	}
	static jboolean mesh_replace_geometry(TS_JNI_ARGS, jlong self, jlong old_geometry, jlong geometry) {
		return toMesh(self).replaceGeometry(toMeshGeometry(old_geometry), toMeshGeometry(geometry));
	}
	static jint mesh_find_geometry(TS_JNI_ARGS, jlong self, jlong geometry) {
		return toMesh(self).findGeometry(toMeshGeometry(geometry));
	}
	static jint mesh_find_geometry_1(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toMesh(self).findGeometry(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint mesh_get_num_geometries(TS_JNI_ARGS, jlong self) {
		return toMesh(self).getNumGeometries();
	}
	static jlong mesh_get_geometry(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshGeometry(toMesh(self).getGeometry((uint32_t)index));
	}
	static jlong mesh_get_geometry_1(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshGeometry(toMesh(self).getGeometry((uint32_t)index));
	}
	static jboolean mesh_has_geometry_indices(TS_JNI_ARGS, jlong self, jint type) {
		return toMesh(self).hasGeometryIndices((MeshIndices::Type)type);
	}
	static jboolean mesh_has_geometry_attribute(TS_JNI_ARGS, jlong self, jint type) {
		return toMesh(self).hasGeometryAttribute((MeshAttribute::Type)type);
	}
	static jlong mesh_get_num_geometry_positions(TS_JNI_ARGS, jlong self) {
		return (jlong)toMesh(self).getNumGeometryPositions();
	}
	static jlong mesh_get_num_geometry_primitives(TS_JNI_ARGS, jlong self) {
		return (jlong)toMesh(self).getNumGeometryPrimitives();
	}
	static void mesh_clear_animations(TS_JNI_ARGS, jlong self) {
		toMesh(self).clearAnimations();
	}
	static void mesh_reserve_animations(TS_JNI_ARGS, jlong self, jint num_animations) {
		toMesh(self).reserveAnimations((uint32_t)num_animations);
	}
	static jint mesh_add_animation(TS_JNI_ARGS, jlong self, jlong animation, jboolean check) {
		return toMesh(self).addAnimation(toMeshAnimation(animation), (bool)check);
	}
	static jboolean mesh_remove_animation(TS_JNI_ARGS, jlong self, jlong animation) {
		return toMesh(self).removeAnimation(toMeshAnimation(animation));
	}
	static jboolean mesh_replace_animation(TS_JNI_ARGS, jlong self, jlong old_animation, jlong animation) {
		return toMesh(self).replaceAnimation(toMeshAnimation(old_animation), toMeshAnimation(animation));
	}
	static jint mesh_find_animation(TS_JNI_ARGS, jlong self, jlong animation) {
		return toMesh(self).findAnimation(toMeshAnimation(animation));
	}
	static jint mesh_find_animation_1(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toMesh(self).findAnimation(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint mesh_get_num_animations(TS_JNI_ARGS, jlong self) {
		return toMesh(self).getNumAnimations();
	}
	static jlong mesh_get_animation(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshAnimation(toMesh(self).getAnimation((uint32_t)index));
	}
	static jlong mesh_get_animation_1(TS_JNI_ARGS, jlong self, jint index) {
		return newMeshAnimation(toMesh(self).getAnimation((uint32_t)index));
	}
	static jlong mesh_get_bound_box(TS_JNI_ARGS, jlong self) {
		return newBoundBoxd(toMesh(self).getBoundBox());
	}
	static jlong mesh_get_bound_box_1(TS_JNI_ARGS, jlong self, jlong node) {
		return newBoundBoxd(toMesh(self).getBoundBox(toMeshNode(node)));
	}
	static jlong mesh_get_bound_box_2(TS_JNI_ARGS, jlong self, jlong geometry) {
		return newBoundBoxd(toMesh(self).getBoundBox(toMeshGeometry(geometry)));
	}
	static jboolean mesh_create_bounds(TS_JNI_ARGS, jlong self, jboolean force, jlong async) {
		return toMesh(self).createBounds((bool)force, (Async*)async);
	}
	static jboolean mesh_create_bounds_1(TS_JNI_ARGS, jlong self, jlong async) {
		return toMesh(self).createBounds((Async*)async);
	}
	static jboolean mesh_create_basis(TS_JNI_ARGS, jlong self, jboolean force, jlong async) {
		return toMesh(self).createBasis((bool)force, (Async*)async);
	}
	static jboolean mesh_create_basis_1(TS_JNI_ARGS, jlong self, jfloat angle, jboolean force, jlong async) {
		return toMesh(self).createBasis(angle, (bool)force, (Async*)async);
	}
	static jboolean mesh_create_basis_2(TS_JNI_ARGS, jlong self, jlong async) {
		return toMesh(self).createBasis((Async*)async);
	}
	static jboolean mesh_create_basis_3(TS_JNI_ARGS, jlong self, jfloat angle, jlong async) {
		return toMesh(self).createBasis(angle, (Async*)async);
	}
	static jboolean mesh_create_normals(TS_JNI_ARGS, jlong self, jboolean force, jlong async) {
		return toMesh(self).createNormals((bool)force, (Async*)async);
	}
	static jboolean mesh_create_normals_1(TS_JNI_ARGS, jlong self, jfloat angle, jboolean force, jlong async) {
		return toMesh(self).createNormals(angle, (bool)force, (Async*)async);
	}
	static jboolean mesh_create_normals_2(TS_JNI_ARGS, jlong self, jlong async) {
		return toMesh(self).createNormals((Async*)async);
	}
	static jboolean mesh_create_normals_3(TS_JNI_ARGS, jlong self, jfloat angle, jlong async) {
		return toMesh(self).createNormals(angle, (Async*)async);
	}
	static jboolean mesh_create_tangents(TS_JNI_ARGS, jlong self, jboolean force, jlong async) {
		return toMesh(self).createTangents((bool)force, (Async*)async);
	}
	static jboolean mesh_create_tangents_1(TS_JNI_ARGS, jlong self, jlong async) {
		return toMesh(self).createTangents((Async*)async);
	}
	static jboolean mesh_create_islands(TS_JNI_ARGS, jlong self, jint max_attributes, jint max_primitives, jboolean force, jlong async) {
		return toMesh(self).createIslands((uint32_t)max_attributes, (uint32_t)max_primitives, (bool)force, (Async*)async);
	}
	static jboolean mesh_create_islands_1(TS_JNI_ARGS, jlong self, jint max_attributes, jint max_primitives, jlong async) {
		return toMesh(self).createIslands((uint32_t)max_attributes, (uint32_t)max_primitives, (Async*)async);
	}
	static jboolean mesh_optimize_indices(TS_JNI_ARGS, jlong self, jint cache, jboolean transparent, jlong async) {
		return toMesh(self).optimizeIndices((uint32_t)cache, (bool)transparent, (Async*)async);
	}
	static jboolean mesh_optimize_indices_1(TS_JNI_ARGS, jlong self, jlong async) {
		return toMesh(self).optimizeIndices((Async*)async);
	}
	static jboolean mesh_optimize_indices_2(TS_JNI_ARGS, jlong self, jint cache, jlong async) {
		return toMesh(self).optimizeIndices((uint32_t)cache, (Async*)async);
	}
	static jboolean mesh_optimize_attributes(TS_JNI_ARGS, jlong self, jlong async) {
		return toMesh(self).optimizeAttributes((Async*)async);
	}
	static void mesh_optimize_materials(TS_JNI_ARGS, jlong self) {
		toMesh(self).optimizeMaterials();
	}
	static jboolean mesh_optimize_winding(TS_JNI_ARGS, jlong self, jboolean clockwise) {
		return toMesh(self).optimizeWinding((bool)clockwise);
	}
	static void mesh_optimize_geometries(TS_JNI_ARGS, jlong self, jfloat threshold, jint depth) {
		toMesh(self).optimizeGeometries(threshold, (uint32_t)depth);
	}
	static void mesh_optimize_animations(TS_JNI_ARGS, jlong self, jfloat threshold) {
		toMesh(self).optimizeAnimations(threshold);
	}
	static jboolean mesh_optimize_order(TS_JNI_ARGS, jlong self) {
		return toMesh(self).optimizeOrder();
	}
	static void mesh_merge_geometries(TS_JNI_ARGS, jlong self) {
		toMesh(self).mergeGeometries();
	}
	static jboolean mesh_pack_attributes(TS_JNI_ARGS, jlong self, jboolean remove) {
		return toMesh(self).packAttributes((bool)remove);
	}
	static jboolean mesh_unpack_attributes(TS_JNI_ARGS, jlong self, jboolean remove) {
		return toMesh(self).unpackAttributes((bool)remove);
	}
	static jboolean mesh_set_transform(TS_JNI_ARGS, jlong self, jlong scale) {
		return toMesh(self).setTransform(toVector3d(scale));
	}
	static jlong mesh_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMesh(self).getMemory();
	}
	static const JNINativeMethod mesh_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mesh_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)mesh_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)mesh_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)mesh_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)mesh_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)mesh_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)mesh_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)mesh_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)mesh_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)mesh_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)mesh_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)mesh_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_clear },
		{ (char*)"is_loaded", (char*)"(J)Z", (void*)mesh_is_loaded },
		{ (char*)"info_", (char*)"(JLjava/lang/String;IJ)Z", (void*)mesh_info },
		{ (char*)"info_1", (char*)"(JJIJ)Z", (void*)mesh_info_1 },
		{ (char*)"info_2", (char*)"(JJIJ)Z", (void*)mesh_info_2 },
		{ (char*)"info_3", (char*)"(JLjava/lang/String;J)Z", (void*)mesh_info_3 },
		{ (char*)"info_4", (char*)"(JJJ)Z", (void*)mesh_info_4 },
		{ (char*)"info_5", (char*)"(JJJ)Z", (void*)mesh_info_5 },
		{ (char*)"load_", (char*)"(JLjava/lang/String;IJ)Z", (void*)mesh_load },
		{ (char*)"load_1", (char*)"(JJIJ)Z", (void*)mesh_load_1 },
		{ (char*)"load_2", (char*)"(JJIJ)Z", (void*)mesh_load_2 },
		{ (char*)"load_3", (char*)"(JLjava/lang/String;J)Z", (void*)mesh_load_3 },
		{ (char*)"load_4", (char*)"(JJJ)Z", (void*)mesh_load_4 },
		{ (char*)"load_5", (char*)"(JJJ)Z", (void*)mesh_load_5 },
		{ (char*)"save_", (char*)"(JLjava/lang/String;I)Z", (void*)mesh_save },
		{ (char*)"save_1", (char*)"(JJI)Z", (void*)mesh_save_1 },
		{ (char*)"save_2", (char*)"(JJI)Z", (void*)mesh_save_2 },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)mesh_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_get_name },
		{ (char*)"set_basis", (char*)"(JIII)Z", (void*)mesh_set_basis },
		{ (char*)"set_basis_1", (char*)"(JI)Z", (void*)mesh_set_basis_1 },
		{ (char*)"get_front_axis", (char*)"(J)I", (void*)mesh_get_front_axis },
		{ (char*)"get_right_axis", (char*)"(J)I", (void*)mesh_get_right_axis },
		{ (char*)"get_up_axis", (char*)"(J)I", (void*)mesh_get_up_axis },
		{ (char*)"get_basis", (char*)"(J)I", (void*)mesh_get_basis },
		{ (char*)"get_front_axis_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_get_front_axis_name },
		{ (char*)"get_right_axis_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_get_right_axis_name },
		{ (char*)"get_up_axis_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_get_up_axis_name },
		{ (char*)"get_basis_name", (char*)"(J)Ljava/lang/String;", (void*)mesh_get_basis_name },
		{ (char*)"clear_nodes", (char*)"(J)V", (void*)mesh_clear_nodes },
		{ (char*)"reserve_nodes", (char*)"(JI)V", (void*)mesh_reserve_nodes },
		{ (char*)"add_node", (char*)"(JJZ)I", (void*)mesh_add_node },
		{ (char*)"remove_node", (char*)"(JJ)Z", (void*)mesh_remove_node },
		{ (char*)"find_node", (char*)"(JJ)I", (void*)mesh_find_node },
		{ (char*)"find_node_1", (char*)"(JLjava/lang/String;)I", (void*)mesh_find_node_1 },
		{ (char*)"get_num_nodes", (char*)"(J)I", (void*)mesh_get_num_nodes },
		{ (char*)"get_node", (char*)"(JI)J", (void*)mesh_get_node },
		{ (char*)"get_node_1", (char*)"(JI)J", (void*)mesh_get_node_1 },
		{ (char*)"create_local_transforms", (char*)"(JJ)V", (void*)mesh_create_local_transforms },
		{ (char*)"create_global_transforms", (char*)"(JJ)V", (void*)mesh_create_global_transforms },
		{ (char*)"clear_geometries", (char*)"(J)V", (void*)mesh_clear_geometries },
		{ (char*)"reserve_geometries", (char*)"(JI)V", (void*)mesh_reserve_geometries },
		{ (char*)"add_geometry", (char*)"(JJZ)I", (void*)mesh_add_geometry },
		{ (char*)"add_geometry_1", (char*)"(JJJZ)I", (void*)mesh_add_geometry_1 },
		{ (char*)"remove_geometry", (char*)"(JJ)Z", (void*)mesh_remove_geometry },
		{ (char*)"replace_geometry", (char*)"(JJJ)Z", (void*)mesh_replace_geometry },
		{ (char*)"find_geometry", (char*)"(JJ)I", (void*)mesh_find_geometry },
		{ (char*)"find_geometry_1", (char*)"(JLjava/lang/String;)I", (void*)mesh_find_geometry_1 },
		{ (char*)"get_num_geometries", (char*)"(J)I", (void*)mesh_get_num_geometries },
		{ (char*)"get_geometry", (char*)"(JI)J", (void*)mesh_get_geometry },
		{ (char*)"get_geometry_1", (char*)"(JI)J", (void*)mesh_get_geometry_1 },
		{ (char*)"has_geometry_indices", (char*)"(JI)Z", (void*)mesh_has_geometry_indices },
		{ (char*)"has_geometry_attribute", (char*)"(JI)Z", (void*)mesh_has_geometry_attribute },
		{ (char*)"get_num_geometry_positions", (char*)"(J)J", (void*)mesh_get_num_geometry_positions },
		{ (char*)"get_num_geometry_primitives", (char*)"(J)J", (void*)mesh_get_num_geometry_primitives },
		{ (char*)"clear_animations", (char*)"(J)V", (void*)mesh_clear_animations },
		{ (char*)"reserve_animations", (char*)"(JI)V", (void*)mesh_reserve_animations },
		{ (char*)"add_animation", (char*)"(JJZ)I", (void*)mesh_add_animation },
		{ (char*)"remove_animation", (char*)"(JJ)Z", (void*)mesh_remove_animation },
		{ (char*)"replace_animation", (char*)"(JJJ)Z", (void*)mesh_replace_animation },
		{ (char*)"find_animation", (char*)"(JJ)I", (void*)mesh_find_animation },
		{ (char*)"find_animation_1", (char*)"(JLjava/lang/String;)I", (void*)mesh_find_animation_1 },
		{ (char*)"get_num_animations", (char*)"(J)I", (void*)mesh_get_num_animations },
		{ (char*)"get_animation", (char*)"(JI)J", (void*)mesh_get_animation },
		{ (char*)"get_animation_1", (char*)"(JI)J", (void*)mesh_get_animation_1 },
		{ (char*)"get_bound_box", (char*)"(J)J", (void*)mesh_get_bound_box },
		{ (char*)"get_bound_box_1", (char*)"(JJ)J", (void*)mesh_get_bound_box_1 },
		{ (char*)"get_bound_box_2", (char*)"(JJ)J", (void*)mesh_get_bound_box_2 },
		{ (char*)"create_bounds", (char*)"(JZJ)Z", (void*)mesh_create_bounds },
		{ (char*)"create_bounds_1", (char*)"(JJ)Z", (void*)mesh_create_bounds_1 },
		{ (char*)"create_basis", (char*)"(JZJ)Z", (void*)mesh_create_basis },
		{ (char*)"create_basis_1", (char*)"(JFZJ)Z", (void*)mesh_create_basis_1 },
		{ (char*)"create_basis_2", (char*)"(JJ)Z", (void*)mesh_create_basis_2 },
		{ (char*)"create_basis_3", (char*)"(JFJ)Z", (void*)mesh_create_basis_3 },
		{ (char*)"create_normals", (char*)"(JZJ)Z", (void*)mesh_create_normals },
		{ (char*)"create_normals_1", (char*)"(JFZJ)Z", (void*)mesh_create_normals_1 },
		{ (char*)"create_normals_2", (char*)"(JJ)Z", (void*)mesh_create_normals_2 },
		{ (char*)"create_normals_3", (char*)"(JFJ)Z", (void*)mesh_create_normals_3 },
		{ (char*)"create_tangents", (char*)"(JZJ)Z", (void*)mesh_create_tangents },
		{ (char*)"create_tangents_1", (char*)"(JJ)Z", (void*)mesh_create_tangents_1 },
		{ (char*)"create_islands", (char*)"(JIIZJ)Z", (void*)mesh_create_islands },
		{ (char*)"create_islands_1", (char*)"(JIIJ)Z", (void*)mesh_create_islands_1 },
		{ (char*)"optimize_indices", (char*)"(JIZJ)Z", (void*)mesh_optimize_indices },
		{ (char*)"optimize_indices_1", (char*)"(JJ)Z", (void*)mesh_optimize_indices_1 },
		{ (char*)"optimize_indices_2", (char*)"(JIJ)Z", (void*)mesh_optimize_indices_2 },
		{ (char*)"optimize_attributes", (char*)"(JJ)Z", (void*)mesh_optimize_attributes },
		{ (char*)"optimize_materials", (char*)"(J)V", (void*)mesh_optimize_materials },
		{ (char*)"optimize_winding", (char*)"(JZ)Z", (void*)mesh_optimize_winding },
		{ (char*)"optimize_geometries", (char*)"(JFI)V", (void*)mesh_optimize_geometries },
		{ (char*)"optimize_animations", (char*)"(JF)V", (void*)mesh_optimize_animations },
		{ (char*)"optimize_order", (char*)"(J)Z", (void*)mesh_optimize_order },
		{ (char*)"merge_geometries", (char*)"(J)V", (void*)mesh_merge_geometries },
		{ (char*)"pack_attributes", (char*)"(JZ)Z", (void*)mesh_pack_attributes },
		{ (char*)"unpack_attributes", (char*)"(JZ)Z", (void*)mesh_unpack_attributes },
		{ (char*)"set_transform", (char*)"(JJ)Z", (void*)mesh_set_transform },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_get_memory },
	};
	
	// Tellusim::Json
	static jlong json_new(TS_JNI_ARGS) {
		return newJson();
	}
	static jlong json_new_1(TS_JNI_ARGS, jint type) {
		return newJson((Json::Type)type);
	}
	static jlong json_new_2(TS_JNI_ARGS, jstring name, jint type) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newJson(name_, (Json::Type)type);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong json_new_3(TS_JNI_ARGS, jlong name, jint type) {
		return newJson(toString(name), (Json::Type)type);
	}
	static jlong json_new_4(TS_JNI_ARGS, jlongArray parent, jstring name, jint type) {
		Array<Json> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toJson(parent__[i]);
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newJson(parent_.get(), name_, (Json::Type)type);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong json_new_5(TS_JNI_ARGS, jlongArray parent, jlong name, jint type) {
		Array<Json> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toJson(parent__[i]);
		jlong ret_ = newJson(parent_.get(), toString(name), (Json::Type)type);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void json_delete(TS_JNI_ARGS, jlong self) {
		delete (Json*)self;
	}
	static jboolean json_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toJson(self) == toJson(ptr));
	}
	static jlong json_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newJson(toJson(self).clonePtr());
	}
	static void json_clear_ptr(TS_JNI_ARGS, jlong self) {
		toJson(self).clearPtr();
	}
	static void json_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toJson(self).destroyPtr();
	}
	static void json_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toJson(self).acquirePtr();
	}
	static void json_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toJson(self).unacquirePtr();
	}
	static jboolean json_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toJson(self).isValidPtr();
	}
	static jboolean json_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toJson(self).isOwnerPtr();
	}
	static jboolean json_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toJson(self).isConstPtr();
	}
	static jint json_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toJson(self).getCountPtr();
	}
	static jlong json_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toJson(self).getInternalPtr();
	}
	static void json_clear(TS_JNI_ARGS, jlong self) {
		toJson(self).clear();
	}
	static jboolean json_create(TS_JNI_ARGS, jlong self, jstring str, jlong size, jboolean owner) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		bool ret_ = toJson(self).create(str_, (size_t)size, (bool)owner);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jboolean json_create_1(TS_JNI_ARGS, jlong self, jlong str, jlong size, jboolean owner) {
		return toJson(self).create(toString(str), (size_t)size, (bool)owner);
	}
	static jboolean json_load(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toJson(self).load(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean json_load_1(TS_JNI_ARGS, jlong self, jlong name) {
		return toJson(self).load(toString(name));
	}
	static jboolean json_load_2(TS_JNI_ARGS, jlong self, jlong stream) {
		return toJson(self).load(toStream(stream));
	}
	static jboolean json_save(TS_JNI_ARGS, jlong self, jstring name, jboolean compact) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toJson(self).save(name_, (bool)compact);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean json_save_1(TS_JNI_ARGS, jlong self, jlong name, jboolean compact) {
		return toJson(self).save(toString(name), (bool)compact);
	}
	static jboolean json_save_2(TS_JNI_ARGS, jlong self, jlong stream, jboolean compact) {
		return toJson(self).save(toStream(stream), (bool)compact);
	}
	static jlong json_get_root(TS_JNI_ARGS, jlong self) {
		return newJson(toJson(self).getRoot());
	}
	static jlong json_get_root_1(TS_JNI_ARGS, jlong self) {
		return newJson(toJson(self).getRoot());
	}
	static jint json_set_parent(TS_JNI_ARGS, jlong self, jlong parent, jboolean check) {
		return toJson(self).setParent(toJson(parent), (bool)check);
	}
	static jlong json_get_parent(TS_JNI_ARGS, jlong self) {
		return newJson(toJson(self).getParent());
	}
	static jlong json_get_parent_1(TS_JNI_ARGS, jlong self) {
		return newJson(toJson(self).getParent());
	}
	static jlong json_add_child(TS_JNI_ARGS, jlong self, jstring name, jint type, jboolean check) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Json ret_ = toJson(self).addChild(name_, (Json::Type)type, (bool)check);
		env->ReleaseStringUTFChars(name, name_);
		return newJson(ret_);
	}
	static jint json_add_child_1(TS_JNI_ARGS, jlong self, jlong child, jboolean check) {
		return toJson(self).addChild(toJson(child), (bool)check);
	}
	static jboolean json_remove_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toJson(self).removeChild(toJson(child));
	}
	static void json_release_children(TS_JNI_ARGS, jlong self) {
		toJson(self).releaseChildren();
	}
	static jint json_find_child(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toJson(self).findChild(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean json_is_child(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toJson(self).isChild(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong json_get_child(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const Json ret_ = toJson(self).getChild(name_);
		env->ReleaseStringUTFChars(name, name_);
		return newJson(ret_);
	}
	static jlong json_get_child_1(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Json ret_ = toJson(self).getChild(name_);
		env->ReleaseStringUTFChars(name, name_);
		return newJson(ret_);
	}
	static jint json_get_num_children(TS_JNI_ARGS, jlong self) {
		return toJson(self).getNumChildren();
	}
	static jlong json_get_child_2(TS_JNI_ARGS, jlong self, jint index) {
		return newJson(toJson(self).getChild((uint32_t)index));
	}
	static jlong json_get_child_3(TS_JNI_ARGS, jlong self, jint index) {
		return newJson(toJson(self).getChild((uint32_t)index));
	}
	static jstring json_get_path_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toJson(self).getPathName().get());
	}
	static void json_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toJson(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void json_set_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toJson(self).setName(toString(name));
	}
	static jstring json_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toJson(self).getName().get());
	}
	static void json_set_type(TS_JNI_ARGS, jlong self, jint type) {
		toJson(self).setType((Json::Type)type);
	}
	static jint json_get_type(TS_JNI_ARGS, jlong self) {
		return toJson(self).getType();
	}
	static jstring json_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(Json::getTypeName((Json::Type)type));
	}
	static jstring json_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toJson(self).getTypeName());
	}
	static jboolean json_is_unknown(TS_JNI_ARGS, jlong self) {
		return toJson(self).isUnknown();
	}
	static jboolean json_is_null(TS_JNI_ARGS, jlong self) {
		return toJson(self).isNull();
	}
	static jboolean json_is_bool(TS_JNI_ARGS, jlong self) {
		return toJson(self).isBool();
	}
	static jboolean json_is_number(TS_JNI_ARGS, jlong self) {
		return toJson(self).isNumber();
	}
	static jboolean json_is_string(TS_JNI_ARGS, jlong self) {
		return toJson(self).isString();
	}
	static jboolean json_is_object(TS_JNI_ARGS, jlong self) {
		return toJson(self).isObject();
	}
	static jboolean json_is_array(TS_JNI_ARGS, jlong self) {
		return toJson(self).isArray();
	}
	static void json_set_data(TS_JNI_ARGS, jlong self, jboolean value) {
		toJson(self).setData((bool)value);
	}
	static void json_set_data_1(TS_JNI_ARGS, jlong self, jint value, jint radix) {
		toJson(self).setData(value, (uint32_t)radix);
	}
	static void json_set_data_2(TS_JNI_ARGS, jlong self, jint value, jint radix) {
		toJson(self).setData((uint32_t)value, (uint32_t)radix);
	}
	static void json_set_data_3(TS_JNI_ARGS, jlong self, jlong value, jint radix) {
		toJson(self).setData((uint64_t)value, (uint32_t)radix);
	}
	static void json_set_data_4(TS_JNI_ARGS, jlong self, jfloat value, jint digits, jboolean compact, jboolean exponent) {
		toJson(self).setData(value, (uint32_t)digits, (bool)compact, (bool)exponent);
	}
	static void json_set_data_5(TS_JNI_ARGS, jlong self, jdouble value, jint digits, jboolean compact, jboolean exponent) {
		toJson(self).setData(value, (uint32_t)digits, (bool)compact, (bool)exponent);
	}
	static void json_set_data_6(TS_JNI_ARGS, jlong self, jstring value) {
		const char *value_ = (value) ? env->GetStringUTFChars(value, nullptr) : nullptr;
		toJson(self).setData(value_);
		env->ReleaseStringUTFChars(value, value_);
	}
	static void json_set_data_7(TS_JNI_ARGS, jlong self, jlong value) {
		toJson(self).setData(toString(value));
	}
	static jstring json_get_data(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toJson(self).getData().get());
	}
	static jboolean json_get_data_bool(TS_JNI_ARGS, jlong self) {
		return toJson(self).getDataBool();
	}
	static jint json_get_datai32(TS_JNI_ARGS, jlong self, jint radix) {
		return toJson(self).getDatai32((uint32_t)radix);
	}
	static jint json_get_datau32(TS_JNI_ARGS, jlong self, jint radix) {
		return toJson(self).getDatau32((uint32_t)radix);
	}
	static jlong json_get_datau64(TS_JNI_ARGS, jlong self, jint radix) {
		return (jlong)toJson(self).getDatau64((uint32_t)radix);
	}
	static jfloat json_get_dataf32(TS_JNI_ARGS, jlong self) {
		return toJson(self).getDataf32();
	}
	static jdouble json_get_dataf64(TS_JNI_ARGS, jlong self) {
		return toJson(self).getDataf64();
	}
	static jstring json_get_number(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toJson(self).getNumber().get());
	}
	static jstring json_get_string(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toJson(self).getString().get());
	}
	static jboolean json_get_data_1(TS_JNI_ARGS, jlong self, jstring name, jboolean value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toJson(self).getData(name_, (bool)value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint json_get_data_2(TS_JNI_ARGS, jlong self, jstring name, jint value, jint radix) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		int32_t ret_ = toJson(self).getData(name_, value, (uint32_t)radix);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint json_get_data_3(TS_JNI_ARGS, jlong self, jstring name, jint value, jint radix) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toJson(self).getData(name_, (uint32_t)value, (uint32_t)radix);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong json_get_data_4(TS_JNI_ARGS, jlong self, jstring name, jlong value, jint radix) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint64_t ret_ = toJson(self).getData(name_, (uint64_t)value, (uint32_t)radix);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jfloat json_get_data_5(TS_JNI_ARGS, jlong self, jstring name, jfloat value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		float32_t ret_ = toJson(self).getData(name_, value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jdouble json_get_data_6(TS_JNI_ARGS, jlong self, jstring name, jdouble value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		float64_t ret_ = toJson(self).getData(name_, value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jstring json_get_data_7(TS_JNI_ARGS, jlong self, jstring name, jlong value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		String ret_ = toJson(self).getData(name_, toString(value));
		env->ReleaseStringUTFChars(name, name_);
		return env->NewStringUTF(ret_.get());
	}
	static void json_set_data_8(TS_JNI_ARGS, jlong self, jstringArray values, jint size) {
		Array<const char*> values_((values) ? (uint32_t)env->GetArrayLength(values) : 0);
		for(uint32_t i = 0; i < values_.size(); i++) values_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(values, i), nullptr);
		toJson(self).setData(values_.get(), (uint32_t)size);
		for(uint32_t i = 0; i < values_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(values, i), values_[i]);
	}
	static void json_set_data_9(TS_JNI_ARGS, jlong self, jlongArray values, jint size) {
		Array<String> values_((uint32_t)env->GetArrayLength(values));
		jlong *values__ = env->GetLongArrayElements(values, nullptr);
		for(uint32_t i = 0; i < values_.size(); i++) values_[i] = toString(values__[i]);
		toJson(self).setData(values_.get(), (uint32_t)size);
		if(values__) env->ReleaseLongArrayElements(values, values__, 0);
	}
	static void json_set_data_10(TS_JNI_ARGS, jlong self, jintArray values, jint size, jint radix) {
		toJson(self).setData(IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix);
	}
	static void json_set_data_11(TS_JNI_ARGS, jlong self, jintArray values, jint size, jint radix) {
		toJson(self).setData((uint32_t*)IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix);
	}
	static void json_set_data_12(TS_JNI_ARGS, jlong self, jfloatArray values, jint size, jint digits, jboolean compact, jboolean exponent) {
		toJson(self).setData(FloatArray(env, values).get(), (uint32_t)size, (uint32_t)digits, (bool)compact, (bool)exponent);
	}
	static void json_set_data_13(TS_JNI_ARGS, jlong self, jdoubleArray values, jint size, jint digits, jboolean compact, jboolean exponent) {
		toJson(self).setData(DoubleArray(env, values).get(), (uint32_t)size, (uint32_t)digits, (bool)compact, (bool)exponent);
	}
	static jint json_get_data_8(TS_JNI_ARGS, jlong self, jlongArray values, jint size) {
		Array<String> values_((uint32_t)env->GetArrayLength(values));
		jlong *values__ = env->GetLongArrayElements(values, nullptr);
		for(uint32_t i = 0; i < values_.size(); i++) values_[i] = toString(values__[i]);
		uint32_t ret_ = toJson(self).getData(values_.get(), (uint32_t)size);
		if(values__) env->ReleaseLongArrayElements(values, values__, 0);
		return ret_;
	}
	static jint json_get_data_9(TS_JNI_ARGS, jlong self, jintArray values, jint size, jint radix) {
		return toJson(self).getData(IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix);
	}
	static jint json_get_data_10(TS_JNI_ARGS, jlong self, jintArray values, jint size, jint radix) {
		return toJson(self).getData((uint32_t*)IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix);
	}
	static jint json_get_data_11(TS_JNI_ARGS, jlong self, jfloatArray values, jint size) {
		return toJson(self).getData(FloatArray(env, values).get(), (uint32_t)size);
	}
	static jint json_get_data_12(TS_JNI_ARGS, jlong self, jdoubleArray values, jint size) {
		return toJson(self).getData(DoubleArray(env, values).get(), (uint32_t)size);
	}
	static const JNINativeMethod json_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)json_new },
		{ (char*)"new_1", (char*)"(I)J", (void*)json_new_1 },
		{ (char*)"new_2", (char*)"(Ljava/lang/String;I)J", (void*)json_new_2 },
		{ (char*)"new_3", (char*)"(JI)J", (void*)json_new_3 },
		{ (char*)"new_4", (char*)"([JLjava/lang/String;I)J", (void*)json_new_4 },
		{ (char*)"new_5", (char*)"([JJI)J", (void*)json_new_5 },
		{ (char*)"delete_", (char*)"(J)V", (void*)json_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)json_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)json_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)json_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)json_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)json_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)json_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)json_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)json_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)json_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)json_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)json_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)json_clear },
		{ (char*)"create_", (char*)"(JLjava/lang/String;JZ)Z", (void*)json_create },
		{ (char*)"create_1", (char*)"(JJJZ)Z", (void*)json_create_1 },
		{ (char*)"load_", (char*)"(JLjava/lang/String;)Z", (void*)json_load },
		{ (char*)"load_1", (char*)"(JJ)Z", (void*)json_load_1 },
		{ (char*)"load_2", (char*)"(JJ)Z", (void*)json_load_2 },
		{ (char*)"save_", (char*)"(JLjava/lang/String;Z)Z", (void*)json_save },
		{ (char*)"save_1", (char*)"(JJZ)Z", (void*)json_save_1 },
		{ (char*)"save_2", (char*)"(JJZ)Z", (void*)json_save_2 },
		{ (char*)"get_root", (char*)"(J)J", (void*)json_get_root },
		{ (char*)"get_root_1", (char*)"(J)J", (void*)json_get_root_1 },
		{ (char*)"set_parent", (char*)"(JJZ)I", (void*)json_set_parent },
		{ (char*)"get_parent", (char*)"(J)J", (void*)json_get_parent },
		{ (char*)"get_parent_1", (char*)"(J)J", (void*)json_get_parent_1 },
		{ (char*)"add_child", (char*)"(JLjava/lang/String;IZ)J", (void*)json_add_child },
		{ (char*)"add_child_1", (char*)"(JJZ)I", (void*)json_add_child_1 },
		{ (char*)"remove_child", (char*)"(JJ)Z", (void*)json_remove_child },
		{ (char*)"release_children", (char*)"(J)V", (void*)json_release_children },
		{ (char*)"find_child", (char*)"(JLjava/lang/String;)I", (void*)json_find_child },
		{ (char*)"is_child", (char*)"(JLjava/lang/String;)Z", (void*)json_is_child },
		{ (char*)"get_child", (char*)"(JLjava/lang/String;)J", (void*)json_get_child },
		{ (char*)"get_child_1", (char*)"(JLjava/lang/String;)J", (void*)json_get_child_1 },
		{ (char*)"get_num_children", (char*)"(J)I", (void*)json_get_num_children },
		{ (char*)"get_child_2", (char*)"(JI)J", (void*)json_get_child_2 },
		{ (char*)"get_child_3", (char*)"(JI)J", (void*)json_get_child_3 },
		{ (char*)"get_path_name", (char*)"(J)Ljava/lang/String;", (void*)json_get_path_name },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)json_set_name },
		{ (char*)"set_name_1", (char*)"(JJ)V", (void*)json_set_name_1 },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)json_get_name },
		{ (char*)"set_type", (char*)"(JI)V", (void*)json_set_type },
		{ (char*)"get_type", (char*)"(J)I", (void*)json_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)json_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)json_get_type_name_1 },
		{ (char*)"is_unknown", (char*)"(J)Z", (void*)json_is_unknown },
		{ (char*)"is_null", (char*)"(J)Z", (void*)json_is_null },
		{ (char*)"is_bool", (char*)"(J)Z", (void*)json_is_bool },
		{ (char*)"is_number", (char*)"(J)Z", (void*)json_is_number },
		{ (char*)"is_string", (char*)"(J)Z", (void*)json_is_string },
		{ (char*)"is_object", (char*)"(J)Z", (void*)json_is_object },
		{ (char*)"is_array", (char*)"(J)Z", (void*)json_is_array },
		{ (char*)"set_data", (char*)"(JZ)V", (void*)json_set_data },
		{ (char*)"set_data_1", (char*)"(JII)V", (void*)json_set_data_1 },
		{ (char*)"set_data_2", (char*)"(JII)V", (void*)json_set_data_2 },
		{ (char*)"set_data_3", (char*)"(JJI)V", (void*)json_set_data_3 },
		{ (char*)"set_data_4", (char*)"(JFIZZ)V", (void*)json_set_data_4 },
		{ (char*)"set_data_5", (char*)"(JDIZZ)V", (void*)json_set_data_5 },
		{ (char*)"set_data_6", (char*)"(JLjava/lang/String;)V", (void*)json_set_data_6 },
		{ (char*)"set_data_7", (char*)"(JJ)V", (void*)json_set_data_7 },
		{ (char*)"get_data", (char*)"(J)Ljava/lang/String;", (void*)json_get_data },
		{ (char*)"get_data_bool", (char*)"(J)Z", (void*)json_get_data_bool },
		{ (char*)"get_datai32", (char*)"(JI)I", (void*)json_get_datai32 },
		{ (char*)"get_datau32", (char*)"(JI)I", (void*)json_get_datau32 },
		{ (char*)"get_datau64", (char*)"(JI)J", (void*)json_get_datau64 },
		{ (char*)"get_dataf32", (char*)"(J)F", (void*)json_get_dataf32 },
		{ (char*)"get_dataf64", (char*)"(J)D", (void*)json_get_dataf64 },
		{ (char*)"get_number", (char*)"(J)Ljava/lang/String;", (void*)json_get_number },
		{ (char*)"get_string", (char*)"(J)Ljava/lang/String;", (void*)json_get_string },
		{ (char*)"get_data_1", (char*)"(JLjava/lang/String;Z)Z", (void*)json_get_data_1 },
		{ (char*)"get_data_2", (char*)"(JLjava/lang/String;II)I", (void*)json_get_data_2 },
		{ (char*)"get_data_3", (char*)"(JLjava/lang/String;II)I", (void*)json_get_data_3 },
		{ (char*)"get_data_4", (char*)"(JLjava/lang/String;JI)J", (void*)json_get_data_4 },
		{ (char*)"get_data_5", (char*)"(JLjava/lang/String;F)F", (void*)json_get_data_5 },
		{ (char*)"get_data_6", (char*)"(JLjava/lang/String;D)D", (void*)json_get_data_6 },
		{ (char*)"get_data_7", (char*)"(JLjava/lang/String;J)Ljava/lang/String;", (void*)json_get_data_7 },
		{ (char*)"set_data_8", (char*)"(J[Ljava/lang/String;I)V", (void*)json_set_data_8 },
		{ (char*)"set_data_9", (char*)"(J[JI)V", (void*)json_set_data_9 },
		{ (char*)"set_data_10", (char*)"(J[III)V", (void*)json_set_data_10 },
		{ (char*)"set_data_11", (char*)"(J[III)V", (void*)json_set_data_11 },
		{ (char*)"set_data_12", (char*)"(J[FIIZZ)V", (void*)json_set_data_12 },
		{ (char*)"set_data_13", (char*)"(J[DIIZZ)V", (void*)json_set_data_13 },
		{ (char*)"get_data_8", (char*)"(J[JI)I", (void*)json_get_data_8 },
		{ (char*)"get_data_9", (char*)"(J[III)I", (void*)json_get_data_9 },
		{ (char*)"get_data_10", (char*)"(J[III)I", (void*)json_get_data_10 },
		{ (char*)"get_data_11", (char*)"(J[FI)I", (void*)json_get_data_11 },
		{ (char*)"get_data_12", (char*)"(J[DI)I", (void*)json_get_data_12 },
	};
	
	// Tellusim::Xml
	static jlong xml_new(TS_JNI_ARGS) {
		return newXml();
	}
	static jlong xml_new_1(TS_JNI_ARGS, jstring name, jstring attributes) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *attributes_ = (attributes) ? env->GetStringUTFChars(attributes, nullptr) : nullptr;
		jlong ret_ = newXml(name_, attributes_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(attributes, attributes_);
		return ret_;
	}
	static jlong xml_new_2(TS_JNI_ARGS, jlong name, jstring attributes) {
		const char *attributes_ = (attributes) ? env->GetStringUTFChars(attributes, nullptr) : nullptr;
		jlong ret_ = newXml(toString(name), attributes_);
		env->ReleaseStringUTFChars(attributes, attributes_);
		return ret_;
	}
	static jlong xml_new_3(TS_JNI_ARGS, jlongArray parent, jstring name, jstring attributes) {
		Array<Xml> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toXml(parent__[i]);
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *attributes_ = (attributes) ? env->GetStringUTFChars(attributes, nullptr) : nullptr;
		jlong ret_ = newXml(parent_.get(), name_, attributes_);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(attributes, attributes_);
		return ret_;
	}
	static jlong xml_new_4(TS_JNI_ARGS, jlongArray parent, jlong name, jstring attributes) {
		Array<Xml> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toXml(parent__[i]);
		const char *attributes_ = (attributes) ? env->GetStringUTFChars(attributes, nullptr) : nullptr;
		jlong ret_ = newXml(parent_.get(), toString(name), attributes_);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(attributes, attributes_);
		return ret_;
	}
	static void xml_delete(TS_JNI_ARGS, jlong self) {
		delete (Xml*)self;
	}
	static jboolean xml_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toXml(self) == toXml(ptr));
	}
	static jlong xml_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newXml(toXml(self).clonePtr());
	}
	static void xml_clear_ptr(TS_JNI_ARGS, jlong self) {
		toXml(self).clearPtr();
	}
	static void xml_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toXml(self).destroyPtr();
	}
	static void xml_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toXml(self).acquirePtr();
	}
	static void xml_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toXml(self).unacquirePtr();
	}
	static jboolean xml_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toXml(self).isValidPtr();
	}
	static jboolean xml_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toXml(self).isOwnerPtr();
	}
	static jboolean xml_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toXml(self).isConstPtr();
	}
	static jint xml_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toXml(self).getCountPtr();
	}
	static jlong xml_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toXml(self).getInternalPtr();
	}
	static void xml_clear(TS_JNI_ARGS, jlong self) {
		toXml(self).clear();
	}
	static jboolean xml_create(TS_JNI_ARGS, jlong self, jstring str, jlong size, jboolean owner) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		bool ret_ = toXml(self).create(str_, (size_t)size, (bool)owner);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static jboolean xml_create_1(TS_JNI_ARGS, jlong self, jlong str, jlong size, jboolean owner) {
		return toXml(self).create(toString(str), (size_t)size, (bool)owner);
	}
	static jboolean xml_load(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toXml(self).load(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean xml_load_1(TS_JNI_ARGS, jlong self, jlong name) {
		return toXml(self).load(toString(name));
	}
	static jboolean xml_load_2(TS_JNI_ARGS, jlong self, jlong stream) {
		return toXml(self).load(toStream(stream));
	}
	static jboolean xml_save(TS_JNI_ARGS, jlong self, jstring name, jboolean compact) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toXml(self).save(name_, (bool)compact);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean xml_save_1(TS_JNI_ARGS, jlong self, jlong name, jboolean compact) {
		return toXml(self).save(toString(name), (bool)compact);
	}
	static jboolean xml_save_2(TS_JNI_ARGS, jlong self, jlong stream, jboolean compact) {
		return toXml(self).save(toStream(stream), (bool)compact);
	}
	static jlong xml_get_root(TS_JNI_ARGS, jlong self) {
		return newXml(toXml(self).getRoot());
	}
	static jlong xml_get_root_1(TS_JNI_ARGS, jlong self) {
		return newXml(toXml(self).getRoot());
	}
	static jint xml_set_parent(TS_JNI_ARGS, jlong self, jlong parent, jboolean check) {
		return toXml(self).setParent(toXml(parent), (bool)check);
	}
	static jlong xml_get_parent(TS_JNI_ARGS, jlong self) {
		return newXml(toXml(self).getParent());
	}
	static jlong xml_get_parent_1(TS_JNI_ARGS, jlong self) {
		return newXml(toXml(self).getParent());
	}
	static jlong xml_add_child(TS_JNI_ARGS, jlong self, jstring name, jboolean check) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Xml ret_ = toXml(self).addChild(name_, (bool)check);
		env->ReleaseStringUTFChars(name, name_);
		return newXml(ret_);
	}
	static jint xml_add_child_1(TS_JNI_ARGS, jlong self, jlong child, jboolean check) {
		return toXml(self).addChild(toXml(child), (bool)check);
	}
	static jboolean xml_remove_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toXml(self).removeChild(toXml(child));
	}
	static void xml_release_children(TS_JNI_ARGS, jlong self) {
		toXml(self).releaseChildren();
	}
	static jint xml_find_child(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toXml(self).findChild(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean xml_is_child(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toXml(self).isChild(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong xml_get_child(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const Xml ret_ = toXml(self).getChild(name_);
		env->ReleaseStringUTFChars(name, name_);
		return newXml(ret_);
	}
	static jlong xml_get_child_1(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Xml ret_ = toXml(self).getChild(name_);
		env->ReleaseStringUTFChars(name, name_);
		return newXml(ret_);
	}
	static jint xml_get_num_children(TS_JNI_ARGS, jlong self) {
		return toXml(self).getNumChildren();
	}
	static jlong xml_get_child_2(TS_JNI_ARGS, jlong self, jint index) {
		return newXml(toXml(self).getChild((uint32_t)index));
	}
	static jlong xml_get_child_3(TS_JNI_ARGS, jlong self, jint index) {
		return newXml(toXml(self).getChild((uint32_t)index));
	}
	static jstring xml_get_path_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toXml(self).getPathName().get());
	}
	static void xml_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toXml(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void xml_set_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toXml(self).setName(toString(name));
	}
	static jstring xml_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toXml(self).getName().get());
	}
	static void xml_set_data(TS_JNI_ARGS, jlong self, jboolean value) {
		toXml(self).setData((bool)value);
	}
	static void xml_set_data_1(TS_JNI_ARGS, jlong self, jstring value) {
		const char *value_ = (value) ? env->GetStringUTFChars(value, nullptr) : nullptr;
		toXml(self).setData(value_);
		env->ReleaseStringUTFChars(value, value_);
	}
	static void xml_set_data_2(TS_JNI_ARGS, jlong self, jlong value) {
		toXml(self).setData(toString(value));
	}
	static void xml_set_data_3(TS_JNI_ARGS, jlong self, jint value, jint radix) {
		toXml(self).setData(value, (uint32_t)radix);
	}
	static void xml_set_data_4(TS_JNI_ARGS, jlong self, jint value, jint radix) {
		toXml(self).setData((uint32_t)value, (uint32_t)radix);
	}
	static void xml_set_data_5(TS_JNI_ARGS, jlong self, jlong value, jint radix) {
		toXml(self).setData((uint64_t)value, (uint32_t)radix);
	}
	static void xml_set_data_6(TS_JNI_ARGS, jlong self, jfloat value, jint digits, jboolean compact, jboolean exponent) {
		toXml(self).setData(value, (uint32_t)digits, (bool)compact, (bool)exponent);
	}
	static void xml_set_data_7(TS_JNI_ARGS, jlong self, jdouble value, jint digits, jboolean compact, jboolean exponent) {
		toXml(self).setData(value, (uint32_t)digits, (bool)compact, (bool)exponent);
	}
	static jstring xml_get_data(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toXml(self).getData().get());
	}
	static jboolean xml_get_data_bool(TS_JNI_ARGS, jlong self) {
		return toXml(self).getDataBool();
	}
	static jint xml_get_datai32(TS_JNI_ARGS, jlong self, jint radix) {
		return toXml(self).getDatai32((uint32_t)radix);
	}
	static jint xml_get_datau32(TS_JNI_ARGS, jlong self, jint radix) {
		return toXml(self).getDatau32((uint32_t)radix);
	}
	static jlong xml_get_datau64(TS_JNI_ARGS, jlong self, jint radix) {
		return (jlong)toXml(self).getDatau64((uint32_t)radix);
	}
	static jfloat xml_get_dataf32(TS_JNI_ARGS, jlong self) {
		return toXml(self).getDataf32();
	}
	static jdouble xml_get_dataf64(TS_JNI_ARGS, jlong self) {
		return toXml(self).getDataf64();
	}
	static jstring xml_get_data_1(TS_JNI_ARGS, jlong self, jstring name, jlong value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		String ret_ = toXml(self).getData(name_, toString(value));
		env->ReleaseStringUTFChars(name, name_);
		return env->NewStringUTF(ret_.get());
	}
	static jboolean xml_get_data_2(TS_JNI_ARGS, jlong self, jstring name, jboolean value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toXml(self).getData(name_, (bool)value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint xml_get_data_3(TS_JNI_ARGS, jlong self, jstring name, jint value, jint radix) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		int32_t ret_ = toXml(self).getData(name_, value, (uint32_t)radix);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint xml_get_data_4(TS_JNI_ARGS, jlong self, jstring name, jint value, jint radix) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toXml(self).getData(name_, (uint32_t)value, (uint32_t)radix);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong xml_get_data_5(TS_JNI_ARGS, jlong self, jstring name, jlong value, jint radix) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint64_t ret_ = toXml(self).getData(name_, (uint64_t)value, (uint32_t)radix);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jfloat xml_get_data_6(TS_JNI_ARGS, jlong self, jstring name, jfloat value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		float32_t ret_ = toXml(self).getData(name_, value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jdouble xml_get_data_7(TS_JNI_ARGS, jlong self, jstring name, jdouble value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		float64_t ret_ = toXml(self).getData(name_, value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void xml_set_data_8(TS_JNI_ARGS, jlong self, jstringArray values, jint size, jint wrap) {
		Array<const char*> values_((values) ? (uint32_t)env->GetArrayLength(values) : 0);
		for(uint32_t i = 0; i < values_.size(); i++) values_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(values, i), nullptr);
		toXml(self).setData(values_.get(), (uint32_t)size, (uint32_t)wrap);
		for(uint32_t i = 0; i < values_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(values, i), values_[i]);
	}
	static void xml_set_data_9(TS_JNI_ARGS, jlong self, jlongArray values, jint size, jint wrap) {
		Array<String> values_((uint32_t)env->GetArrayLength(values));
		jlong *values__ = env->GetLongArrayElements(values, nullptr);
		for(uint32_t i = 0; i < values_.size(); i++) values_[i] = toString(values__[i]);
		toXml(self).setData(values_.get(), (uint32_t)size, (uint32_t)wrap);
		if(values__) env->ReleaseLongArrayElements(values, values__, 0);
	}
	static void xml_set_data_10(TS_JNI_ARGS, jlong self, jintArray values, jint size, jint radix, jint wrap) {
		toXml(self).setData(IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix, (uint32_t)wrap);
	}
	static void xml_set_data_11(TS_JNI_ARGS, jlong self, jintArray values, jint size, jint radix, jint wrap) {
		toXml(self).setData((uint32_t*)IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix, (uint32_t)wrap);
	}
	static void xml_set_data_12(TS_JNI_ARGS, jlong self, jfloatArray values, jint size, jint digits, jboolean compact, jboolean exponent, jint wrap) {
		toXml(self).setData(FloatArray(env, values).get(), (uint32_t)size, (uint32_t)digits, (bool)compact, (bool)exponent, (uint32_t)wrap);
	}
	static void xml_set_data_13(TS_JNI_ARGS, jlong self, jdoubleArray values, jint size, jint digits, jboolean compact, jboolean exponent, jint wrap) {
		toXml(self).setData(DoubleArray(env, values).get(), (uint32_t)size, (uint32_t)digits, (bool)compact, (bool)exponent, (uint32_t)wrap);
	}
	static jint xml_get_data_8(TS_JNI_ARGS, jlong self, jlongArray values, jint size) {
		Array<String> values_((uint32_t)env->GetArrayLength(values));
		jlong *values__ = env->GetLongArrayElements(values, nullptr);
		for(uint32_t i = 0; i < values_.size(); i++) values_[i] = toString(values__[i]);
		uint32_t ret_ = toXml(self).getData(values_.get(), (uint32_t)size);
		if(values__) env->ReleaseLongArrayElements(values, values__, 0);
		return ret_;
	}
	static jint xml_get_data_9(TS_JNI_ARGS, jlong self, jintArray values, jint size, jint radix) {
		return toXml(self).getData(IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix);
	}
	static jint xml_get_data_10(TS_JNI_ARGS, jlong self, jintArray values, jint size, jint radix) {
		return toXml(self).getData((uint32_t*)IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix);
	}
	static jint xml_get_data_11(TS_JNI_ARGS, jlong self, jfloatArray values, jint size) {
		return toXml(self).getData(FloatArray(env, values).get(), (uint32_t)size);
	}
	static jint xml_get_data_12(TS_JNI_ARGS, jlong self, jdoubleArray values, jint size) {
		return toXml(self).getData(DoubleArray(env, values).get(), (uint32_t)size);
	}
	static jint xml_add_attribute(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toXml(self).addAttribute(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean xml_remove_attribute(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toXml(self).removeAttribute(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint xml_find_attribute(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toXml(self).findAttribute(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean xml_is_attribute(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toXml(self).isAttribute(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void xml_remove_attributes(TS_JNI_ARGS, jlong self) {
		toXml(self).removeAttributes();
	}
	static jint xml_get_num_attributes(TS_JNI_ARGS, jlong self) {
		return toXml(self).getNumAttributes();
	}
	static jstring xml_get_attribute_name(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toXml(self).getAttributeName((uint32_t)index).get());
	}
	static jboolean xml_set_attributes(TS_JNI_ARGS, jlong self, jstring str) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		bool ret_ = toXml(self).setAttributes(str_);
		env->ReleaseStringUTFChars(str, str_);
		return ret_;
	}
	static void xml_set_attribute(TS_JNI_ARGS, jlong self, jint index, jboolean value) {
		toXml(self).setAttribute((uint32_t)index, (bool)value);
	}
	static void xml_set_attribute_1(TS_JNI_ARGS, jlong self, jint index, jstring value) {
		const char *value_ = (value) ? env->GetStringUTFChars(value, nullptr) : nullptr;
		toXml(self).setAttribute((uint32_t)index, value_);
		env->ReleaseStringUTFChars(value, value_);
	}
	static void xml_set_attribute_2(TS_JNI_ARGS, jlong self, jint index, jlong value) {
		toXml(self).setAttribute((uint32_t)index, toString(value));
	}
	static void xml_set_attribute_3(TS_JNI_ARGS, jlong self, jint index, jint value, jint radix) {
		toXml(self).setAttribute((uint32_t)index, value, (uint32_t)radix);
	}
	static void xml_set_attribute_4(TS_JNI_ARGS, jlong self, jint index, jint value, jint radix) {
		toXml(self).setAttribute((uint32_t)index, (uint32_t)value, (uint32_t)radix);
	}
	static void xml_set_attribute_5(TS_JNI_ARGS, jlong self, jint index, jlong value, jint radix) {
		toXml(self).setAttribute((uint32_t)index, (uint64_t)value, (uint32_t)radix);
	}
	static void xml_set_attribute_6(TS_JNI_ARGS, jlong self, jint index, jfloat value, jint digits, jboolean compact, jboolean exponent) {
		toXml(self).setAttribute((uint32_t)index, value, (uint32_t)digits, (bool)compact, (bool)exponent);
	}
	static void xml_set_attribute_7(TS_JNI_ARGS, jlong self, jint index, jdouble value, jint digits, jboolean compact, jboolean exponent) {
		toXml(self).setAttribute((uint32_t)index, value, (uint32_t)digits, (bool)compact, (bool)exponent);
	}
	static jstring xml_get_attribute(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toXml(self).getAttribute((uint32_t)index).get());
	}
	static jint xml_get_attributei32(TS_JNI_ARGS, jlong self, jint index, jint radix) {
		return toXml(self).getAttributei32((uint32_t)index, (uint32_t)radix);
	}
	static jint xml_get_attributeu32(TS_JNI_ARGS, jlong self, jint index, jint radix) {
		return toXml(self).getAttributeu32((uint32_t)index, (uint32_t)radix);
	}
	static jlong xml_get_attributeu64(TS_JNI_ARGS, jlong self, jint index, jint radix) {
		return (jlong)toXml(self).getAttributeu64((uint32_t)index, (uint32_t)radix);
	}
	static jfloat xml_get_attributef32(TS_JNI_ARGS, jlong self, jint index) {
		return toXml(self).getAttributef32((uint32_t)index);
	}
	static jdouble xml_get_attributef64(TS_JNI_ARGS, jlong self, jint index) {
		return toXml(self).getAttributef64((uint32_t)index);
	}
	static jstring xml_get_attribute_1(TS_JNI_ARGS, jlong self, jstring name, jlong value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		String ret_ = toXml(self).getAttribute(name_, toString(value));
		env->ReleaseStringUTFChars(name, name_);
		return env->NewStringUTF(ret_.get());
	}
	static jboolean xml_get_attribute_2(TS_JNI_ARGS, jlong self, jstring name, jboolean value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toXml(self).getAttribute(name_, (bool)value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint xml_get_attribute_3(TS_JNI_ARGS, jlong self, jstring name, jint value, jint radix) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		int32_t ret_ = toXml(self).getAttribute(name_, value, (uint32_t)radix);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jint xml_get_attribute_4(TS_JNI_ARGS, jlong self, jstring name, jint value, jint radix) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint32_t ret_ = toXml(self).getAttribute(name_, (uint32_t)value, (uint32_t)radix);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong xml_get_attribute_5(TS_JNI_ARGS, jlong self, jstring name, jlong value, jint radix) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		uint64_t ret_ = toXml(self).getAttribute(name_, (uint64_t)value, (uint32_t)radix);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jfloat xml_get_attribute_6(TS_JNI_ARGS, jlong self, jstring name, jfloat value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		float32_t ret_ = toXml(self).getAttribute(name_, value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jdouble xml_get_attribute_7(TS_JNI_ARGS, jlong self, jstring name, jdouble value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		float64_t ret_ = toXml(self).getAttribute(name_, value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void xml_set_attribute_8(TS_JNI_ARGS, jlong self, jint index, jstringArray values, jint size, jstring delimiter) {
		Array<const char*> values_((values) ? (uint32_t)env->GetArrayLength(values) : 0);
		for(uint32_t i = 0; i < values_.size(); i++) values_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(values, i), nullptr);
		const char *delimiter_ = (delimiter) ? env->GetStringUTFChars(delimiter, nullptr) : nullptr;
		toXml(self).setAttribute((uint32_t)index, values_.get(), (uint32_t)size, delimiter_);
		for(uint32_t i = 0; i < values_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(values, i), values_[i]);
		env->ReleaseStringUTFChars(delimiter, delimiter_);
	}
	static void xml_set_attribute_9(TS_JNI_ARGS, jlong self, jint index, jlongArray values, jint size, jstring delimiter) {
		Array<String> values_((uint32_t)env->GetArrayLength(values));
		jlong *values__ = env->GetLongArrayElements(values, nullptr);
		for(uint32_t i = 0; i < values_.size(); i++) values_[i] = toString(values__[i]);
		const char *delimiter_ = (delimiter) ? env->GetStringUTFChars(delimiter, nullptr) : nullptr;
		toXml(self).setAttribute((uint32_t)index, values_.get(), (uint32_t)size, delimiter_);
		if(values__) env->ReleaseLongArrayElements(values, values__, 0);
		env->ReleaseStringUTFChars(delimiter, delimiter_);
	}
	static void xml_set_attribute_10(TS_JNI_ARGS, jlong self, jint index, jintArray values, jint size, jint radix) {
		toXml(self).setAttribute((uint32_t)index, IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix);
	}
	static void xml_set_attribute_11(TS_JNI_ARGS, jlong self, jint index, jintArray values, jint size, jint radix) {
		toXml(self).setAttribute((uint32_t)index, (uint32_t*)IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix);
	}
	static void xml_set_attribute_12(TS_JNI_ARGS, jlong self, jint index, jfloatArray values, jint size, jint digits, jboolean compact, jboolean exponent) {
		toXml(self).setAttribute((uint32_t)index, FloatArray(env, values).get(), (uint32_t)size, (uint32_t)digits, (bool)compact, (bool)exponent);
	}
	static void xml_set_attribute_13(TS_JNI_ARGS, jlong self, jint index, jdoubleArray values, jint size, jint digits, jboolean compact, jboolean exponent) {
		toXml(self).setAttribute((uint32_t)index, DoubleArray(env, values).get(), (uint32_t)size, (uint32_t)digits, (bool)compact, (bool)exponent);
	}
	static jint xml_get_attribute_8(TS_JNI_ARGS, jlong self, jint index, jlongArray values, jint size, jstring delimiter) {
		Array<String> values_((uint32_t)env->GetArrayLength(values));
		jlong *values__ = env->GetLongArrayElements(values, nullptr);
		for(uint32_t i = 0; i < values_.size(); i++) values_[i] = toString(values__[i]);
		const char *delimiter_ = (delimiter) ? env->GetStringUTFChars(delimiter, nullptr) : nullptr;
		uint32_t ret_ = toXml(self).getAttribute((uint32_t)index, values_.get(), (uint32_t)size, delimiter_);
		if(values__) env->ReleaseLongArrayElements(values, values__, 0);
		env->ReleaseStringUTFChars(delimiter, delimiter_);
		return ret_;
	}
	static jint xml_get_attribute_9(TS_JNI_ARGS, jlong self, jint index, jintArray values, jint size, jint radix) {
		return toXml(self).getAttribute((uint32_t)index, IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix);
	}
	static jint xml_get_attribute_10(TS_JNI_ARGS, jlong self, jint index, jintArray values, jint size, jint radix) {
		return toXml(self).getAttribute((uint32_t)index, (uint32_t*)IntArray(env, values).get(), (uint32_t)size, (uint32_t)radix);
	}
	static jint xml_get_attribute_11(TS_JNI_ARGS, jlong self, jint index, jfloatArray values, jint size) {
		return toXml(self).getAttribute((uint32_t)index, FloatArray(env, values).get(), (uint32_t)size);
	}
	static jint xml_get_attribute_12(TS_JNI_ARGS, jlong self, jint index, jdoubleArray values, jint size) {
		return toXml(self).getAttribute((uint32_t)index, DoubleArray(env, values).get(), (uint32_t)size);
	}
	static const JNINativeMethod xml_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)xml_new },
		{ (char*)"new_1", (char*)"(Ljava/lang/String;Ljava/lang/String;)J", (void*)xml_new_1 },
		{ (char*)"new_2", (char*)"(JLjava/lang/String;)J", (void*)xml_new_2 },
		{ (char*)"new_3", (char*)"([JLjava/lang/String;Ljava/lang/String;)J", (void*)xml_new_3 },
		{ (char*)"new_4", (char*)"([JJLjava/lang/String;)J", (void*)xml_new_4 },
		{ (char*)"delete_", (char*)"(J)V", (void*)xml_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)xml_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)xml_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)xml_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)xml_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)xml_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)xml_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)xml_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)xml_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)xml_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)xml_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)xml_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)xml_clear },
		{ (char*)"create_", (char*)"(JLjava/lang/String;JZ)Z", (void*)xml_create },
		{ (char*)"create_1", (char*)"(JJJZ)Z", (void*)xml_create_1 },
		{ (char*)"load_", (char*)"(JLjava/lang/String;)Z", (void*)xml_load },
		{ (char*)"load_1", (char*)"(JJ)Z", (void*)xml_load_1 },
		{ (char*)"load_2", (char*)"(JJ)Z", (void*)xml_load_2 },
		{ (char*)"save_", (char*)"(JLjava/lang/String;Z)Z", (void*)xml_save },
		{ (char*)"save_1", (char*)"(JJZ)Z", (void*)xml_save_1 },
		{ (char*)"save_2", (char*)"(JJZ)Z", (void*)xml_save_2 },
		{ (char*)"get_root", (char*)"(J)J", (void*)xml_get_root },
		{ (char*)"get_root_1", (char*)"(J)J", (void*)xml_get_root_1 },
		{ (char*)"set_parent", (char*)"(JJZ)I", (void*)xml_set_parent },
		{ (char*)"get_parent", (char*)"(J)J", (void*)xml_get_parent },
		{ (char*)"get_parent_1", (char*)"(J)J", (void*)xml_get_parent_1 },
		{ (char*)"add_child", (char*)"(JLjava/lang/String;Z)J", (void*)xml_add_child },
		{ (char*)"add_child_1", (char*)"(JJZ)I", (void*)xml_add_child_1 },
		{ (char*)"remove_child", (char*)"(JJ)Z", (void*)xml_remove_child },
		{ (char*)"release_children", (char*)"(J)V", (void*)xml_release_children },
		{ (char*)"find_child", (char*)"(JLjava/lang/String;)I", (void*)xml_find_child },
		{ (char*)"is_child", (char*)"(JLjava/lang/String;)Z", (void*)xml_is_child },
		{ (char*)"get_child", (char*)"(JLjava/lang/String;)J", (void*)xml_get_child },
		{ (char*)"get_child_1", (char*)"(JLjava/lang/String;)J", (void*)xml_get_child_1 },
		{ (char*)"get_num_children", (char*)"(J)I", (void*)xml_get_num_children },
		{ (char*)"get_child_2", (char*)"(JI)J", (void*)xml_get_child_2 },
		{ (char*)"get_child_3", (char*)"(JI)J", (void*)xml_get_child_3 },
		{ (char*)"get_path_name", (char*)"(J)Ljava/lang/String;", (void*)xml_get_path_name },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)xml_set_name },
		{ (char*)"set_name_1", (char*)"(JJ)V", (void*)xml_set_name_1 },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)xml_get_name },
		{ (char*)"set_data", (char*)"(JZ)V", (void*)xml_set_data },
		{ (char*)"set_data_1", (char*)"(JLjava/lang/String;)V", (void*)xml_set_data_1 },
		{ (char*)"set_data_2", (char*)"(JJ)V", (void*)xml_set_data_2 },
		{ (char*)"set_data_3", (char*)"(JII)V", (void*)xml_set_data_3 },
		{ (char*)"set_data_4", (char*)"(JII)V", (void*)xml_set_data_4 },
		{ (char*)"set_data_5", (char*)"(JJI)V", (void*)xml_set_data_5 },
		{ (char*)"set_data_6", (char*)"(JFIZZ)V", (void*)xml_set_data_6 },
		{ (char*)"set_data_7", (char*)"(JDIZZ)V", (void*)xml_set_data_7 },
		{ (char*)"get_data", (char*)"(J)Ljava/lang/String;", (void*)xml_get_data },
		{ (char*)"get_data_bool", (char*)"(J)Z", (void*)xml_get_data_bool },
		{ (char*)"get_datai32", (char*)"(JI)I", (void*)xml_get_datai32 },
		{ (char*)"get_datau32", (char*)"(JI)I", (void*)xml_get_datau32 },
		{ (char*)"get_datau64", (char*)"(JI)J", (void*)xml_get_datau64 },
		{ (char*)"get_dataf32", (char*)"(J)F", (void*)xml_get_dataf32 },
		{ (char*)"get_dataf64", (char*)"(J)D", (void*)xml_get_dataf64 },
		{ (char*)"get_data_1", (char*)"(JLjava/lang/String;J)Ljava/lang/String;", (void*)xml_get_data_1 },
		{ (char*)"get_data_2", (char*)"(JLjava/lang/String;Z)Z", (void*)xml_get_data_2 },
		{ (char*)"get_data_3", (char*)"(JLjava/lang/String;II)I", (void*)xml_get_data_3 },
		{ (char*)"get_data_4", (char*)"(JLjava/lang/String;II)I", (void*)xml_get_data_4 },
		{ (char*)"get_data_5", (char*)"(JLjava/lang/String;JI)J", (void*)xml_get_data_5 },
		{ (char*)"get_data_6", (char*)"(JLjava/lang/String;F)F", (void*)xml_get_data_6 },
		{ (char*)"get_data_7", (char*)"(JLjava/lang/String;D)D", (void*)xml_get_data_7 },
		{ (char*)"set_data_8", (char*)"(J[Ljava/lang/String;II)V", (void*)xml_set_data_8 },
		{ (char*)"set_data_9", (char*)"(J[JII)V", (void*)xml_set_data_9 },
		{ (char*)"set_data_10", (char*)"(J[IIII)V", (void*)xml_set_data_10 },
		{ (char*)"set_data_11", (char*)"(J[IIII)V", (void*)xml_set_data_11 },
		{ (char*)"set_data_12", (char*)"(J[FIIZZI)V", (void*)xml_set_data_12 },
		{ (char*)"set_data_13", (char*)"(J[DIIZZI)V", (void*)xml_set_data_13 },
		{ (char*)"get_data_8", (char*)"(J[JI)I", (void*)xml_get_data_8 },
		{ (char*)"get_data_9", (char*)"(J[III)I", (void*)xml_get_data_9 },
		{ (char*)"get_data_10", (char*)"(J[III)I", (void*)xml_get_data_10 },
		{ (char*)"get_data_11", (char*)"(J[FI)I", (void*)xml_get_data_11 },
		{ (char*)"get_data_12", (char*)"(J[DI)I", (void*)xml_get_data_12 },
		{ (char*)"add_attribute", (char*)"(JLjava/lang/String;)I", (void*)xml_add_attribute },
		{ (char*)"remove_attribute", (char*)"(JLjava/lang/String;)Z", (void*)xml_remove_attribute },
		{ (char*)"find_attribute", (char*)"(JLjava/lang/String;)I", (void*)xml_find_attribute },
		{ (char*)"is_attribute", (char*)"(JLjava/lang/String;)Z", (void*)xml_is_attribute },
		{ (char*)"remove_attributes", (char*)"(J)V", (void*)xml_remove_attributes },
		{ (char*)"get_num_attributes", (char*)"(J)I", (void*)xml_get_num_attributes },
		{ (char*)"get_attribute_name", (char*)"(JI)Ljava/lang/String;", (void*)xml_get_attribute_name },
		{ (char*)"set_attributes", (char*)"(JLjava/lang/String;)Z", (void*)xml_set_attributes },
		{ (char*)"set_attribute", (char*)"(JIZ)V", (void*)xml_set_attribute },
		{ (char*)"set_attribute_1", (char*)"(JILjava/lang/String;)V", (void*)xml_set_attribute_1 },
		{ (char*)"set_attribute_2", (char*)"(JIJ)V", (void*)xml_set_attribute_2 },
		{ (char*)"set_attribute_3", (char*)"(JIII)V", (void*)xml_set_attribute_3 },
		{ (char*)"set_attribute_4", (char*)"(JIII)V", (void*)xml_set_attribute_4 },
		{ (char*)"set_attribute_5", (char*)"(JIJI)V", (void*)xml_set_attribute_5 },
		{ (char*)"set_attribute_6", (char*)"(JIFIZZ)V", (void*)xml_set_attribute_6 },
		{ (char*)"set_attribute_7", (char*)"(JIDIZZ)V", (void*)xml_set_attribute_7 },
		{ (char*)"get_attribute", (char*)"(JI)Ljava/lang/String;", (void*)xml_get_attribute },
		{ (char*)"get_attributei32", (char*)"(JII)I", (void*)xml_get_attributei32 },
		{ (char*)"get_attributeu32", (char*)"(JII)I", (void*)xml_get_attributeu32 },
		{ (char*)"get_attributeu64", (char*)"(JII)J", (void*)xml_get_attributeu64 },
		{ (char*)"get_attributef32", (char*)"(JI)F", (void*)xml_get_attributef32 },
		{ (char*)"get_attributef64", (char*)"(JI)D", (void*)xml_get_attributef64 },
		{ (char*)"get_attribute_1", (char*)"(JLjava/lang/String;J)Ljava/lang/String;", (void*)xml_get_attribute_1 },
		{ (char*)"get_attribute_2", (char*)"(JLjava/lang/String;Z)Z", (void*)xml_get_attribute_2 },
		{ (char*)"get_attribute_3", (char*)"(JLjava/lang/String;II)I", (void*)xml_get_attribute_3 },
		{ (char*)"get_attribute_4", (char*)"(JLjava/lang/String;II)I", (void*)xml_get_attribute_4 },
		{ (char*)"get_attribute_5", (char*)"(JLjava/lang/String;JI)J", (void*)xml_get_attribute_5 },
		{ (char*)"get_attribute_6", (char*)"(JLjava/lang/String;F)F", (void*)xml_get_attribute_6 },
		{ (char*)"get_attribute_7", (char*)"(JLjava/lang/String;D)D", (void*)xml_get_attribute_7 },
		{ (char*)"set_attribute_8", (char*)"(JI[Ljava/lang/String;ILjava/lang/String;)V", (void*)xml_set_attribute_8 },
		{ (char*)"set_attribute_9", (char*)"(JI[JILjava/lang/String;)V", (void*)xml_set_attribute_9 },
		{ (char*)"set_attribute_10", (char*)"(JI[III)V", (void*)xml_set_attribute_10 },
		{ (char*)"set_attribute_11", (char*)"(JI[III)V", (void*)xml_set_attribute_11 },
		{ (char*)"set_attribute_12", (char*)"(JI[FIIZZ)V", (void*)xml_set_attribute_12 },
		{ (char*)"set_attribute_13", (char*)"(JI[DIIZZ)V", (void*)xml_set_attribute_13 },
		{ (char*)"get_attribute_8", (char*)"(JI[JILjava/lang/String;)I", (void*)xml_get_attribute_8 },
		{ (char*)"get_attribute_9", (char*)"(JI[III)I", (void*)xml_get_attribute_9 },
		{ (char*)"get_attribute_10", (char*)"(JI[III)I", (void*)xml_get_attribute_10 },
		{ (char*)"get_attribute_11", (char*)"(JI[FI)I", (void*)xml_get_attribute_11 },
		{ (char*)"get_attribute_12", (char*)"(JI[DI)I", (void*)xml_get_attribute_12 },
	};
	
	// Tellusim::Buffer
	static jlong buffer_new(TS_JNI_ARGS) {
		return newBuffer();
	}
	static void buffer_delete(TS_JNI_ARGS, jlong self) {
		delete (Buffer*)self;
	}
	static jboolean buffer_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toBuffer(self) == toBuffer(ptr));
	}
	static jlong buffer_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newBuffer(toBuffer(self).clonePtr());
	}
	static void buffer_clear_ptr(TS_JNI_ARGS, jlong self) {
		toBuffer(self).clearPtr();
	}
	static void buffer_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toBuffer(self).destroyPtr();
	}
	static void buffer_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toBuffer(self).acquirePtr();
	}
	static void buffer_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toBuffer(self).unacquirePtr();
	}
	static jboolean buffer_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).isValidPtr();
	}
	static jboolean buffer_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).isOwnerPtr();
	}
	static jboolean buffer_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).isConstPtr();
	}
	static jint buffer_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).getCountPtr();
	}
	static jlong buffer_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toBuffer(self).getInternalPtr();
	}
	static jint buffer_get_platform(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).getPlatform();
	}
	static jstring buffer_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toBuffer(self).getPlatformName());
	}
	static jint buffer_get_index(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).getIndex();
	}
	static void buffer_clear(TS_JNI_ARGS, jlong self) {
		toBuffer(self).clear();
	}
	static jboolean buffer_is_created(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).isCreated();
	}
	static void buffer_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toBuffer(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring buffer_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toBuffer(self).getName().get());
	}
	static jboolean buffer_create(TS_JNI_ARGS, jlong self, jint flags, jlong size, jint format) {
		return toBuffer(self).create((Buffer::Flags)flags, (size_t)size, (Format)format);
	}
	static jboolean buffer_is_mapped(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).isMapped();
	}
	static jint buffer_get_flags(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).getFlags();
	}
	static jboolean buffer_has_flag(TS_JNI_ARGS, jlong self, jint flags) {
		return toBuffer(self).hasFlag((Buffer::Flags)flags);
	}
	static jboolean buffer_has_flags(TS_JNI_ARGS, jlong self, jint flags) {
		return toBuffer(self).hasFlags((Buffer::Flags)flags);
	}
	static jstring buffer_get_flags_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toBuffer(self).getFlagsName().get());
	}
	static jint buffer_get_format(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).getFormat();
	}
	static jstring buffer_get_format_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toBuffer(self).getFormatName());
	}
	static jint buffer_get_components(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).getComponents();
	}
	static jint buffer_get_pixel_size(TS_JNI_ARGS, jlong self) {
		return toBuffer(self).getPixelSize();
	}
	static jlong buffer_get_size(TS_JNI_ARGS, jlong self) {
		return (jlong)toBuffer(self).getSize();
	}
	static jlong buffer_get_page_size(TS_JNI_ARGS, jlong self) {
		return (jlong)toBuffer(self).getPageSize();
	}
	static jstring buffer_get_description(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toBuffer(self).getDescription().get());
	}
	static const JNINativeMethod buffer_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)buffer_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)buffer_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)buffer_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)buffer_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)buffer_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)buffer_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)buffer_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)buffer_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)buffer_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)buffer_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)buffer_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)buffer_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)buffer_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)buffer_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)buffer_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)buffer_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)buffer_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)buffer_is_created },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)buffer_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)buffer_get_name },
		{ (char*)"create_", (char*)"(JIJI)Z", (void*)buffer_create },
		{ (char*)"is_mapped", (char*)"(J)Z", (void*)buffer_is_mapped },
		{ (char*)"get_flags", (char*)"(J)I", (void*)buffer_get_flags },
		{ (char*)"has_flag", (char*)"(JI)Z", (void*)buffer_has_flag },
		{ (char*)"has_flags", (char*)"(JI)Z", (void*)buffer_has_flags },
		{ (char*)"get_flags_name", (char*)"(J)Ljava/lang/String;", (void*)buffer_get_flags_name },
		{ (char*)"get_format", (char*)"(J)I", (void*)buffer_get_format },
		{ (char*)"get_format_name", (char*)"(J)Ljava/lang/String;", (void*)buffer_get_format_name },
		{ (char*)"get_components", (char*)"(J)I", (void*)buffer_get_components },
		{ (char*)"get_pixel_size", (char*)"(J)I", (void*)buffer_get_pixel_size },
		{ (char*)"get_size", (char*)"(J)J", (void*)buffer_get_size },
		{ (char*)"get_page_size", (char*)"(J)J", (void*)buffer_get_page_size },
		{ (char*)"get_description", (char*)"(J)Ljava/lang/String;", (void*)buffer_get_description },
	};
	
	// Tellusim::BufferTable
	static jlong buffer_table_new(TS_JNI_ARGS) {
		return newBufferTable();
	}
	static void buffer_table_delete(TS_JNI_ARGS, jlong self) {
		delete (BufferTable*)self;
	}
	static jboolean buffer_table_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toBufferTable(self) == toBufferTable(ptr));
	}
	static jlong buffer_table_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newBufferTable(toBufferTable(self).clonePtr());
	}
	static void buffer_table_clear_ptr(TS_JNI_ARGS, jlong self) {
		toBufferTable(self).clearPtr();
	}
	static void buffer_table_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toBufferTable(self).destroyPtr();
	}
	static void buffer_table_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toBufferTable(self).acquirePtr();
	}
	static void buffer_table_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toBufferTable(self).unacquirePtr();
	}
	static jboolean buffer_table_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toBufferTable(self).isValidPtr();
	}
	static jboolean buffer_table_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toBufferTable(self).isOwnerPtr();
	}
	static jboolean buffer_table_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toBufferTable(self).isConstPtr();
	}
	static jint buffer_table_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toBufferTable(self).getCountPtr();
	}
	static jlong buffer_table_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toBufferTable(self).getInternalPtr();
	}
	static jint buffer_table_get_platform(TS_JNI_ARGS, jlong self) {
		return toBufferTable(self).getPlatform();
	}
	static jstring buffer_table_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toBufferTable(self).getPlatformName());
	}
	static jint buffer_table_get_index(TS_JNI_ARGS, jlong self) {
		return toBufferTable(self).getIndex();
	}
	static void buffer_table_clear(TS_JNI_ARGS, jlong self) {
		toBufferTable(self).clear();
	}
	static jboolean buffer_table_is_created(TS_JNI_ARGS, jlong self) {
		return toBufferTable(self).isCreated();
	}
	static void buffer_table_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toBufferTable(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring buffer_table_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toBufferTable(self).getName().get());
	}
	static jboolean buffer_table_create(TS_JNI_ARGS, jlong self, jint size) {
		return toBufferTable(self).create((uint32_t)size);
	}
	static jint buffer_table_get_size(TS_JNI_ARGS, jlong self) {
		return toBufferTable(self).getSize();
	}
	static jlong buffer_table_get(TS_JNI_ARGS, jlong self, jint index) {
		return newBuffer(toBufferTable(self).get((uint32_t)index));
	}
	static jboolean buffer_table_is_owner(TS_JNI_ARGS, jlong self, jint index) {
		return toBufferTable(self).isOwner((uint32_t)index);
	}
	static jlong buffer_table_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toBufferTable(self).getMemory();
	}
	static const JNINativeMethod buffer_table_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)buffer_table_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)buffer_table_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)buffer_table_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)buffer_table_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)buffer_table_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)buffer_table_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)buffer_table_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)buffer_table_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)buffer_table_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)buffer_table_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)buffer_table_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)buffer_table_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)buffer_table_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)buffer_table_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)buffer_table_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)buffer_table_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)buffer_table_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)buffer_table_is_created },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)buffer_table_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)buffer_table_get_name },
		{ (char*)"create_", (char*)"(JI)Z", (void*)buffer_table_create },
		{ (char*)"get_size", (char*)"(J)I", (void*)buffer_table_get_size },
		{ (char*)"get_", (char*)"(JI)J", (void*)buffer_table_get },
		{ (char*)"is_owner", (char*)"(JI)Z", (void*)buffer_table_is_owner },
		{ (char*)"get_memory", (char*)"(J)J", (void*)buffer_table_get_memory },
	};
	
	// Tellusim::D3D12Buffer
	static jlong d3d12_buffer_new(TS_JNI_ARGS) {
		return newD3D12Buffer();
	}
	static void d3d12_buffer_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Buffer*)self;
	}
	static jboolean d3d12_buffer_equal_buffer_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Buffer(self).operator==(toBuffer(base));
	}
	static jlong d3d12_buffer_cast_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Buffer(toBuffer(self));
	}
	static jlong d3d12_buffer_base_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newBuffer(toD3D12Buffer(self).getBuffer());
	}
	static jboolean d3d12_buffer_create(TS_JNI_ARGS, jlong self, jint flags, jlong buffer, jint state) {
		return toD3D12Buffer(self).create((Buffer::Flags)flags, (ID3D12Resource*)buffer, (uint32_t)state);
	}
	static jlong d3d12_buffer_get_d3d12_buffer(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Buffer(self).getD3D12Buffer();
	}
	static jlong d3d12_buffer_get_unordered_access_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Buffer(self).getUnorderedAccessView();
	}
	static jlong d3d12_buffer_get_shader_resource_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Buffer(self).getShaderResourceView();
	}
	static jlong d3d12_buffer_get_buffer_address(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Buffer(self).getBufferAddress();
	}
	static void d3d12_buffer_set_buffer_state(TS_JNI_ARGS, jlong self, jint state) {
		toD3D12Buffer(self).setBufferState((uint32_t)state);
	}
	static jint d3d12_buffer_get_buffer_state(TS_JNI_ARGS, jlong self) {
		return toD3D12Buffer(self).getBufferState();
	}
	static jlong d3d12_buffer_get_shared_handle(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Buffer(self).getSharedHandle();
	}
	static jlong d3d12_buffer_get_interop_handle(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Buffer(self).getInteropHandle();
	}
	static const JNINativeMethod d3d12_buffer_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_buffer_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_buffer_delete },
		{ (char*)"equal_buffer_ptr", (char*)"(JJ)Z", (void*)d3d12_buffer_equal_buffer_ptr },
		{ (char*)"cast_buffer_ptr", (char*)"(J)J", (void*)d3d12_buffer_cast_buffer_ptr },
		{ (char*)"base_buffer_ptr", (char*)"(J)J", (void*)d3d12_buffer_base_buffer_ptr },
		{ (char*)"create_", (char*)"(JIJI)Z", (void*)d3d12_buffer_create },
		{ (char*)"get_d3d12_buffer", (char*)"(J)J", (void*)d3d12_buffer_get_d3d12_buffer },
		{ (char*)"get_unordered_access_view", (char*)"(J)J", (void*)d3d12_buffer_get_unordered_access_view },
		{ (char*)"get_shader_resource_view", (char*)"(J)J", (void*)d3d12_buffer_get_shader_resource_view },
		{ (char*)"get_buffer_address", (char*)"(J)J", (void*)d3d12_buffer_get_buffer_address },
		{ (char*)"set_buffer_state", (char*)"(JI)V", (void*)d3d12_buffer_set_buffer_state },
		{ (char*)"get_buffer_state", (char*)"(J)I", (void*)d3d12_buffer_get_buffer_state },
		{ (char*)"get_shared_handle", (char*)"(J)J", (void*)d3d12_buffer_get_shared_handle },
		{ (char*)"get_interop_handle", (char*)"(J)J", (void*)d3d12_buffer_get_interop_handle },
	};
	
	// Tellusim::D3D11Buffer
	static jlong d3d11_buffer_new(TS_JNI_ARGS) {
		return newD3D11Buffer();
	}
	static void d3d11_buffer_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D11Buffer*)self;
	}
	static jboolean d3d11_buffer_equal_buffer_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D11Buffer(self).operator==(toBuffer(base));
	}
	static jlong d3d11_buffer_cast_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D11Buffer(toBuffer(self));
	}
	static jlong d3d11_buffer_base_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newBuffer(toD3D11Buffer(self).getBuffer());
	}
	static jboolean d3d11_buffer_create(TS_JNI_ARGS, jlong self, jint flags, jlong buffer) {
		return toD3D11Buffer(self).create((Buffer::Flags)flags, (ID3D11Buffer*)buffer);
	}
	static jlong d3d11_buffer_get_d3d11_buffer(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Buffer(self).getD3D11Buffer();
	}
	static jlong d3d11_buffer_get_unordered_access_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Buffer(self).getUnorderedAccessView();
	}
	static jlong d3d11_buffer_get_shader_resource_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Buffer(self).getShaderResourceView();
	}
	static jlong d3d11_buffer_get_interop_handle(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Buffer(self).getInteropHandle();
	}
	static const JNINativeMethod d3d11_buffer_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d11_buffer_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d11_buffer_delete },
		{ (char*)"equal_buffer_ptr", (char*)"(JJ)Z", (void*)d3d11_buffer_equal_buffer_ptr },
		{ (char*)"cast_buffer_ptr", (char*)"(J)J", (void*)d3d11_buffer_cast_buffer_ptr },
		{ (char*)"base_buffer_ptr", (char*)"(J)J", (void*)d3d11_buffer_base_buffer_ptr },
		{ (char*)"create_", (char*)"(JIJ)Z", (void*)d3d11_buffer_create },
		{ (char*)"get_d3d11_buffer", (char*)"(J)J", (void*)d3d11_buffer_get_d3d11_buffer },
		{ (char*)"get_unordered_access_view", (char*)"(J)J", (void*)d3d11_buffer_get_unordered_access_view },
		{ (char*)"get_shader_resource_view", (char*)"(J)J", (void*)d3d11_buffer_get_shader_resource_view },
		{ (char*)"get_interop_handle", (char*)"(J)J", (void*)d3d11_buffer_get_interop_handle },
	};
	
	// Tellusim::MTLBuffer
	static jlong mtl_buffer_new(TS_JNI_ARGS) {
		return newMTLBuffer();
	}
	static void mtl_buffer_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLBuffer*)self;
	}
	static jboolean mtl_buffer_equal_buffer_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLBuffer(self).operator==(toBuffer(base));
	}
	static jlong mtl_buffer_cast_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLBuffer(toBuffer(self));
	}
	static jlong mtl_buffer_base_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newBuffer(toMTLBuffer(self).getBuffer());
	}
	static jboolean mtl_buffer_create(TS_JNI_ARGS, jlong self, jint flags, jlong buffer) {
		return toMTLBuffer(self).create((Buffer::Flags)flags, (void*)buffer);
	}
	static jlong mtl_buffer_get_mtl_buffer(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLBuffer(self).getMTLBuffer();
	}
	static jlong mtl_buffer_get_shared_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLBuffer(self).getSharedPtr();
	}
	static const JNINativeMethod mtl_buffer_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_buffer_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_buffer_delete },
		{ (char*)"equal_buffer_ptr", (char*)"(JJ)Z", (void*)mtl_buffer_equal_buffer_ptr },
		{ (char*)"cast_buffer_ptr", (char*)"(J)J", (void*)mtl_buffer_cast_buffer_ptr },
		{ (char*)"base_buffer_ptr", (char*)"(J)J", (void*)mtl_buffer_base_buffer_ptr },
		{ (char*)"create_", (char*)"(JIJ)Z", (void*)mtl_buffer_create },
		{ (char*)"get_mtl_buffer", (char*)"(J)J", (void*)mtl_buffer_get_mtl_buffer },
		{ (char*)"get_shared_ptr", (char*)"(J)J", (void*)mtl_buffer_get_shared_ptr },
	};
	
	// Tellusim::VKBuffer
	static jlong vk_buffer_new(TS_JNI_ARGS) {
		return newVKBuffer();
	}
	static void vk_buffer_delete(TS_JNI_ARGS, jlong self) {
		delete (VKBuffer*)self;
	}
	static jboolean vk_buffer_equal_buffer_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKBuffer(self).operator==(toBuffer(base));
	}
	static jlong vk_buffer_cast_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newVKBuffer(toBuffer(self));
	}
	static jlong vk_buffer_base_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newBuffer(toVKBuffer(self).getBuffer());
	}
	static jboolean vk_buffer_create(TS_JNI_ARGS, jlong self, jint flags, jlong size, jlong buffer, jint access) {
		return toVKBuffer(self).create((Buffer::Flags)flags, (size_t)size, (VkBuffer)buffer, (uint32_t)access);
	}
	static jlong vk_buffer_get_vk_buffer(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKBuffer(self).getVKBuffer();
	}
	static jlong vk_buffer_get_buffer_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKBuffer(self).getBufferView();
	}
	static jlong vk_buffer_get_buffer_address(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKBuffer(self).getBufferAddress();
	}
	static void vk_buffer_set_buffer_access(TS_JNI_ARGS, jlong self, jint access) {
		toVKBuffer(self).setBufferAccess((uint32_t)access);
	}
	static jint vk_buffer_get_buffer_access(TS_JNI_ARGS, jlong self) {
		return toVKBuffer(self).getBufferAccess();
	}
	static jlong vk_buffer_get_shared_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKBuffer(self).getSharedPtr();
	}
	static jlong vk_buffer_get_interop_handle(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKBuffer(self).getInteropHandle();
	}
	static const JNINativeMethod vk_buffer_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_buffer_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_buffer_delete },
		{ (char*)"equal_buffer_ptr", (char*)"(JJ)Z", (void*)vk_buffer_equal_buffer_ptr },
		{ (char*)"cast_buffer_ptr", (char*)"(J)J", (void*)vk_buffer_cast_buffer_ptr },
		{ (char*)"base_buffer_ptr", (char*)"(J)J", (void*)vk_buffer_base_buffer_ptr },
		{ (char*)"create_", (char*)"(JIJJI)Z", (void*)vk_buffer_create },
		{ (char*)"get_vk_buffer", (char*)"(J)J", (void*)vk_buffer_get_vk_buffer },
		{ (char*)"get_buffer_view", (char*)"(J)J", (void*)vk_buffer_get_buffer_view },
		{ (char*)"get_buffer_address", (char*)"(J)J", (void*)vk_buffer_get_buffer_address },
		{ (char*)"set_buffer_access", (char*)"(JI)V", (void*)vk_buffer_set_buffer_access },
		{ (char*)"get_buffer_access", (char*)"(J)I", (void*)vk_buffer_get_buffer_access },
		{ (char*)"get_shared_ptr", (char*)"(J)J", (void*)vk_buffer_get_shared_ptr },
		{ (char*)"get_interop_handle", (char*)"(J)J", (void*)vk_buffer_get_interop_handle },
	};
	
	// Tellusim::GLBuffer
	static jlong gl_buffer_new(TS_JNI_ARGS) {
		return newGLBuffer();
	}
	static void gl_buffer_delete(TS_JNI_ARGS, jlong self) {
		delete (GLBuffer*)self;
	}
	static jboolean gl_buffer_equal_buffer_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLBuffer(self).operator==(toBuffer(base));
	}
	static jlong gl_buffer_cast_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newGLBuffer(toBuffer(self));
	}
	static jlong gl_buffer_base_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newBuffer(toGLBuffer(self).getBuffer());
	}
	static jboolean gl_buffer_create(TS_JNI_ARGS, jlong self, jint flags, jint target, jint buffer_id) {
		return toGLBuffer(self).create((Buffer::Flags)flags, (uint32_t)target, (uint32_t)buffer_id);
	}
	static jint gl_buffer_get_target(TS_JNI_ARGS, jlong self) {
		return toGLBuffer(self).getTarget();
	}
	static jint gl_buffer_get_buffer_id(TS_JNI_ARGS, jlong self) {
		return toGLBuffer(self).getBufferID();
	}
	static const JNINativeMethod gl_buffer_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gl_buffer_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)gl_buffer_delete },
		{ (char*)"equal_buffer_ptr", (char*)"(JJ)Z", (void*)gl_buffer_equal_buffer_ptr },
		{ (char*)"cast_buffer_ptr", (char*)"(J)J", (void*)gl_buffer_cast_buffer_ptr },
		{ (char*)"base_buffer_ptr", (char*)"(J)J", (void*)gl_buffer_base_buffer_ptr },
		{ (char*)"create_", (char*)"(JIII)Z", (void*)gl_buffer_create },
		{ (char*)"get_target", (char*)"(J)I", (void*)gl_buffer_get_target },
		{ (char*)"get_buffer_id", (char*)"(J)I", (void*)gl_buffer_get_buffer_id },
	};
	
	// Tellusim::GLESBuffer
	static jlong gles_buffer_new(TS_JNI_ARGS) {
		return newGLESBuffer();
	}
	static void gles_buffer_delete(TS_JNI_ARGS, jlong self) {
		delete (GLESBuffer*)self;
	}
	static jboolean gles_buffer_equal_buffer_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLESBuffer(self).operator==(toBuffer(base));
	}
	static jlong gles_buffer_cast_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newGLESBuffer(toBuffer(self));
	}
	static jlong gles_buffer_base_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newBuffer(toGLESBuffer(self).getBuffer());
	}
	static jboolean gles_buffer_create(TS_JNI_ARGS, jlong self, jint flags, jint target, jint buffer_id) {
		return toGLESBuffer(self).create((Buffer::Flags)flags, (uint32_t)target, (uint32_t)buffer_id);
	}
	static jint gles_buffer_get_target(TS_JNI_ARGS, jlong self) {
		return toGLESBuffer(self).getTarget();
	}
	static jint gles_buffer_get_buffer_id(TS_JNI_ARGS, jlong self) {
		return toGLESBuffer(self).getBufferID();
	}
	static const JNINativeMethod gles_buffer_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gles_buffer_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)gles_buffer_delete },
		{ (char*)"equal_buffer_ptr", (char*)"(JJ)Z", (void*)gles_buffer_equal_buffer_ptr },
		{ (char*)"cast_buffer_ptr", (char*)"(J)J", (void*)gles_buffer_cast_buffer_ptr },
		{ (char*)"base_buffer_ptr", (char*)"(J)J", (void*)gles_buffer_base_buffer_ptr },
		{ (char*)"create_", (char*)"(JIII)Z", (void*)gles_buffer_create },
		{ (char*)"get_target", (char*)"(J)I", (void*)gles_buffer_get_target },
		{ (char*)"get_buffer_id", (char*)"(J)I", (void*)gles_buffer_get_buffer_id },
	};
	
	// Tellusim::CUBuffer
	static jlong cu_buffer_new(TS_JNI_ARGS) {
		return newCUBuffer();
	}
	static void cu_buffer_delete(TS_JNI_ARGS, jlong self) {
		delete (CUBuffer*)self;
	}
	static jboolean cu_buffer_equal_buffer_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCUBuffer(self).operator==(toBuffer(base));
	}
	static jlong cu_buffer_cast_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newCUBuffer(toBuffer(self));
	}
	static jlong cu_buffer_base_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newBuffer(toCUBuffer(self).getBuffer());
	}
	static jlong cu_buffer_get_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toCUBuffer(self).getBufferPtr();
	}
	static jlong cu_buffer_get_buffer_data(TS_JNI_ARGS, jlong self) {
		return (jlong)toCUBuffer(self).getBufferData();
	}
	static jlong cu_buffer_get_buffer_event(TS_JNI_ARGS, jlong self) {
		return (jlong)toCUBuffer(self).getBufferEvent();
	}
	static jint cu_buffer_get_array_format(TS_JNI_ARGS, jlong self) {
		return toCUBuffer(self).getArrayFormat();
	}
	static jint cu_buffer_get_array_channels(TS_JNI_ARGS, jlong self) {
		return toCUBuffer(self).getArrayChannels();
	}
	static jlong cu_buffer_get_shared_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toCUBuffer(self).getSharedMemory();
	}
	static const JNINativeMethod cu_buffer_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)cu_buffer_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)cu_buffer_delete },
		{ (char*)"equal_buffer_ptr", (char*)"(JJ)Z", (void*)cu_buffer_equal_buffer_ptr },
		{ (char*)"cast_buffer_ptr", (char*)"(J)J", (void*)cu_buffer_cast_buffer_ptr },
		{ (char*)"base_buffer_ptr", (char*)"(J)J", (void*)cu_buffer_base_buffer_ptr },
		{ (char*)"get_buffer_ptr", (char*)"(J)J", (void*)cu_buffer_get_buffer_ptr },
		{ (char*)"get_buffer_data", (char*)"(J)J", (void*)cu_buffer_get_buffer_data },
		{ (char*)"get_buffer_event", (char*)"(J)J", (void*)cu_buffer_get_buffer_event },
		{ (char*)"get_array_format", (char*)"(J)I", (void*)cu_buffer_get_array_format },
		{ (char*)"get_array_channels", (char*)"(J)I", (void*)cu_buffer_get_array_channels },
		{ (char*)"get_shared_memory", (char*)"(J)J", (void*)cu_buffer_get_shared_memory },
	};
	
	// Tellusim::HIPBuffer
	static jlong hip_buffer_new(TS_JNI_ARGS) {
		return newHIPBuffer();
	}
	static void hip_buffer_delete(TS_JNI_ARGS, jlong self) {
		delete (HIPBuffer*)self;
	}
	static jboolean hip_buffer_equal_buffer_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toHIPBuffer(self).operator==(toBuffer(base));
	}
	static jlong hip_buffer_cast_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newHIPBuffer(toBuffer(self));
	}
	static jlong hip_buffer_base_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newBuffer(toHIPBuffer(self).getBuffer());
	}
	static jlong hip_buffer_get_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toHIPBuffer(self).getBufferPtr();
	}
	static jlong hip_buffer_get_buffer_data(TS_JNI_ARGS, jlong self) {
		return (jlong)toHIPBuffer(self).getBufferData();
	}
	static jlong hip_buffer_get_buffer_event(TS_JNI_ARGS, jlong self) {
		return (jlong)toHIPBuffer(self).getBufferEvent();
	}
	static jint hip_buffer_get_array_format(TS_JNI_ARGS, jlong self) {
		return toHIPBuffer(self).getArrayFormat();
	}
	static jint hip_buffer_get_array_channels(TS_JNI_ARGS, jlong self) {
		return toHIPBuffer(self).getArrayChannels();
	}
	static jlong hip_buffer_get_shared_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toHIPBuffer(self).getSharedMemory();
	}
	static const JNINativeMethod hip_buffer_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)hip_buffer_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)hip_buffer_delete },
		{ (char*)"equal_buffer_ptr", (char*)"(JJ)Z", (void*)hip_buffer_equal_buffer_ptr },
		{ (char*)"cast_buffer_ptr", (char*)"(J)J", (void*)hip_buffer_cast_buffer_ptr },
		{ (char*)"base_buffer_ptr", (char*)"(J)J", (void*)hip_buffer_base_buffer_ptr },
		{ (char*)"get_buffer_ptr", (char*)"(J)J", (void*)hip_buffer_get_buffer_ptr },
		{ (char*)"get_buffer_data", (char*)"(J)J", (void*)hip_buffer_get_buffer_data },
		{ (char*)"get_buffer_event", (char*)"(J)J", (void*)hip_buffer_get_buffer_event },
		{ (char*)"get_array_format", (char*)"(J)I", (void*)hip_buffer_get_array_format },
		{ (char*)"get_array_channels", (char*)"(J)I", (void*)hip_buffer_get_array_channels },
		{ (char*)"get_shared_memory", (char*)"(J)J", (void*)hip_buffer_get_shared_memory },
	};
	
	// Tellusim::FUBuffer
	static jlong fu_buffer_new(TS_JNI_ARGS) {
		return newFUBuffer();
	}
	static jlong fu_buffer_new_1(TS_JNI_ARGS, jlongArray buffers, jboolean owner) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		jlong ret_ = newFUBuffer(buffers_, (bool)owner);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
		return ret_;
	}
	static void fu_buffer_delete(TS_JNI_ARGS, jlong self) {
		delete (FUBuffer*)self;
	}
	static jboolean fu_buffer_equal_buffer_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUBuffer(self).operator==(toBuffer(base));
	}
	static jlong fu_buffer_cast_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newFUBuffer(toBuffer(self));
	}
	static jlong fu_buffer_base_buffer_ptr(TS_JNI_ARGS, jlong self) {
		return newBuffer(toFUBuffer(self).getBuffer());
	}
	static void fu_buffer_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUBuffer(self).setMask((uint32_t)mask);
	}
	static jint fu_buffer_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUBuffer(self).getMask();
	}
	static jint fu_buffer_get_num_buffers(TS_JNI_ARGS, jlong self) {
		return toFUBuffer(self).getNumBuffers();
	}
	static jlong fu_buffer_get_buffer(TS_JNI_ARGS, jlong self, jint index) {
		return newBuffer(toFUBuffer(self).getBuffer((uint32_t)index));
	}
	static jlong fu_buffer_get_buffer_1(TS_JNI_ARGS, jlong self, jint index) {
		return newBuffer(toFUBuffer(self).getBuffer((uint32_t)index));
	}
	static const JNINativeMethod fu_buffer_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_buffer_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_buffer_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_buffer_delete },
		{ (char*)"equal_buffer_ptr", (char*)"(JJ)Z", (void*)fu_buffer_equal_buffer_ptr },
		{ (char*)"cast_buffer_ptr", (char*)"(J)J", (void*)fu_buffer_cast_buffer_ptr },
		{ (char*)"base_buffer_ptr", (char*)"(J)J", (void*)fu_buffer_base_buffer_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_buffer_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_buffer_get_mask },
		{ (char*)"get_num_buffers", (char*)"(J)I", (void*)fu_buffer_get_num_buffers },
		{ (char*)"get_buffer", (char*)"(JI)J", (void*)fu_buffer_get_buffer },
		{ (char*)"get_buffer_1", (char*)"(JI)J", (void*)fu_buffer_get_buffer_1 },
	};
	
	// Tellusim::Command::DrawArraysIndirect
	static jlong command_draw_arrays_indirect_new(TS_JNI_ARGS) {
		return newCommandDrawArraysIndirect();
	}
	static jlong command_draw_arrays_indirect_copy(TS_JNI_ARGS, jlong self) {
		return newCommandDrawArraysIndirect(toCommandDrawArraysIndirect(self));
	}
	static void command_draw_arrays_indirect_delete(TS_JNI_ARGS, jlong self) {
		delete (Command::DrawArraysIndirect*)self;
	}
	static void command_draw_arrays_indirect_set_num_vertices(TS_JNI_ARGS, jlong self, jint num_vertices) {
		toCommandDrawArraysIndirect(self).num_vertices = num_vertices;
	}
	static jint command_draw_arrays_indirect_get_num_vertices(TS_JNI_ARGS, jlong self) {
		return toCommandDrawArraysIndirect(self).num_vertices;
	}
	static void command_draw_arrays_indirect_set_num_instances(TS_JNI_ARGS, jlong self, jint num_instances) {
		toCommandDrawArraysIndirect(self).num_instances = num_instances;
	}
	static jint command_draw_arrays_indirect_get_num_instances(TS_JNI_ARGS, jlong self) {
		return toCommandDrawArraysIndirect(self).num_instances;
	}
	static void command_draw_arrays_indirect_set_base_vertex(TS_JNI_ARGS, jlong self, jint base_vertex) {
		toCommandDrawArraysIndirect(self).base_vertex = base_vertex;
	}
	static jint command_draw_arrays_indirect_get_base_vertex(TS_JNI_ARGS, jlong self) {
		return toCommandDrawArraysIndirect(self).base_vertex;
	}
	static void command_draw_arrays_indirect_set_base_instance(TS_JNI_ARGS, jlong self, jint base_instance) {
		toCommandDrawArraysIndirect(self).base_instance = base_instance;
	}
	static jint command_draw_arrays_indirect_get_base_instance(TS_JNI_ARGS, jlong self) {
		return toCommandDrawArraysIndirect(self).base_instance;
	}
	static const JNINativeMethod command_draw_arrays_indirect_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)command_draw_arrays_indirect_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)command_draw_arrays_indirect_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)command_draw_arrays_indirect_delete },
		{ (char*)"set_num_vertices_", (char*)"(JI)V", (void*)command_draw_arrays_indirect_set_num_vertices },
		{ (char*)"get_num_vertices_", (char*)"(J)I", (void*)command_draw_arrays_indirect_get_num_vertices },
		{ (char*)"set_num_instances_", (char*)"(JI)V", (void*)command_draw_arrays_indirect_set_num_instances },
		{ (char*)"get_num_instances_", (char*)"(J)I", (void*)command_draw_arrays_indirect_get_num_instances },
		{ (char*)"set_base_vertex_", (char*)"(JI)V", (void*)command_draw_arrays_indirect_set_base_vertex },
		{ (char*)"get_base_vertex_", (char*)"(J)I", (void*)command_draw_arrays_indirect_get_base_vertex },
		{ (char*)"set_base_instance_", (char*)"(JI)V", (void*)command_draw_arrays_indirect_set_base_instance },
		{ (char*)"get_base_instance_", (char*)"(J)I", (void*)command_draw_arrays_indirect_get_base_instance },
	};
	// Tellusim::Command::DrawElementsIndirect
	static jlong command_draw_elements_indirect_new(TS_JNI_ARGS) {
		return newCommandDrawElementsIndirect();
	}
	static jlong command_draw_elements_indirect_copy(TS_JNI_ARGS, jlong self) {
		return newCommandDrawElementsIndirect(toCommandDrawElementsIndirect(self));
	}
	static void command_draw_elements_indirect_delete(TS_JNI_ARGS, jlong self) {
		delete (Command::DrawElementsIndirect*)self;
	}
	static void command_draw_elements_indirect_set_num_indices(TS_JNI_ARGS, jlong self, jint num_indices) {
		toCommandDrawElementsIndirect(self).num_indices = num_indices;
	}
	static jint command_draw_elements_indirect_get_num_indices(TS_JNI_ARGS, jlong self) {
		return toCommandDrawElementsIndirect(self).num_indices;
	}
	static void command_draw_elements_indirect_set_num_instances(TS_JNI_ARGS, jlong self, jint num_instances) {
		toCommandDrawElementsIndirect(self).num_instances = num_instances;
	}
	static jint command_draw_elements_indirect_get_num_instances(TS_JNI_ARGS, jlong self) {
		return toCommandDrawElementsIndirect(self).num_instances;
	}
	static void command_draw_elements_indirect_set_base_index(TS_JNI_ARGS, jlong self, jint base_index) {
		toCommandDrawElementsIndirect(self).base_index = base_index;
	}
	static jint command_draw_elements_indirect_get_base_index(TS_JNI_ARGS, jlong self) {
		return toCommandDrawElementsIndirect(self).base_index;
	}
	static void command_draw_elements_indirect_set_base_vertex(TS_JNI_ARGS, jlong self, jint base_vertex) {
		toCommandDrawElementsIndirect(self).base_vertex = base_vertex;
	}
	static jint command_draw_elements_indirect_get_base_vertex(TS_JNI_ARGS, jlong self) {
		return toCommandDrawElementsIndirect(self).base_vertex;
	}
	static void command_draw_elements_indirect_set_base_instance(TS_JNI_ARGS, jlong self, jint base_instance) {
		toCommandDrawElementsIndirect(self).base_instance = base_instance;
	}
	static jint command_draw_elements_indirect_get_base_instance(TS_JNI_ARGS, jlong self) {
		return toCommandDrawElementsIndirect(self).base_instance;
	}
	static const JNINativeMethod command_draw_elements_indirect_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)command_draw_elements_indirect_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)command_draw_elements_indirect_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)command_draw_elements_indirect_delete },
		{ (char*)"set_num_indices_", (char*)"(JI)V", (void*)command_draw_elements_indirect_set_num_indices },
		{ (char*)"get_num_indices_", (char*)"(J)I", (void*)command_draw_elements_indirect_get_num_indices },
		{ (char*)"set_num_instances_", (char*)"(JI)V", (void*)command_draw_elements_indirect_set_num_instances },
		{ (char*)"get_num_instances_", (char*)"(J)I", (void*)command_draw_elements_indirect_get_num_instances },
		{ (char*)"set_base_index_", (char*)"(JI)V", (void*)command_draw_elements_indirect_set_base_index },
		{ (char*)"get_base_index_", (char*)"(J)I", (void*)command_draw_elements_indirect_get_base_index },
		{ (char*)"set_base_vertex_", (char*)"(JI)V", (void*)command_draw_elements_indirect_set_base_vertex },
		{ (char*)"get_base_vertex_", (char*)"(J)I", (void*)command_draw_elements_indirect_get_base_vertex },
		{ (char*)"set_base_instance_", (char*)"(JI)V", (void*)command_draw_elements_indirect_set_base_instance },
		{ (char*)"get_base_instance_", (char*)"(J)I", (void*)command_draw_elements_indirect_get_base_instance },
	};
	// Tellusim::Command::DrawMeshIndirect
	static jlong command_draw_mesh_indirect_new(TS_JNI_ARGS) {
		return newCommandDrawMeshIndirect();
	}
	static jlong command_draw_mesh_indirect_copy(TS_JNI_ARGS, jlong self) {
		return newCommandDrawMeshIndirect(toCommandDrawMeshIndirect(self));
	}
	static void command_draw_mesh_indirect_delete(TS_JNI_ARGS, jlong self) {
		delete (Command::DrawMeshIndirect*)self;
	}
	static void command_draw_mesh_indirect_set_group_width(TS_JNI_ARGS, jlong self, jint group_width) {
		toCommandDrawMeshIndirect(self).group_width = group_width;
	}
	static jint command_draw_mesh_indirect_get_group_width(TS_JNI_ARGS, jlong self) {
		return toCommandDrawMeshIndirect(self).group_width;
	}
	static void command_draw_mesh_indirect_set_group_height(TS_JNI_ARGS, jlong self, jint group_height) {
		toCommandDrawMeshIndirect(self).group_height = group_height;
	}
	static jint command_draw_mesh_indirect_get_group_height(TS_JNI_ARGS, jlong self) {
		return toCommandDrawMeshIndirect(self).group_height;
	}
	static void command_draw_mesh_indirect_set_group_depth(TS_JNI_ARGS, jlong self, jint group_depth) {
		toCommandDrawMeshIndirect(self).group_depth = group_depth;
	}
	static jint command_draw_mesh_indirect_get_group_depth(TS_JNI_ARGS, jlong self) {
		return toCommandDrawMeshIndirect(self).group_depth;
	}
	static const JNINativeMethod command_draw_mesh_indirect_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)command_draw_mesh_indirect_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)command_draw_mesh_indirect_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)command_draw_mesh_indirect_delete },
		{ (char*)"set_group_width_", (char*)"(JI)V", (void*)command_draw_mesh_indirect_set_group_width },
		{ (char*)"get_group_width_", (char*)"(J)I", (void*)command_draw_mesh_indirect_get_group_width },
		{ (char*)"set_group_height_", (char*)"(JI)V", (void*)command_draw_mesh_indirect_set_group_height },
		{ (char*)"get_group_height_", (char*)"(J)I", (void*)command_draw_mesh_indirect_get_group_height },
		{ (char*)"set_group_depth_", (char*)"(JI)V", (void*)command_draw_mesh_indirect_set_group_depth },
		{ (char*)"get_group_depth_", (char*)"(J)I", (void*)command_draw_mesh_indirect_get_group_depth },
	};
	// Tellusim::Command
	static jlong command_new(TS_JNI_ARGS) {
		return newCommand();
	}
	static void command_delete(TS_JNI_ARGS, jlong self) {
		delete (Command*)self;
	}
	static jboolean command_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toCommand(self) == toCommand(ptr));
	}
	static jlong command_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newCommand(toCommand(self).clonePtr());
	}
	static void command_clear_ptr(TS_JNI_ARGS, jlong self) {
		toCommand(self).clearPtr();
	}
	static void command_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toCommand(self).destroyPtr();
	}
	static void command_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toCommand(self).acquirePtr();
	}
	static void command_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toCommand(self).unacquirePtr();
	}
	static jboolean command_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toCommand(self).isValidPtr();
	}
	static jboolean command_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toCommand(self).isOwnerPtr();
	}
	static jboolean command_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toCommand(self).isConstPtr();
	}
	static jint command_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toCommand(self).getCountPtr();
	}
	static jlong command_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toCommand(self).getInternalPtr();
	}
	static jint command_get_platform(TS_JNI_ARGS, jlong self) {
		return toCommand(self).getPlatform();
	}
	static jstring command_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toCommand(self).getPlatformName());
	}
	static jint command_get_index(TS_JNI_ARGS, jlong self) {
		return toCommand(self).getIndex();
	}
	static void command_set_pipeline(TS_JNI_ARGS, jlong self, jlong pipeline) {
		toCommand(self).setPipeline(toPipeline(pipeline));
	}
	static jlong command_get_pipeline(TS_JNI_ARGS, jlong self) {
		return newPipeline(toCommand(self).getPipeline());
	}
	static void command_set_viewport(TS_JNI_ARGS, jlong self, jint index, jlong viewport) {
		toCommand(self).setViewport((uint32_t)index, toViewport(viewport));
	}
	static void command_set_viewports(TS_JNI_ARGS, jlong self, jlongArray viewports) {
		Array<Viewport> viewports_((uint32_t)env->GetArrayLength(viewports));
		jlong *viewports__ = env->GetLongArrayElements(viewports, nullptr);
		for(uint32_t i = 0; i < viewports_.size(); i++) viewports_[i] = toViewport(viewports__[i]);
		toCommand(self).setViewports(viewports_.get(), viewports_.size());
		if(viewports__) env->ReleaseLongArrayElements(viewports, viewports__, 0);
	}
	static void command_set_scissor(TS_JNI_ARGS, jlong self, jint index, jlong scissor) {
		toCommand(self).setScissor((uint32_t)index, toScissor(scissor));
	}
	static void command_set_scissors(TS_JNI_ARGS, jlong self, jlongArray scissors) {
		Array<Scissor> scissors_((uint32_t)env->GetArrayLength(scissors));
		jlong *scissors__ = env->GetLongArrayElements(scissors, nullptr);
		for(uint32_t i = 0; i < scissors_.size(); i++) scissors_[i] = toScissor(scissors__[i]);
		toCommand(self).setScissors(scissors_.get(), scissors_.size());
		if(scissors__) env->ReleaseLongArrayElements(scissors, scissors__, 0);
	}
	static void command_set_sampler(TS_JNI_ARGS, jlong self, jint index, jlong sampler) {
		toCommand(self).setSampler((uint32_t)index, toSampler(sampler));
	}
	static void command_set_samplers(TS_JNI_ARGS, jlong self, jint index, jlongArray samplers) {
		Array<Sampler> samplers_((uint32_t)env->GetArrayLength(samplers));
		jlong *samplers__ = env->GetLongArrayElements(samplers, nullptr);
		for(uint32_t i = 0; i < samplers_.size(); i++) samplers_[i] = toSampler(samplers__[i]);
		toCommand(self).setSamplers((uint32_t)index, samplers_);
		if(samplers__) env->ReleaseLongArrayElements(samplers, samplers__, 0);
	}
	static void command_set_texture(TS_JNI_ARGS, jlong self, jint index, jlong texture) {
		toCommand(self).setTexture((uint32_t)index, toTexture(texture));
	}
	static void command_set_texture_1(TS_JNI_ARGS, jlong self, jint index, jlong texture, jlong slice) {
		toCommand(self).setTexture((uint32_t)index, toTexture(texture), toSlice(slice));
	}
	static void command_set_textures(TS_JNI_ARGS, jlong self, jint index, jlongArray textures) {
		Array<Texture> textures_((uint32_t)env->GetArrayLength(textures));
		jlong *textures__ = env->GetLongArrayElements(textures, nullptr);
		for(uint32_t i = 0; i < textures_.size(); i++) textures_[i] = toTexture(textures__[i]);
		toCommand(self).setTextures((uint32_t)index, textures_);
		if(textures__) env->ReleaseLongArrayElements(textures, textures__, 0);
	}
	static void command_set_surface_texture(TS_JNI_ARGS, jlong self, jint index, jlong texture) {
		toCommand(self).setSurfaceTexture((uint32_t)index, toTexture(texture));
	}
	static void command_set_surface_texture_1(TS_JNI_ARGS, jlong self, jint index, jlong texture, jlong slice, jint format) {
		toCommand(self).setSurfaceTexture((uint32_t)index, toTexture(texture), toSlice(slice), (Format)format);
	}
	static void command_set_surface_textures(TS_JNI_ARGS, jlong self, jint index, jlongArray textures) {
		Array<Texture> textures_((uint32_t)env->GetArrayLength(textures));
		jlong *textures__ = env->GetLongArrayElements(textures, nullptr);
		for(uint32_t i = 0; i < textures_.size(); i++) textures_[i] = toTexture(textures__[i]);
		toCommand(self).setSurfaceTextures((uint32_t)index, textures_);
		if(textures__) env->ReleaseLongArrayElements(textures, textures__, 0);
	}
	static jlong command_get_uniform_data(TS_JNI_ARGS, jlong self, jint index, jlong size) {
		return (jlong)toCommand(self).getUniformData((uint32_t)index, (size_t)size);
	}
	static void command_set_uniform_data(TS_JNI_ARGS, jlong self, jint index, jbyteArray src) {
		toCommand(self).setUniformData((uint32_t)index, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static void command_set_uniform_buffer(TS_JNI_ARGS, jlong self, jint index, jlong buffer, jlong offset, jlong size) {
		toCommand(self).setUniformBuffer((uint32_t)index, toBuffer(buffer), (size_t)offset, (size_t)size);
	}
	static void command_set_uniform_offset(TS_JNI_ARGS, jlong self, jint index, jlong offset, jboolean relative) {
		toCommand(self).setUniformOffset((uint32_t)index, (size_t)offset, (bool)relative);
	}
	static void command_set_uniform_buffers(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		toCommand(self).setUniformBuffers((uint32_t)index, buffers_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
	}
	static void command_set_uniform_buffers_1(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers, jlongArray offsets) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		jlong *offsets__ = env->GetLongArrayElements(offsets, nullptr);
		Array<size_t> offsets_((uint32_t)env->GetArrayLength(offsets));
		for(uint32_t i = 0; i < offsets_.size(); i++) offsets_[i] = (size_t)offsets__[i];
		toCommand(self).setUniformBuffers((uint32_t)index, buffers_, offsets_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
		if(offsets_) env->ReleaseLongArrayElements(offsets, offsets__, 0);
	}
	static jlong command_get_storage_data(TS_JNI_ARGS, jlong self, jint index, jlong size) {
		return (jlong)toCommand(self).getStorageData((uint32_t)index, (size_t)size);
	}
	static void command_set_storage_data(TS_JNI_ARGS, jlong self, jint index, jbyteArray src) {
		toCommand(self).setStorageData((uint32_t)index, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static void command_set_storage_buffer(TS_JNI_ARGS, jlong self, jint index, jlong buffer, jlong offset, jlong size) {
		toCommand(self).setStorageBuffer((uint32_t)index, toBuffer(buffer), (size_t)offset, (size_t)size);
	}
	static void command_set_storage_offset(TS_JNI_ARGS, jlong self, jint index, jlong offset, jboolean relative) {
		toCommand(self).setStorageOffset((uint32_t)index, (size_t)offset, (bool)relative);
	}
	static void command_set_storage_buffers(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		toCommand(self).setStorageBuffers((uint32_t)index, buffers_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
	}
	static void command_set_storage_buffers_1(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers, jlongArray offsets) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		jlong *offsets__ = env->GetLongArrayElements(offsets, nullptr);
		Array<size_t> offsets_((uint32_t)env->GetArrayLength(offsets));
		for(uint32_t i = 0; i < offsets_.size(); i++) offsets_[i] = (size_t)offsets__[i];
		toCommand(self).setStorageBuffers((uint32_t)index, buffers_, offsets_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
		if(offsets_) env->ReleaseLongArrayElements(offsets, offsets__, 0);
	}
	static void command_set_tracing(TS_JNI_ARGS, jlong self, jint index, jlong tracing) {
		toCommand(self).setTracing((uint32_t)index, toTracing(tracing));
	}
	static void command_set_tracings(TS_JNI_ARGS, jlong self, jint index, jlongArray tracings) {
		Array<Tracing> tracings_((uint32_t)env->GetArrayLength(tracings));
		jlong *tracings__ = env->GetLongArrayElements(tracings, nullptr);
		for(uint32_t i = 0; i < tracings_.size(); i++) tracings_[i] = toTracing(tracings__[i]);
		toCommand(self).setTracings((uint32_t)index, tracings_);
		if(tracings__) env->ReleaseLongArrayElements(tracings, tracings__, 0);
	}
	static void command_set_texel_buffer(TS_JNI_ARGS, jlong self, jint index, jlong buffer) {
		toCommand(self).setTexelBuffer((uint32_t)index, toBuffer(buffer));
	}
	static void command_set_texel_buffers(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		toCommand(self).setTexelBuffers((uint32_t)index, buffers_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
	}
	static void command_set_texture_table(TS_JNI_ARGS, jlong self, jint index, jlong table) {
		toCommand(self).setTextureTable((uint32_t)index, toTextureTable(table));
	}
	static void command_set_texture_tables(TS_JNI_ARGS, jlong self, jint index, jlongArray tables) {
		Array<TextureTable> tables_((uint32_t)env->GetArrayLength(tables));
		jlong *tables__ = env->GetLongArrayElements(tables, nullptr);
		for(uint32_t i = 0; i < tables_.size(); i++) tables_[i] = toTextureTable(tables__[i]);
		toCommand(self).setTextureTables((uint32_t)index, tables_);
		if(tables__) env->ReleaseLongArrayElements(tables, tables__, 0);
	}
	static void command_set_storage_table(TS_JNI_ARGS, jlong self, jint index, jlong table) {
		toCommand(self).setStorageTable((uint32_t)index, toBufferTable(table));
	}
	static void command_set_storage_tables(TS_JNI_ARGS, jlong self, jint index, jlongArray tables) {
		Array<BufferTable> tables_((uint32_t)env->GetArrayLength(tables));
		jlong *tables__ = env->GetLongArrayElements(tables, nullptr);
		for(uint32_t i = 0; i < tables_.size(); i++) tables_[i] = toBufferTable(tables__[i]);
		toCommand(self).setStorageTables((uint32_t)index, tables_);
		if(tables__) env->ReleaseLongArrayElements(tables, tables__, 0);
	}
	static jlong command_get_vertex_data(TS_JNI_ARGS, jlong self, jint index, jlong size) {
		return (jlong)toCommand(self).getVertexData((uint32_t)index, (size_t)size);
	}
	static void command_set_vertex_data(TS_JNI_ARGS, jlong self, jint index, jbyteArray src) {
		toCommand(self).setVertexData((uint32_t)index, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static void command_set_vertex_buffer(TS_JNI_ARGS, jlong self, jint index, jlong buffer, jlong offset) {
		toCommand(self).setVertexBuffer((uint32_t)index, toBuffer(buffer), (size_t)offset);
	}
	static void command_set_vertex_offset(TS_JNI_ARGS, jlong self, jint index, jlong offset, jboolean relative) {
		toCommand(self).setVertexOffset((uint32_t)index, (size_t)offset, (bool)relative);
	}
	static void command_set_vertex_buffers(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		toCommand(self).setVertexBuffers((uint32_t)index, buffers_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
	}
	static void command_set_vertex_buffers_1(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers, jlongArray offsets) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		jlong *offsets__ = env->GetLongArrayElements(offsets, nullptr);
		Array<size_t> offsets_((uint32_t)env->GetArrayLength(offsets));
		for(uint32_t i = 0; i < offsets_.size(); i++) offsets_[i] = (size_t)offsets__[i];
		toCommand(self).setVertexBuffers((uint32_t)index, buffers_, offsets_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
		if(offsets_) env->ReleaseLongArrayElements(offsets, offsets__, 0);
	}
	static jlong command_get_index_data(TS_JNI_ARGS, jlong self, jint format, jlong size) {
		return (jlong)toCommand(self).getIndexData((Format)format, (size_t)size);
	}
	static void command_set_index_data(TS_JNI_ARGS, jlong self, jint format, jbyteArray src) {
		toCommand(self).setIndexData((Format)format, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static void command_set_index_buffer(TS_JNI_ARGS, jlong self, jint format, jlong buffer, jlong offset) {
		toCommand(self).setIndexBuffer((Format)format, toBuffer(buffer), (size_t)offset);
	}
	static void command_set_index_offset(TS_JNI_ARGS, jlong self, jlong offset, jboolean relative) {
		toCommand(self).setIndexOffset((size_t)offset, (bool)relative);
	}
	static jlong command_get_indirect_data(TS_JNI_ARGS, jlong self, jlong size) {
		return (jlong)toCommand(self).getIndirectData((size_t)size);
	}
	static void command_set_indirect_data(TS_JNI_ARGS, jlong self, jbyteArray src) {
		toCommand(self).setIndirectData(ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static void command_set_indirect_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset) {
		toCommand(self).setIndirectBuffer(toBuffer(buffer), (size_t)offset);
	}
	static void command_set_indirect_offset(TS_JNI_ARGS, jlong self, jlong offset, jboolean relative) {
		toCommand(self).setIndirectOffset((size_t)offset, (bool)relative);
	}
	static void command_set_blend_color(TS_JNI_ARGS, jlong self, jlong color) {
		toCommand(self).setBlendColor(toColor(color));
	}
	static void command_set_blend_color_1(TS_JNI_ARGS, jlong self, jfloat r, jfloat g, jfloat b, jfloat a) {
		toCommand(self).setBlendColor(r, g, b, a);
	}
	static void command_set_stencil_ref(TS_JNI_ARGS, jlong self, jint ref) {
		toCommand(self).setStencilRef((uint32_t)ref);
	}
	static void command_draw_arrays(TS_JNI_ARGS, jlong self, jint num_vertices, jint base_vertex) {
		toCommand(self).drawArrays((uint32_t)num_vertices, (uint32_t)base_vertex);
	}
	static void command_draw_arrays_instanced(TS_JNI_ARGS, jlong self, jint num_vertices, jint base_vertex, jint num_instances, jint base_instance) {
		toCommand(self).drawArraysInstanced((uint32_t)num_vertices, (uint32_t)base_vertex, (uint32_t)num_instances, (uint32_t)base_instance);
	}
	static void command_draw_arrays_indirect(TS_JNI_ARGS, jlong self, jint num_draws, jlong stride) {
		toCommand(self).drawArraysIndirect((uint32_t)num_draws, (size_t)stride);
	}
	static void command_draw_arrays_indirect_1(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset, jint num_draws, jlong stride) {
		toCommand(self).drawArraysIndirect(toBuffer(buffer), (size_t)offset, (uint32_t)num_draws, (size_t)stride);
	}
	static void command_draw_elements(TS_JNI_ARGS, jlong self, jint num_indices, jint base_index, jint base_vertex) {
		toCommand(self).drawElements((uint32_t)num_indices, (uint32_t)base_index, base_vertex);
	}
	static void command_draw_elements_instanced(TS_JNI_ARGS, jlong self, jint num_indices, jint base_index, jint num_instances) {
		toCommand(self).drawElementsInstanced((uint32_t)num_indices, (uint32_t)base_index, (uint32_t)num_instances);
	}
	static void command_draw_elements_instanced_1(TS_JNI_ARGS, jlong self, jint num_indices, jint base_index, jint base_vertex, jint num_instances, jint base_instance) {
		toCommand(self).drawElementsInstanced((uint32_t)num_indices, (uint32_t)base_index, base_vertex, (uint32_t)num_instances, (uint32_t)base_instance);
	}
	static void command_draw_elements_indirect(TS_JNI_ARGS, jlong self, jint num_draws, jlong stride) {
		toCommand(self).drawElementsIndirect((uint32_t)num_draws, (size_t)stride);
	}
	static void command_draw_elements_indirect_1(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset, jint num_draws, jlong stride) {
		toCommand(self).drawElementsIndirect(toBuffer(buffer), (size_t)offset, (uint32_t)num_draws, (size_t)stride);
	}
	static void command_draw_mesh(TS_JNI_ARGS, jlong self, jint width, jint height, jint depth) {
		toCommand(self).drawMesh((uint32_t)width, (uint32_t)height, (uint32_t)depth);
	}
	static void command_draw_mesh_indirect(TS_JNI_ARGS, jlong self, jint num_draws, jlong stride) {
		toCommand(self).drawMeshIndirect((uint32_t)num_draws, (size_t)stride);
	}
	static void command_draw_mesh_indirect_1(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset, jint num_draws, jlong stride) {
		toCommand(self).drawMeshIndirect(toBuffer(buffer), (size_t)offset, (uint32_t)num_draws, (size_t)stride);
	}
	static void command_begin_conditional(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset) {
		toCommand(self).beginConditional(toBuffer(buffer), (size_t)offset);
	}
	static void command_end_conditional(TS_JNI_ARGS, jlong self) {
		toCommand(self).endConditional();
	}
	static jboolean command_begin_query(TS_JNI_ARGS, jlong self, jlong query) {
		return toCommand(self).beginQuery(toQuery(query));
	}
	static void command_end_query(TS_JNI_ARGS, jlong self, jlong query) {
		toCommand(self).endQuery(toQuery(query));
	}
	static const JNINativeMethod command_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)command_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)command_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)command_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)command_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)command_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)command_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)command_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)command_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)command_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)command_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)command_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)command_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)command_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)command_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)command_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)command_get_index },
		{ (char*)"set_pipeline", (char*)"(JJ)V", (void*)command_set_pipeline },
		{ (char*)"get_pipeline", (char*)"(J)J", (void*)command_get_pipeline },
		{ (char*)"set_viewport", (char*)"(JIJ)V", (void*)command_set_viewport },
		{ (char*)"set_viewports", (char*)"(J[J)V", (void*)command_set_viewports },
		{ (char*)"set_scissor", (char*)"(JIJ)V", (void*)command_set_scissor },
		{ (char*)"set_scissors", (char*)"(J[J)V", (void*)command_set_scissors },
		{ (char*)"set_sampler", (char*)"(JIJ)V", (void*)command_set_sampler },
		{ (char*)"set_samplers", (char*)"(JI[J)V", (void*)command_set_samplers },
		{ (char*)"set_texture", (char*)"(JIJ)V", (void*)command_set_texture },
		{ (char*)"set_texture_1", (char*)"(JIJJ)V", (void*)command_set_texture_1 },
		{ (char*)"set_textures", (char*)"(JI[J)V", (void*)command_set_textures },
		{ (char*)"set_surface_texture", (char*)"(JIJ)V", (void*)command_set_surface_texture },
		{ (char*)"set_surface_texture_1", (char*)"(JIJJI)V", (void*)command_set_surface_texture_1 },
		{ (char*)"set_surface_textures", (char*)"(JI[J)V", (void*)command_set_surface_textures },
		{ (char*)"get_uniform_data", (char*)"(JIJ)J", (void*)command_get_uniform_data },
		{ (char*)"set_uniform_data", (char*)"(JI[B)V", (void*)command_set_uniform_data },
		{ (char*)"set_uniform_buffer", (char*)"(JIJJJ)V", (void*)command_set_uniform_buffer },
		{ (char*)"set_uniform_offset", (char*)"(JIJZ)V", (void*)command_set_uniform_offset },
		{ (char*)"set_uniform_buffers", (char*)"(JI[J)V", (void*)command_set_uniform_buffers },
		{ (char*)"set_uniform_buffers_1", (char*)"(JI[J[J)V", (void*)command_set_uniform_buffers_1 },
		{ (char*)"get_storage_data", (char*)"(JIJ)J", (void*)command_get_storage_data },
		{ (char*)"set_storage_data", (char*)"(JI[B)V", (void*)command_set_storage_data },
		{ (char*)"set_storage_buffer", (char*)"(JIJJJ)V", (void*)command_set_storage_buffer },
		{ (char*)"set_storage_offset", (char*)"(JIJZ)V", (void*)command_set_storage_offset },
		{ (char*)"set_storage_buffers", (char*)"(JI[J)V", (void*)command_set_storage_buffers },
		{ (char*)"set_storage_buffers_1", (char*)"(JI[J[J)V", (void*)command_set_storage_buffers_1 },
		{ (char*)"set_tracing", (char*)"(JIJ)V", (void*)command_set_tracing },
		{ (char*)"set_tracings", (char*)"(JI[J)V", (void*)command_set_tracings },
		{ (char*)"set_texel_buffer", (char*)"(JIJ)V", (void*)command_set_texel_buffer },
		{ (char*)"set_texel_buffers", (char*)"(JI[J)V", (void*)command_set_texel_buffers },
		{ (char*)"set_texture_table", (char*)"(JIJ)V", (void*)command_set_texture_table },
		{ (char*)"set_texture_tables", (char*)"(JI[J)V", (void*)command_set_texture_tables },
		{ (char*)"set_storage_table", (char*)"(JIJ)V", (void*)command_set_storage_table },
		{ (char*)"set_storage_tables", (char*)"(JI[J)V", (void*)command_set_storage_tables },
		{ (char*)"get_vertex_data", (char*)"(JIJ)J", (void*)command_get_vertex_data },
		{ (char*)"set_vertex_data", (char*)"(JI[B)V", (void*)command_set_vertex_data },
		{ (char*)"set_vertex_buffer", (char*)"(JIJJ)V", (void*)command_set_vertex_buffer },
		{ (char*)"set_vertex_offset", (char*)"(JIJZ)V", (void*)command_set_vertex_offset },
		{ (char*)"set_vertex_buffers", (char*)"(JI[J)V", (void*)command_set_vertex_buffers },
		{ (char*)"set_vertex_buffers_1", (char*)"(JI[J[J)V", (void*)command_set_vertex_buffers_1 },
		{ (char*)"get_index_data", (char*)"(JIJ)J", (void*)command_get_index_data },
		{ (char*)"set_index_data", (char*)"(JI[B)V", (void*)command_set_index_data },
		{ (char*)"set_index_buffer", (char*)"(JIJJ)V", (void*)command_set_index_buffer },
		{ (char*)"set_index_offset", (char*)"(JJZ)V", (void*)command_set_index_offset },
		{ (char*)"get_indirect_data", (char*)"(JJ)J", (void*)command_get_indirect_data },
		{ (char*)"set_indirect_data", (char*)"(J[B)V", (void*)command_set_indirect_data },
		{ (char*)"set_indirect_buffer", (char*)"(JJJ)V", (void*)command_set_indirect_buffer },
		{ (char*)"set_indirect_offset", (char*)"(JJZ)V", (void*)command_set_indirect_offset },
		{ (char*)"set_blend_color", (char*)"(JJ)V", (void*)command_set_blend_color },
		{ (char*)"set_blend_color_1", (char*)"(JFFFF)V", (void*)command_set_blend_color_1 },
		{ (char*)"set_stencil_ref", (char*)"(JI)V", (void*)command_set_stencil_ref },
		{ (char*)"draw_arrays", (char*)"(JII)V", (void*)command_draw_arrays },
		{ (char*)"draw_arrays_instanced", (char*)"(JIIII)V", (void*)command_draw_arrays_instanced },
		{ (char*)"draw_arrays_indirect", (char*)"(JIJ)V", (void*)command_draw_arrays_indirect },
		{ (char*)"draw_arrays_indirect_1", (char*)"(JJJIJ)V", (void*)command_draw_arrays_indirect_1 },
		{ (char*)"draw_elements", (char*)"(JIII)V", (void*)command_draw_elements },
		{ (char*)"draw_elements_instanced", (char*)"(JIII)V", (void*)command_draw_elements_instanced },
		{ (char*)"draw_elements_instanced_1", (char*)"(JIIIII)V", (void*)command_draw_elements_instanced_1 },
		{ (char*)"draw_elements_indirect", (char*)"(JIJ)V", (void*)command_draw_elements_indirect },
		{ (char*)"draw_elements_indirect_1", (char*)"(JJJIJ)V", (void*)command_draw_elements_indirect_1 },
		{ (char*)"draw_mesh", (char*)"(JIII)V", (void*)command_draw_mesh },
		{ (char*)"draw_mesh_indirect", (char*)"(JIJ)V", (void*)command_draw_mesh_indirect },
		{ (char*)"draw_mesh_indirect_1", (char*)"(JJJIJ)V", (void*)command_draw_mesh_indirect_1 },
		{ (char*)"begin_conditional", (char*)"(JJJ)V", (void*)command_begin_conditional },
		{ (char*)"end_conditional", (char*)"(J)V", (void*)command_end_conditional },
		{ (char*)"begin_query", (char*)"(JJ)Z", (void*)command_begin_query },
		{ (char*)"end_query", (char*)"(JJ)V", (void*)command_end_query },
	};
	
	// Tellusim::D3D12Command
	static jlong d3d12_command_new(TS_JNI_ARGS) {
		return newD3D12Command();
	}
	static void d3d12_command_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Command*)self;
	}
	static jboolean d3d12_command_equal_command_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Command(self).operator==(toCommand(base));
	}
	static jlong d3d12_command_cast_command_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Command(toCommand(self));
	}
	static jlong d3d12_command_base_command_ptr(TS_JNI_ARGS, jlong self) {
		return newCommand(toD3D12Command(self).getCommand());
	}
	static jlong d3d12_command_get_d3d12_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Command(self).getD3D12Command();
	}
	static void d3d12_command_update(TS_JNI_ARGS, jlong self) {
		toD3D12Command(self).update();
	}
	static const JNINativeMethod d3d12_command_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_command_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_command_delete },
		{ (char*)"equal_command_ptr", (char*)"(JJ)Z", (void*)d3d12_command_equal_command_ptr },
		{ (char*)"cast_command_ptr", (char*)"(J)J", (void*)d3d12_command_cast_command_ptr },
		{ (char*)"base_command_ptr", (char*)"(J)J", (void*)d3d12_command_base_command_ptr },
		{ (char*)"get_d3d12_command", (char*)"(J)J", (void*)d3d12_command_get_d3d12_command },
		{ (char*)"update_", (char*)"(J)V", (void*)d3d12_command_update },
	};
	
	// Tellusim::MTLCommand
	static jlong mtl_command_new(TS_JNI_ARGS) {
		return newMTLCommand();
	}
	static void mtl_command_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLCommand*)self;
	}
	static jboolean mtl_command_equal_command_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLCommand(self).operator==(toCommand(base));
	}
	static jlong mtl_command_cast_command_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLCommand(toCommand(self));
	}
	static jlong mtl_command_base_command_ptr(TS_JNI_ARGS, jlong self) {
		return newCommand(toMTLCommand(self).getCommand());
	}
	static jlong mtl_command_get_encoder(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLCommand(self).getEncoder();
	}
	static void mtl_command_flush(TS_JNI_ARGS, jlong self, jlong encoder, jboolean enqueue) {
		toMTLCommand(self).flush((void*)encoder, (bool)enqueue);
	}
	static void mtl_command_flush_1(TS_JNI_ARGS, jlong self, jboolean create, jboolean enqueue) {
		toMTLCommand(self).flush((bool)create, (bool)enqueue);
	}
	static void mtl_command_update(TS_JNI_ARGS, jlong self) {
		toMTLCommand(self).update();
	}
	static const JNINativeMethod mtl_command_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_command_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_command_delete },
		{ (char*)"equal_command_ptr", (char*)"(JJ)Z", (void*)mtl_command_equal_command_ptr },
		{ (char*)"cast_command_ptr", (char*)"(J)J", (void*)mtl_command_cast_command_ptr },
		{ (char*)"base_command_ptr", (char*)"(J)J", (void*)mtl_command_base_command_ptr },
		{ (char*)"get_encoder", (char*)"(J)J", (void*)mtl_command_get_encoder },
		{ (char*)"flush_", (char*)"(JJZ)V", (void*)mtl_command_flush },
		{ (char*)"flush_1", (char*)"(JZZ)V", (void*)mtl_command_flush_1 },
		{ (char*)"update_", (char*)"(J)V", (void*)mtl_command_update },
	};
	
	// Tellusim::VKCommand
	static jlong vk_command_new(TS_JNI_ARGS) {
		return newVKCommand();
	}
	static void vk_command_delete(TS_JNI_ARGS, jlong self) {
		delete (VKCommand*)self;
	}
	static jboolean vk_command_equal_command_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKCommand(self).operator==(toCommand(base));
	}
	static jlong vk_command_cast_command_ptr(TS_JNI_ARGS, jlong self) {
		return newVKCommand(toCommand(self));
	}
	static jlong vk_command_base_command_ptr(TS_JNI_ARGS, jlong self) {
		return newCommand(toVKCommand(self).getCommand());
	}
	static jlong vk_command_get_vk_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCommand(self).getVKCommand();
	}
	static jlong vk_command_get_sampler_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCommand(self).getSamplerDescriptor();
	}
	static jlong vk_command_get_image_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCommand(self).getImageDescriptor();
	}
	static jlong vk_command_get_buffer_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCommand(self).getBufferDescriptor();
	}
	static jlong vk_command_get_tracing_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCommand(self).getTracingDescriptor();
	}
	static jlong vk_command_get_texel_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCommand(self).getTexelDescriptor();
	}
	static void vk_command_update(TS_JNI_ARGS, jlong self) {
		toVKCommand(self).update();
	}
	static const JNINativeMethod vk_command_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_command_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_command_delete },
		{ (char*)"equal_command_ptr", (char*)"(JJ)Z", (void*)vk_command_equal_command_ptr },
		{ (char*)"cast_command_ptr", (char*)"(J)J", (void*)vk_command_cast_command_ptr },
		{ (char*)"base_command_ptr", (char*)"(J)J", (void*)vk_command_base_command_ptr },
		{ (char*)"get_vk_command", (char*)"(J)J", (void*)vk_command_get_vk_command },
		{ (char*)"get_sampler_descriptor", (char*)"(J)J", (void*)vk_command_get_sampler_descriptor },
		{ (char*)"get_image_descriptor", (char*)"(J)J", (void*)vk_command_get_image_descriptor },
		{ (char*)"get_buffer_descriptor", (char*)"(J)J", (void*)vk_command_get_buffer_descriptor },
		{ (char*)"get_tracing_descriptor", (char*)"(J)J", (void*)vk_command_get_tracing_descriptor },
		{ (char*)"get_texel_descriptor", (char*)"(J)J", (void*)vk_command_get_texel_descriptor },
		{ (char*)"update_", (char*)"(J)V", (void*)vk_command_update },
	};
	
	// Tellusim::FUCommand
	static jlong fu_command_new(TS_JNI_ARGS) {
		return newFUCommand();
	}
	static jlong fu_command_new_1(TS_JNI_ARGS, jlongArray commands, jboolean owner) {
		Array<Command> commands_((uint32_t)env->GetArrayLength(commands));
		jlong *commands__ = env->GetLongArrayElements(commands, nullptr);
		for(uint32_t i = 0; i < commands_.size(); i++) commands_[i] = toCommand(commands__[i]);
		jlong ret_ = newFUCommand(commands_, (bool)owner);
		if(commands__) env->ReleaseLongArrayElements(commands, commands__, 0);
		return ret_;
	}
	static void fu_command_delete(TS_JNI_ARGS, jlong self) {
		delete (FUCommand*)self;
	}
	static jboolean fu_command_equal_command_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUCommand(self).operator==(toCommand(base));
	}
	static jlong fu_command_cast_command_ptr(TS_JNI_ARGS, jlong self) {
		return newFUCommand(toCommand(self));
	}
	static jlong fu_command_base_command_ptr(TS_JNI_ARGS, jlong self) {
		return newCommand(toFUCommand(self).getCommand());
	}
	static void fu_command_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUCommand(self).setMask((uint32_t)mask);
	}
	static jint fu_command_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUCommand(self).getMask();
	}
	static jint fu_command_get_num_commands(TS_JNI_ARGS, jlong self) {
		return toFUCommand(self).getNumCommands();
	}
	static jlong fu_command_get_command(TS_JNI_ARGS, jlong self, jint index) {
		return newCommand(toFUCommand(self).getCommand((uint32_t)index));
	}
	static jlong fu_command_get_command_1(TS_JNI_ARGS, jlong self, jint index) {
		return newCommand(toFUCommand(self).getCommand((uint32_t)index));
	}
	static const JNINativeMethod fu_command_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_command_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_command_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_command_delete },
		{ (char*)"equal_command_ptr", (char*)"(JJ)Z", (void*)fu_command_equal_command_ptr },
		{ (char*)"cast_command_ptr", (char*)"(J)J", (void*)fu_command_cast_command_ptr },
		{ (char*)"base_command_ptr", (char*)"(J)J", (void*)fu_command_base_command_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_command_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_command_get_mask },
		{ (char*)"get_num_commands", (char*)"(J)I", (void*)fu_command_get_num_commands },
		{ (char*)"get_command", (char*)"(JI)J", (void*)fu_command_get_command },
		{ (char*)"get_command_1", (char*)"(JI)J", (void*)fu_command_get_command_1 },
	};
	
	// Tellusim::Compute::DispatchIndirect
	static jlong compute_dispatch_indirect_new(TS_JNI_ARGS) {
		return newComputeDispatchIndirect();
	}
	static jlong compute_dispatch_indirect_copy(TS_JNI_ARGS, jlong self) {
		return newComputeDispatchIndirect(toComputeDispatchIndirect(self));
	}
	static void compute_dispatch_indirect_delete(TS_JNI_ARGS, jlong self) {
		delete (Compute::DispatchIndirect*)self;
	}
	static void compute_dispatch_indirect_set_group_width(TS_JNI_ARGS, jlong self, jint group_width) {
		toComputeDispatchIndirect(self).group_width = group_width;
	}
	static jint compute_dispatch_indirect_get_group_width(TS_JNI_ARGS, jlong self) {
		return toComputeDispatchIndirect(self).group_width;
	}
	static void compute_dispatch_indirect_set_group_height(TS_JNI_ARGS, jlong self, jint group_height) {
		toComputeDispatchIndirect(self).group_height = group_height;
	}
	static jint compute_dispatch_indirect_get_group_height(TS_JNI_ARGS, jlong self) {
		return toComputeDispatchIndirect(self).group_height;
	}
	static void compute_dispatch_indirect_set_group_depth(TS_JNI_ARGS, jlong self, jint group_depth) {
		toComputeDispatchIndirect(self).group_depth = group_depth;
	}
	static jint compute_dispatch_indirect_get_group_depth(TS_JNI_ARGS, jlong self) {
		return toComputeDispatchIndirect(self).group_depth;
	}
	static const JNINativeMethod compute_dispatch_indirect_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)compute_dispatch_indirect_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)compute_dispatch_indirect_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)compute_dispatch_indirect_delete },
		{ (char*)"set_group_width_", (char*)"(JI)V", (void*)compute_dispatch_indirect_set_group_width },
		{ (char*)"get_group_width_", (char*)"(J)I", (void*)compute_dispatch_indirect_get_group_width },
		{ (char*)"set_group_height_", (char*)"(JI)V", (void*)compute_dispatch_indirect_set_group_height },
		{ (char*)"get_group_height_", (char*)"(J)I", (void*)compute_dispatch_indirect_get_group_height },
		{ (char*)"set_group_depth_", (char*)"(JI)V", (void*)compute_dispatch_indirect_set_group_depth },
		{ (char*)"get_group_depth_", (char*)"(J)I", (void*)compute_dispatch_indirect_get_group_depth },
	};
	// Tellusim::Compute
	static jlong compute_new(TS_JNI_ARGS) {
		return newCompute();
	}
	static void compute_delete(TS_JNI_ARGS, jlong self) {
		delete (Compute*)self;
	}
	static jboolean compute_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toCompute(self) == toCompute(ptr));
	}
	static jlong compute_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newCompute(toCompute(self).clonePtr());
	}
	static void compute_clear_ptr(TS_JNI_ARGS, jlong self) {
		toCompute(self).clearPtr();
	}
	static void compute_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toCompute(self).destroyPtr();
	}
	static void compute_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toCompute(self).acquirePtr();
	}
	static void compute_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toCompute(self).unacquirePtr();
	}
	static jboolean compute_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toCompute(self).isValidPtr();
	}
	static jboolean compute_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toCompute(self).isOwnerPtr();
	}
	static jboolean compute_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toCompute(self).isConstPtr();
	}
	static jint compute_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toCompute(self).getCountPtr();
	}
	static jlong compute_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toCompute(self).getInternalPtr();
	}
	static jint compute_get_platform(TS_JNI_ARGS, jlong self) {
		return toCompute(self).getPlatform();
	}
	static jstring compute_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toCompute(self).getPlatformName());
	}
	static jint compute_get_index(TS_JNI_ARGS, jlong self) {
		return toCompute(self).getIndex();
	}
	static void compute_set_kernel(TS_JNI_ARGS, jlong self, jlong kernel) {
		toCompute(self).setKernel(toKernel(kernel));
	}
	static jlong compute_get_kernel(TS_JNI_ARGS, jlong self) {
		return newKernel(toCompute(self).getKernel());
	}
	static void compute_set_traversal(TS_JNI_ARGS, jlong self, jlong traversal) {
		toCompute(self).setTraversal(toTraversal(traversal));
	}
	static jlong compute_get_traversal(TS_JNI_ARGS, jlong self) {
		return newTraversal(toCompute(self).getTraversal());
	}
	static void compute_set_sampler(TS_JNI_ARGS, jlong self, jint index, jlong sampler) {
		toCompute(self).setSampler((uint32_t)index, toSampler(sampler));
	}
	static void compute_set_samplers(TS_JNI_ARGS, jlong self, jint index, jlongArray samplers) {
		Array<Sampler> samplers_((uint32_t)env->GetArrayLength(samplers));
		jlong *samplers__ = env->GetLongArrayElements(samplers, nullptr);
		for(uint32_t i = 0; i < samplers_.size(); i++) samplers_[i] = toSampler(samplers__[i]);
		toCompute(self).setSamplers((uint32_t)index, samplers_);
		if(samplers__) env->ReleaseLongArrayElements(samplers, samplers__, 0);
	}
	static void compute_set_texture(TS_JNI_ARGS, jlong self, jint index, jlong texture) {
		toCompute(self).setTexture((uint32_t)index, toTexture(texture));
	}
	static void compute_set_texture_1(TS_JNI_ARGS, jlong self, jint index, jlong texture, jlong slice) {
		toCompute(self).setTexture((uint32_t)index, toTexture(texture), toSlice(slice));
	}
	static void compute_set_textures(TS_JNI_ARGS, jlong self, jint index, jlongArray textures) {
		Array<Texture> textures_((uint32_t)env->GetArrayLength(textures));
		jlong *textures__ = env->GetLongArrayElements(textures, nullptr);
		for(uint32_t i = 0; i < textures_.size(); i++) textures_[i] = toTexture(textures__[i]);
		toCompute(self).setTextures((uint32_t)index, textures_);
		if(textures__) env->ReleaseLongArrayElements(textures, textures__, 0);
	}
	static void compute_set_surface_texture(TS_JNI_ARGS, jlong self, jint index, jlong texture) {
		toCompute(self).setSurfaceTexture((uint32_t)index, toTexture(texture));
	}
	static void compute_set_surface_texture_1(TS_JNI_ARGS, jlong self, jint index, jlong texture, jlong slice, jint format) {
		toCompute(self).setSurfaceTexture((uint32_t)index, toTexture(texture), toSlice(slice), (Format)format);
	}
	static void compute_set_surface_textures(TS_JNI_ARGS, jlong self, jint index, jlongArray textures) {
		Array<Texture> textures_((uint32_t)env->GetArrayLength(textures));
		jlong *textures__ = env->GetLongArrayElements(textures, nullptr);
		for(uint32_t i = 0; i < textures_.size(); i++) textures_[i] = toTexture(textures__[i]);
		toCompute(self).setSurfaceTextures((uint32_t)index, textures_);
		if(textures__) env->ReleaseLongArrayElements(textures, textures__, 0);
	}
	static jlong compute_get_uniform_data(TS_JNI_ARGS, jlong self, jint index, jlong size) {
		return (jlong)toCompute(self).getUniformData((uint32_t)index, (size_t)size);
	}
	static void compute_set_uniform_data(TS_JNI_ARGS, jlong self, jint index, jbyteArray src) {
		toCompute(self).setUniformData((uint32_t)index, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static void compute_set_uniform_buffer(TS_JNI_ARGS, jlong self, jint index, jlong buffer, jlong offset, jlong size) {
		toCompute(self).setUniformBuffer((uint32_t)index, toBuffer(buffer), (size_t)offset, (size_t)size);
	}
	static void compute_set_uniform_offset(TS_JNI_ARGS, jlong self, jint index, jlong offset, jboolean relative) {
		toCompute(self).setUniformOffset((uint32_t)index, (size_t)offset, (bool)relative);
	}
	static void compute_set_uniform_buffers(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		toCompute(self).setUniformBuffers((uint32_t)index, buffers_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
	}
	static void compute_set_uniform_buffers_1(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers, jlongArray offsets) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		jlong *offsets__ = env->GetLongArrayElements(offsets, nullptr);
		Array<size_t> offsets_((uint32_t)env->GetArrayLength(offsets));
		for(uint32_t i = 0; i < offsets_.size(); i++) offsets_[i] = (size_t)offsets__[i];
		toCompute(self).setUniformBuffers((uint32_t)index, buffers_, offsets_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
		if(offsets_) env->ReleaseLongArrayElements(offsets, offsets__, 0);
	}
	static jlong compute_get_storage_data(TS_JNI_ARGS, jlong self, jint index, jlong size) {
		return (jlong)toCompute(self).getStorageData((uint32_t)index, (size_t)size);
	}
	static void compute_set_storage_data(TS_JNI_ARGS, jlong self, jint index, jbyteArray src) {
		toCompute(self).setStorageData((uint32_t)index, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static void compute_set_storage_buffer(TS_JNI_ARGS, jlong self, jint index, jlong buffer, jlong offset, jlong size) {
		toCompute(self).setStorageBuffer((uint32_t)index, toBuffer(buffer), (size_t)offset, (size_t)size);
	}
	static void compute_set_storage_offset(TS_JNI_ARGS, jlong self, jint index, jlong offset, jboolean relative) {
		toCompute(self).setStorageOffset((uint32_t)index, (size_t)offset, (bool)relative);
	}
	static void compute_set_storage_buffers(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		toCompute(self).setStorageBuffers((uint32_t)index, buffers_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
	}
	static void compute_set_storage_buffers_1(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers, jlongArray offsets) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		jlong *offsets__ = env->GetLongArrayElements(offsets, nullptr);
		Array<size_t> offsets_((uint32_t)env->GetArrayLength(offsets));
		for(uint32_t i = 0; i < offsets_.size(); i++) offsets_[i] = (size_t)offsets__[i];
		toCompute(self).setStorageBuffers((uint32_t)index, buffers_, offsets_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
		if(offsets_) env->ReleaseLongArrayElements(offsets, offsets__, 0);
	}
	static void compute_set_tracing(TS_JNI_ARGS, jlong self, jint index, jlong tracing) {
		toCompute(self).setTracing((uint32_t)index, toTracing(tracing));
	}
	static void compute_set_tracings(TS_JNI_ARGS, jlong self, jint index, jlongArray tracings) {
		Array<Tracing> tracings_((uint32_t)env->GetArrayLength(tracings));
		jlong *tracings__ = env->GetLongArrayElements(tracings, nullptr);
		for(uint32_t i = 0; i < tracings_.size(); i++) tracings_[i] = toTracing(tracings__[i]);
		toCompute(self).setTracings((uint32_t)index, tracings_);
		if(tracings__) env->ReleaseLongArrayElements(tracings, tracings__, 0);
	}
	static void compute_set_texel_buffer(TS_JNI_ARGS, jlong self, jint index, jlong buffer) {
		toCompute(self).setTexelBuffer((uint32_t)index, toBuffer(buffer));
	}
	static void compute_set_texel_buffers(TS_JNI_ARGS, jlong self, jint index, jlongArray buffers) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		toCompute(self).setTexelBuffers((uint32_t)index, buffers_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
	}
	static void compute_set_texture_table(TS_JNI_ARGS, jlong self, jint index, jlong table) {
		toCompute(self).setTextureTable((uint32_t)index, toTextureTable(table));
	}
	static void compute_set_texture_tables(TS_JNI_ARGS, jlong self, jint index, jlongArray tables) {
		Array<TextureTable> tables_((uint32_t)env->GetArrayLength(tables));
		jlong *tables__ = env->GetLongArrayElements(tables, nullptr);
		for(uint32_t i = 0; i < tables_.size(); i++) tables_[i] = toTextureTable(tables__[i]);
		toCompute(self).setTextureTables((uint32_t)index, tables_);
		if(tables__) env->ReleaseLongArrayElements(tables, tables__, 0);
	}
	static void compute_set_storage_table(TS_JNI_ARGS, jlong self, jint index, jlong table) {
		toCompute(self).setStorageTable((uint32_t)index, toBufferTable(table));
	}
	static void compute_set_storage_tables(TS_JNI_ARGS, jlong self, jint index, jlongArray tables) {
		Array<BufferTable> tables_((uint32_t)env->GetArrayLength(tables));
		jlong *tables__ = env->GetLongArrayElements(tables, nullptr);
		for(uint32_t i = 0; i < tables_.size(); i++) tables_[i] = toBufferTable(tables__[i]);
		toCompute(self).setStorageTables((uint32_t)index, tables_);
		if(tables__) env->ReleaseLongArrayElements(tables, tables__, 0);
	}
	static jlong compute_get_indirect_data(TS_JNI_ARGS, jlong self, jlong size) {
		return (jlong)toCompute(self).getIndirectData((size_t)size);
	}
	static void compute_set_indirect_data(TS_JNI_ARGS, jlong self, jbyteArray src) {
		toCompute(self).setIndirectData(ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static void compute_set_indirect_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset) {
		toCompute(self).setIndirectBuffer(toBuffer(buffer), (size_t)offset);
	}
	static void compute_set_indirect_offset(TS_JNI_ARGS, jlong self, jlong offset, jboolean relative) {
		toCompute(self).setIndirectOffset((size_t)offset, (bool)relative);
	}
	static void compute_dispatch(TS_JNI_ARGS, jlong self, jint width, jint height, jint depth) {
		toCompute(self).dispatch((uint32_t)width, (uint32_t)height, (uint32_t)depth);
	}
	static void compute_dispatch_1(TS_JNI_ARGS, jlong self, jlong texture) {
		toCompute(self).dispatch(toTexture(texture));
	}
	static void compute_dispatch_2(TS_JNI_ARGS, jlong self, jlong size) {
		toCompute(self).dispatch(toSize(size));
	}
	static void compute_dispatch_indirect(TS_JNI_ARGS, jlong self) {
		toCompute(self).dispatchIndirect();
	}
	static jboolean compute_set_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset, jbyteArray src) {
		return toCompute(self).setBuffer(toBuffer(buffer), (size_t)offset, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jboolean compute_set_buffer_1(TS_JNI_ARGS, jlong self, jlong buffer, jbyteArray src) {
		return toCompute(self).setBuffer(toBuffer(buffer), ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jboolean compute_set_buffer_2(TS_JNI_ARGS, jlong self, jlong buffer, jlong src) {
		return toCompute(self).setBuffer(toBuffer(buffer), (const void*)src);
	}
	static jboolean compute_copy_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jlong dest_offset, jlong src, jlong src_offset, jlong size) {
		return toCompute(self).copyBuffer(toBuffer(buffer), (size_t)dest_offset, toBuffer(src), (size_t)src_offset, (size_t)size);
	}
	static jboolean compute_copy_buffer_1(TS_JNI_ARGS, jlong self, jlong buffer, jlong dest_offset, jlong src, jlong size) {
		return toCompute(self).copyBuffer(toBuffer(buffer), (size_t)dest_offset, toBuffer(src), (size_t)size);
	}
	static jboolean compute_copy_buffer_2(TS_JNI_ARGS, jlong self, jlong buffer, jlong src, jlong size) {
		return toCompute(self).copyBuffer(toBuffer(buffer), toBuffer(src), (size_t)size);
	}
	static jboolean compute_copy_buffer_3(TS_JNI_ARGS, jlong self, jlong buffer, jlong src) {
		return toCompute(self).copyBuffer(toBuffer(buffer), toBuffer(src));
	}
	static jboolean compute_clear_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jint format, jlong offset, jbyteArray src) {
		return toCompute(self).clearBuffer(toBuffer(buffer), (Format)format, (size_t)offset, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jboolean compute_clear_buffer_1(TS_JNI_ARGS, jlong self, jlong buffer, jint format, jbyteArray src) {
		return toCompute(self).clearBuffer(toBuffer(buffer), (Format)format, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jboolean compute_clear_buffer_2(TS_JNI_ARGS, jlong self, jlong buffer, jint format, jlong src) {
		return toCompute(self).clearBuffer(toBuffer(buffer), (Format)format, (const void*)src);
	}
	static jboolean compute_clear_buffer_3(TS_JNI_ARGS, jlong self, jlong buffer) {
		return toCompute(self).clearBuffer(toBuffer(buffer));
	}
	static jboolean compute_set_texture_2(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_origin, jlong dest_slice, jlong image, jlong src_slice) {
		return toCompute(self).setTexture(toTexture(texture), toOrigin(dest_origin), toSlice(dest_slice), toImage(image), toSlice(src_slice));
	}
	static jboolean compute_set_texture_3(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_origin, jlong image) {
		return toCompute(self).setTexture(toTexture(texture), toOrigin(dest_origin), toImage(image));
	}
	static jboolean compute_set_texture_4(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_slice, jlong image) {
		return toCompute(self).setTexture(toTexture(texture), toSlice(dest_slice), toImage(image));
	}
	static jboolean compute_set_texture_5(TS_JNI_ARGS, jlong self, jlong texture, jlong image) {
		return toCompute(self).setTexture(toTexture(texture), toImage(image));
	}
	static jboolean compute_copy_texture(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_origin, jlong dest_slice, jlong src, jlong src_region, jlong src_slice) {
		return toCompute(self).copyTexture(toTexture(texture), toOrigin(dest_origin), toSlice(dest_slice), toTexture(src), toRegion(src_region), toSlice(src_slice));
	}
	static jboolean compute_copy_texture_1(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_origin, jlong src, jlong src_region) {
		return toCompute(self).copyTexture(toTexture(texture), toOrigin(dest_origin), toTexture(src), toRegion(src_region));
	}
	static jboolean compute_copy_texture_2(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_slice, jlong src, jlong src_slice) {
		return toCompute(self).copyTexture(toTexture(texture), toSlice(dest_slice), toTexture(src), toSlice(src_slice));
	}
	static jboolean compute_copy_texture_3(TS_JNI_ARGS, jlong self, jlong texture, jlong src) {
		return toCompute(self).copyTexture(toTexture(texture), toTexture(src));
	}
	static jboolean compute_clear_texture(TS_JNI_ARGS, jlong self, jlong texture, jlong region, jlong slice, jlong src) {
		return toCompute(self).clearTexture(toTexture(texture), toRegion(region), toSlice(slice), (const void*)src);
	}
	static jboolean compute_clear_texture_1(TS_JNI_ARGS, jlong self, jlong texture, jlong region, jlong src) {
		return toCompute(self).clearTexture(toTexture(texture), toRegion(region), (const void*)src);
	}
	static jboolean compute_clear_texture_2(TS_JNI_ARGS, jlong self, jlong texture, jlong slice, jlong src) {
		return toCompute(self).clearTexture(toTexture(texture), toSlice(slice), (const void*)src);
	}
	static jboolean compute_clear_texture_3(TS_JNI_ARGS, jlong self, jlong texture, jlong src) {
		return toCompute(self).clearTexture(toTexture(texture), (const void*)src);
	}
	static void compute_barrier(TS_JNI_ARGS, jlong self, jlong texture) {
		toCompute(self).barrier(toTexture(texture));
	}
	static void compute_barrier_1(TS_JNI_ARGS, jlong self, jlong buffer) {
		toCompute(self).barrier(toBuffer(buffer));
	}
	static void compute_barrier_2(TS_JNI_ARGS, jlong self, jlongArray textures) {
		Array<Texture> textures_((uint32_t)env->GetArrayLength(textures));
		jlong *textures__ = env->GetLongArrayElements(textures, nullptr);
		for(uint32_t i = 0; i < textures_.size(); i++) textures_[i] = toTexture(textures__[i]);
		toCompute(self).barrier(textures_);
		if(textures__) env->ReleaseLongArrayElements(textures, textures__, 0);
	}
	static void compute_barrier_3(TS_JNI_ARGS, jlong self, jlongArray buffers) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		toCompute(self).barrier(buffers_);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
	}
	static void compute_begin_conditional(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset) {
		toCompute(self).beginConditional(toBuffer(buffer), (size_t)offset);
	}
	static void compute_end_conditional(TS_JNI_ARGS, jlong self) {
		toCompute(self).endConditional();
	}
	static jboolean compute_begin_query(TS_JNI_ARGS, jlong self, jlong query) {
		return toCompute(self).beginQuery(toQuery(query));
	}
	static void compute_end_query(TS_JNI_ARGS, jlong self, jlong query) {
		toCompute(self).endQuery(toQuery(query));
	}
	static const JNINativeMethod compute_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)compute_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)compute_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)compute_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)compute_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)compute_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)compute_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)compute_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)compute_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)compute_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)compute_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)compute_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)compute_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)compute_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)compute_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)compute_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)compute_get_index },
		{ (char*)"set_kernel", (char*)"(JJ)V", (void*)compute_set_kernel },
		{ (char*)"get_kernel", (char*)"(J)J", (void*)compute_get_kernel },
		{ (char*)"set_traversal", (char*)"(JJ)V", (void*)compute_set_traversal },
		{ (char*)"get_traversal", (char*)"(J)J", (void*)compute_get_traversal },
		{ (char*)"set_sampler", (char*)"(JIJ)V", (void*)compute_set_sampler },
		{ (char*)"set_samplers", (char*)"(JI[J)V", (void*)compute_set_samplers },
		{ (char*)"set_texture", (char*)"(JIJ)V", (void*)compute_set_texture },
		{ (char*)"set_texture_1", (char*)"(JIJJ)V", (void*)compute_set_texture_1 },
		{ (char*)"set_textures", (char*)"(JI[J)V", (void*)compute_set_textures },
		{ (char*)"set_surface_texture", (char*)"(JIJ)V", (void*)compute_set_surface_texture },
		{ (char*)"set_surface_texture_1", (char*)"(JIJJI)V", (void*)compute_set_surface_texture_1 },
		{ (char*)"set_surface_textures", (char*)"(JI[J)V", (void*)compute_set_surface_textures },
		{ (char*)"get_uniform_data", (char*)"(JIJ)J", (void*)compute_get_uniform_data },
		{ (char*)"set_uniform_data", (char*)"(JI[B)V", (void*)compute_set_uniform_data },
		{ (char*)"set_uniform_buffer", (char*)"(JIJJJ)V", (void*)compute_set_uniform_buffer },
		{ (char*)"set_uniform_offset", (char*)"(JIJZ)V", (void*)compute_set_uniform_offset },
		{ (char*)"set_uniform_buffers", (char*)"(JI[J)V", (void*)compute_set_uniform_buffers },
		{ (char*)"set_uniform_buffers_1", (char*)"(JI[J[J)V", (void*)compute_set_uniform_buffers_1 },
		{ (char*)"get_storage_data", (char*)"(JIJ)J", (void*)compute_get_storage_data },
		{ (char*)"set_storage_data", (char*)"(JI[B)V", (void*)compute_set_storage_data },
		{ (char*)"set_storage_buffer", (char*)"(JIJJJ)V", (void*)compute_set_storage_buffer },
		{ (char*)"set_storage_offset", (char*)"(JIJZ)V", (void*)compute_set_storage_offset },
		{ (char*)"set_storage_buffers", (char*)"(JI[J)V", (void*)compute_set_storage_buffers },
		{ (char*)"set_storage_buffers_1", (char*)"(JI[J[J)V", (void*)compute_set_storage_buffers_1 },
		{ (char*)"set_tracing", (char*)"(JIJ)V", (void*)compute_set_tracing },
		{ (char*)"set_tracings", (char*)"(JI[J)V", (void*)compute_set_tracings },
		{ (char*)"set_texel_buffer", (char*)"(JIJ)V", (void*)compute_set_texel_buffer },
		{ (char*)"set_texel_buffers", (char*)"(JI[J)V", (void*)compute_set_texel_buffers },
		{ (char*)"set_texture_table", (char*)"(JIJ)V", (void*)compute_set_texture_table },
		{ (char*)"set_texture_tables", (char*)"(JI[J)V", (void*)compute_set_texture_tables },
		{ (char*)"set_storage_table", (char*)"(JIJ)V", (void*)compute_set_storage_table },
		{ (char*)"set_storage_tables", (char*)"(JI[J)V", (void*)compute_set_storage_tables },
		{ (char*)"get_indirect_data", (char*)"(JJ)J", (void*)compute_get_indirect_data },
		{ (char*)"set_indirect_data", (char*)"(J[B)V", (void*)compute_set_indirect_data },
		{ (char*)"set_indirect_buffer", (char*)"(JJJ)V", (void*)compute_set_indirect_buffer },
		{ (char*)"set_indirect_offset", (char*)"(JJZ)V", (void*)compute_set_indirect_offset },
		{ (char*)"dispatch_", (char*)"(JIII)V", (void*)compute_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJ)V", (void*)compute_dispatch_1 },
		{ (char*)"dispatch_2", (char*)"(JJ)V", (void*)compute_dispatch_2 },
		{ (char*)"dispatch_indirect", (char*)"(J)V", (void*)compute_dispatch_indirect },
		{ (char*)"set_buffer", (char*)"(JJJ[B)Z", (void*)compute_set_buffer },
		{ (char*)"set_buffer_1", (char*)"(JJ[B)Z", (void*)compute_set_buffer_1 },
		{ (char*)"set_buffer_2", (char*)"(JJJ)Z", (void*)compute_set_buffer_2 },
		{ (char*)"copy_buffer", (char*)"(JJJJJJ)Z", (void*)compute_copy_buffer },
		{ (char*)"copy_buffer_1", (char*)"(JJJJJ)Z", (void*)compute_copy_buffer_1 },
		{ (char*)"copy_buffer_2", (char*)"(JJJJ)Z", (void*)compute_copy_buffer_2 },
		{ (char*)"copy_buffer_3", (char*)"(JJJ)Z", (void*)compute_copy_buffer_3 },
		{ (char*)"clear_buffer", (char*)"(JJIJ[B)Z", (void*)compute_clear_buffer },
		{ (char*)"clear_buffer_1", (char*)"(JJI[B)Z", (void*)compute_clear_buffer_1 },
		{ (char*)"clear_buffer_2", (char*)"(JJIJ)Z", (void*)compute_clear_buffer_2 },
		{ (char*)"clear_buffer_3", (char*)"(JJ)Z", (void*)compute_clear_buffer_3 },
		{ (char*)"set_texture_2", (char*)"(JJJJJJ)Z", (void*)compute_set_texture_2 },
		{ (char*)"set_texture_3", (char*)"(JJJJ)Z", (void*)compute_set_texture_3 },
		{ (char*)"set_texture_4", (char*)"(JJJJ)Z", (void*)compute_set_texture_4 },
		{ (char*)"set_texture_5", (char*)"(JJJ)Z", (void*)compute_set_texture_5 },
		{ (char*)"copy_texture", (char*)"(JJJJJJJ)Z", (void*)compute_copy_texture },
		{ (char*)"copy_texture_1", (char*)"(JJJJJ)Z", (void*)compute_copy_texture_1 },
		{ (char*)"copy_texture_2", (char*)"(JJJJJ)Z", (void*)compute_copy_texture_2 },
		{ (char*)"copy_texture_3", (char*)"(JJJ)Z", (void*)compute_copy_texture_3 },
		{ (char*)"clear_texture", (char*)"(JJJJJ)Z", (void*)compute_clear_texture },
		{ (char*)"clear_texture_1", (char*)"(JJJJ)Z", (void*)compute_clear_texture_1 },
		{ (char*)"clear_texture_2", (char*)"(JJJJ)Z", (void*)compute_clear_texture_2 },
		{ (char*)"clear_texture_3", (char*)"(JJJ)Z", (void*)compute_clear_texture_3 },
		{ (char*)"barrier_", (char*)"(JJ)V", (void*)compute_barrier },
		{ (char*)"barrier_1", (char*)"(JJ)V", (void*)compute_barrier_1 },
		{ (char*)"barrier_2", (char*)"(J[J)V", (void*)compute_barrier_2 },
		{ (char*)"barrier_3", (char*)"(J[J)V", (void*)compute_barrier_3 },
		{ (char*)"begin_conditional", (char*)"(JJJ)V", (void*)compute_begin_conditional },
		{ (char*)"end_conditional", (char*)"(J)V", (void*)compute_end_conditional },
		{ (char*)"begin_query", (char*)"(JJ)Z", (void*)compute_begin_query },
		{ (char*)"end_query", (char*)"(JJ)V", (void*)compute_end_query },
	};
	
	// Tellusim::D3D12Compute
	static jlong d3d12_compute_new(TS_JNI_ARGS) {
		return newD3D12Compute();
	}
	static void d3d12_compute_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Compute*)self;
	}
	static jboolean d3d12_compute_equal_compute_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Compute(self).operator==(toCompute(base));
	}
	static jlong d3d12_compute_cast_compute_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Compute(toCompute(self));
	}
	static jlong d3d12_compute_base_compute_ptr(TS_JNI_ARGS, jlong self) {
		return newCompute(toD3D12Compute(self).getCompute());
	}
	static jlong d3d12_compute_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Compute(self).getCommand();
	}
	static void d3d12_compute_update(TS_JNI_ARGS, jlong self) {
		toD3D12Compute(self).update();
	}
	static const JNINativeMethod d3d12_compute_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_compute_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_compute_delete },
		{ (char*)"equal_compute_ptr", (char*)"(JJ)Z", (void*)d3d12_compute_equal_compute_ptr },
		{ (char*)"cast_compute_ptr", (char*)"(J)J", (void*)d3d12_compute_cast_compute_ptr },
		{ (char*)"base_compute_ptr", (char*)"(J)J", (void*)d3d12_compute_base_compute_ptr },
		{ (char*)"get_command", (char*)"(J)J", (void*)d3d12_compute_get_command },
		{ (char*)"update_", (char*)"(J)V", (void*)d3d12_compute_update },
	};
	
	// Tellusim::MTLCompute
	static jlong mtl_compute_new(TS_JNI_ARGS) {
		return newMTLCompute();
	}
	static void mtl_compute_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLCompute*)self;
	}
	static jboolean mtl_compute_equal_compute_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLCompute(self).operator==(toCompute(base));
	}
	static jlong mtl_compute_cast_compute_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLCompute(toCompute(self));
	}
	static jlong mtl_compute_base_compute_ptr(TS_JNI_ARGS, jlong self) {
		return newCompute(toMTLCompute(self).getCompute());
	}
	static jlong mtl_compute_get_encoder(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLCompute(self).getEncoder();
	}
	static void mtl_compute_flush(TS_JNI_ARGS, jlong self, jlong encoder, jboolean enqueue) {
		toMTLCompute(self).flush((void*)encoder, (bool)enqueue);
	}
	static void mtl_compute_flush_1(TS_JNI_ARGS, jlong self, jboolean create, jboolean enqueue) {
		toMTLCompute(self).flush((bool)create, (bool)enqueue);
	}
	static void mtl_compute_update(TS_JNI_ARGS, jlong self) {
		toMTLCompute(self).update();
	}
	static const JNINativeMethod mtl_compute_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_compute_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_compute_delete },
		{ (char*)"equal_compute_ptr", (char*)"(JJ)Z", (void*)mtl_compute_equal_compute_ptr },
		{ (char*)"cast_compute_ptr", (char*)"(J)J", (void*)mtl_compute_cast_compute_ptr },
		{ (char*)"base_compute_ptr", (char*)"(J)J", (void*)mtl_compute_base_compute_ptr },
		{ (char*)"get_encoder", (char*)"(J)J", (void*)mtl_compute_get_encoder },
		{ (char*)"flush_", (char*)"(JJZ)V", (void*)mtl_compute_flush },
		{ (char*)"flush_1", (char*)"(JZZ)V", (void*)mtl_compute_flush_1 },
		{ (char*)"update_", (char*)"(J)V", (void*)mtl_compute_update },
	};
	
	// Tellusim::VKCompute
	static jlong vk_compute_new(TS_JNI_ARGS) {
		return newVKCompute();
	}
	static void vk_compute_delete(TS_JNI_ARGS, jlong self) {
		delete (VKCompute*)self;
	}
	static jboolean vk_compute_equal_compute_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKCompute(self).operator==(toCompute(base));
	}
	static jlong vk_compute_cast_compute_ptr(TS_JNI_ARGS, jlong self) {
		return newVKCompute(toCompute(self));
	}
	static jlong vk_compute_base_compute_ptr(TS_JNI_ARGS, jlong self) {
		return newCompute(toVKCompute(self).getCompute());
	}
	static jlong vk_compute_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCompute(self).getCommand();
	}
	static jlong vk_compute_get_sampler_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCompute(self).getSamplerDescriptor();
	}
	static jlong vk_compute_get_image_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCompute(self).getImageDescriptor();
	}
	static jlong vk_compute_get_buffer_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCompute(self).getBufferDescriptor();
	}
	static jlong vk_compute_get_tracing_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCompute(self).getTracingDescriptor();
	}
	static jlong vk_compute_get_texel_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKCompute(self).getTexelDescriptor();
	}
	static void vk_compute_update(TS_JNI_ARGS, jlong self) {
		toVKCompute(self).update();
	}
	static const JNINativeMethod vk_compute_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_compute_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_compute_delete },
		{ (char*)"equal_compute_ptr", (char*)"(JJ)Z", (void*)vk_compute_equal_compute_ptr },
		{ (char*)"cast_compute_ptr", (char*)"(J)J", (void*)vk_compute_cast_compute_ptr },
		{ (char*)"base_compute_ptr", (char*)"(J)J", (void*)vk_compute_base_compute_ptr },
		{ (char*)"get_command", (char*)"(J)J", (void*)vk_compute_get_command },
		{ (char*)"get_sampler_descriptor", (char*)"(J)J", (void*)vk_compute_get_sampler_descriptor },
		{ (char*)"get_image_descriptor", (char*)"(J)J", (void*)vk_compute_get_image_descriptor },
		{ (char*)"get_buffer_descriptor", (char*)"(J)J", (void*)vk_compute_get_buffer_descriptor },
		{ (char*)"get_tracing_descriptor", (char*)"(J)J", (void*)vk_compute_get_tracing_descriptor },
		{ (char*)"get_texel_descriptor", (char*)"(J)J", (void*)vk_compute_get_texel_descriptor },
		{ (char*)"update_", (char*)"(J)V", (void*)vk_compute_update },
	};
	
	// Tellusim::FUCompute
	static jlong fu_compute_new(TS_JNI_ARGS) {
		return newFUCompute();
	}
	static jlong fu_compute_new_1(TS_JNI_ARGS, jlongArray computes, jboolean owner) {
		Array<Compute> computes_((uint32_t)env->GetArrayLength(computes));
		jlong *computes__ = env->GetLongArrayElements(computes, nullptr);
		for(uint32_t i = 0; i < computes_.size(); i++) computes_[i] = toCompute(computes__[i]);
		jlong ret_ = newFUCompute(computes_, (bool)owner);
		if(computes__) env->ReleaseLongArrayElements(computes, computes__, 0);
		return ret_;
	}
	static void fu_compute_delete(TS_JNI_ARGS, jlong self) {
		delete (FUCompute*)self;
	}
	static jboolean fu_compute_equal_compute_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUCompute(self).operator==(toCompute(base));
	}
	static jlong fu_compute_cast_compute_ptr(TS_JNI_ARGS, jlong self) {
		return newFUCompute(toCompute(self));
	}
	static jlong fu_compute_base_compute_ptr(TS_JNI_ARGS, jlong self) {
		return newCompute(toFUCompute(self).getCompute());
	}
	static void fu_compute_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUCompute(self).setMask((uint32_t)mask);
	}
	static jint fu_compute_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUCompute(self).getMask();
	}
	static jint fu_compute_get_num_computes(TS_JNI_ARGS, jlong self) {
		return toFUCompute(self).getNumComputes();
	}
	static jlong fu_compute_get_compute(TS_JNI_ARGS, jlong self, jint index) {
		return newCompute(toFUCompute(self).getCompute((uint32_t)index));
	}
	static jlong fu_compute_get_compute_1(TS_JNI_ARGS, jlong self, jint index) {
		return newCompute(toFUCompute(self).getCompute((uint32_t)index));
	}
	static const JNINativeMethod fu_compute_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_compute_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_compute_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_compute_delete },
		{ (char*)"equal_compute_ptr", (char*)"(JJ)Z", (void*)fu_compute_equal_compute_ptr },
		{ (char*)"cast_compute_ptr", (char*)"(J)J", (void*)fu_compute_cast_compute_ptr },
		{ (char*)"base_compute_ptr", (char*)"(J)J", (void*)fu_compute_base_compute_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_compute_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_compute_get_mask },
		{ (char*)"get_num_computes", (char*)"(J)I", (void*)fu_compute_get_num_computes },
		{ (char*)"get_compute", (char*)"(JI)J", (void*)fu_compute_get_compute },
		{ (char*)"get_compute_1", (char*)"(JI)J", (void*)fu_compute_get_compute_1 },
	};
	
	// Tellusim::Context
	static jlong context_new(TS_JNI_ARGS) {
		return newContext();
	}
	static jlong context_new_1(TS_JNI_ARGS, jint platform, jint index) {
		return newContext((Platform)platform, (uint32_t)index);
	}
	static void context_delete(TS_JNI_ARGS, jlong self) {
		delete (Context*)self;
	}
	static jboolean context_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toContext(self) == toContext(ptr));
	}
	static jlong context_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newContext(toContext(self).clonePtr());
	}
	static void context_clear_ptr(TS_JNI_ARGS, jlong self) {
		toContext(self).clearPtr();
	}
	static void context_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toContext(self).destroyPtr();
	}
	static void context_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toContext(self).acquirePtr();
	}
	static void context_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toContext(self).unacquirePtr();
	}
	static jboolean context_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toContext(self).isValidPtr();
	}
	static jboolean context_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toContext(self).isOwnerPtr();
	}
	static jboolean context_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toContext(self).isConstPtr();
	}
	static jint context_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toContext(self).getCountPtr();
	}
	static jlong context_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toContext(self).getInternalPtr();
	}
	static jint context_get_platform(TS_JNI_ARGS, jlong self) {
		return toContext(self).getPlatform();
	}
	static jstring context_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toContext(self).getPlatformName());
	}
	static jint context_get_index(TS_JNI_ARGS, jlong self) {
		return toContext(self).getIndex();
	}
	static jboolean context_is_created(TS_JNI_ARGS, jlong self) {
		return toContext(self).isCreated();
	}
	static jboolean context_create(TS_JNI_ARGS, jlong self) {
		return toContext(self).create();
	}
	static jboolean context_flush(TS_JNI_ARGS, jlong self) {
		return toContext(self).flush();
	}
	static jboolean context_finish(TS_JNI_ARGS, jlong self) {
		return toContext(self).finish();
	}
	static const JNINativeMethod context_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)context_new },
		{ (char*)"new_1", (char*)"(II)J", (void*)context_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)context_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)context_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)context_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)context_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)context_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)context_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)context_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)context_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)context_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)context_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)context_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)context_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)context_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)context_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)context_get_index },
		{ (char*)"is_created", (char*)"(J)Z", (void*)context_is_created },
		{ (char*)"create_", (char*)"(J)Z", (void*)context_create },
		{ (char*)"flush_", (char*)"(J)Z", (void*)context_flush },
		{ (char*)"finish_", (char*)"(J)Z", (void*)context_finish },
	};
	
	// Tellusim::D3D12Context
	static jlong d3d12_context_new(TS_JNI_ARGS) {
		return newD3D12Context();
	}
	static void d3d12_context_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Context*)self;
	}
	static jboolean d3d12_context_equal_context_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Context(self).operator==(toContext(base));
	}
	static jlong d3d12_context_cast_context_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Context(toContext(self));
	}
	static jlong d3d12_context_base_context_ptr(TS_JNI_ARGS, jlong self) {
		return newContext(toD3D12Context(self).getContext());
	}
	static jboolean d3d12_context_create(TS_JNI_ARGS, jlong self, jlong device, jlong queue) {
		return toD3D12Context(self).create((ID3D12Device*)device, (ID3D12CommandQueue*)queue);
	}
	static jlong d3d12_context_get_factory(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Context(self).getFactory();
	}
	static jlong d3d12_context_get_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Context(self).getDevice();
	}
	static jlong d3d12_context_get_queue(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Context(self).getQueue();
	}
	static jlong d3d12_context_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Context(self).getCommand();
	}
	static jlong d3d12_context_get_proc_address(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		void* ret_ = D3D12Context::getProcAddress(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jboolean d3d12_context_error(TS_JNI_ARGS, jint result) {
		return D3D12Context::error((uint32_t)result);
	}
	static const JNINativeMethod d3d12_context_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_context_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_context_delete },
		{ (char*)"equal_context_ptr", (char*)"(JJ)Z", (void*)d3d12_context_equal_context_ptr },
		{ (char*)"cast_context_ptr", (char*)"(J)J", (void*)d3d12_context_cast_context_ptr },
		{ (char*)"base_context_ptr", (char*)"(J)J", (void*)d3d12_context_base_context_ptr },
		{ (char*)"create_", (char*)"(JJJ)Z", (void*)d3d12_context_create },
		{ (char*)"get_factory", (char*)"(J)J", (void*)d3d12_context_get_factory },
		{ (char*)"get_device", (char*)"(J)J", (void*)d3d12_context_get_device },
		{ (char*)"get_queue", (char*)"(J)J", (void*)d3d12_context_get_queue },
		{ (char*)"get_command", (char*)"(J)J", (void*)d3d12_context_get_command },
		{ (char*)"get_proc_address", (char*)"(Ljava/lang/String;)J", (void*)d3d12_context_get_proc_address },
		{ (char*)"error_", (char*)"(I)Z", (void*)d3d12_context_error },
	};
	
	// Tellusim::D3D11Context
	static jlong d3d11_context_new(TS_JNI_ARGS) {
		return newD3D11Context();
	}
	static void d3d11_context_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D11Context*)self;
	}
	static jboolean d3d11_context_equal_context_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D11Context(self).operator==(toContext(base));
	}
	static jlong d3d11_context_cast_context_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D11Context(toContext(self));
	}
	static jlong d3d11_context_base_context_ptr(TS_JNI_ARGS, jlong self) {
		return newContext(toD3D11Context(self).getContext());
	}
	static jboolean d3d11_context_create(TS_JNI_ARGS, jlong self, jlong device) {
		return toD3D11Context(self).create((ID3D11Device*)device);
	}
	static jlong d3d11_context_get_factory(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Context(self).getFactory();
	}
	static jlong d3d11_context_get_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Context(self).getDevice();
	}
	static jlong d3d11_context_get_d3d11_context(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Context(self).getD3D11Context();
	}
	static jlong d3d11_context_get_proc_address(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		void* ret_ = D3D11Context::getProcAddress(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jboolean d3d11_context_error(TS_JNI_ARGS, jint result) {
		return D3D11Context::error((uint32_t)result);
	}
	static const JNINativeMethod d3d11_context_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d11_context_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d11_context_delete },
		{ (char*)"equal_context_ptr", (char*)"(JJ)Z", (void*)d3d11_context_equal_context_ptr },
		{ (char*)"cast_context_ptr", (char*)"(J)J", (void*)d3d11_context_cast_context_ptr },
		{ (char*)"base_context_ptr", (char*)"(J)J", (void*)d3d11_context_base_context_ptr },
		{ (char*)"create_", (char*)"(JJ)Z", (void*)d3d11_context_create },
		{ (char*)"get_factory", (char*)"(J)J", (void*)d3d11_context_get_factory },
		{ (char*)"get_device", (char*)"(J)J", (void*)d3d11_context_get_device },
		{ (char*)"get_d3d11_context", (char*)"(J)J", (void*)d3d11_context_get_d3d11_context },
		{ (char*)"get_proc_address", (char*)"(Ljava/lang/String;)J", (void*)d3d11_context_get_proc_address },
		{ (char*)"error_", (char*)"(I)Z", (void*)d3d11_context_error },
	};
	
	// Tellusim::MTLContext
	static jlong mtl_context_new(TS_JNI_ARGS) {
		return newMTLContext();
	}
	static void mtl_context_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLContext*)self;
	}
	static jboolean mtl_context_equal_context_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLContext(self).operator==(toContext(base));
	}
	static jlong mtl_context_cast_context_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLContext(toContext(self));
	}
	static jlong mtl_context_base_context_ptr(TS_JNI_ARGS, jlong self) {
		return newContext(toMTLContext(self).getContext());
	}
	static jboolean mtl_context_create(TS_JNI_ARGS, jlong self, jlong device, jlong queue) {
		return toMTLContext(self).create((void*)device, (void*)queue);
	}
	static jlong mtl_context_get_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLContext(self).getDevice();
	}
	static jlong mtl_context_get_queue(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLContext(self).getQueue();
	}
	static jlong mtl_context_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLContext(self).getCommand();
	}
	static jlong mtl_context_get_encoder(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLContext(self).getEncoder();
	}
	static jlong mtl_context_get_render_encoder(TS_JNI_ARGS, jlong self, jlong descriptor) {
		return (jlong)toMTLContext(self).getRenderEncoder((void*)descriptor);
	}
	static jlong mtl_context_get_compute_encoder(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLContext(self).getComputeEncoder();
	}
	static jlong mtl_context_get_tracing_encoder(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLContext(self).getTracingEncoder();
	}
	static jlong mtl_context_get_blit_encoder(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLContext(self).getBlitEncoder();
	}
	static void mtl_context_end_encoder(TS_JNI_ARGS, jlong self) {
		toMTLContext(self).endEncoder();
	}
	static const JNINativeMethod mtl_context_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_context_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_context_delete },
		{ (char*)"equal_context_ptr", (char*)"(JJ)Z", (void*)mtl_context_equal_context_ptr },
		{ (char*)"cast_context_ptr", (char*)"(J)J", (void*)mtl_context_cast_context_ptr },
		{ (char*)"base_context_ptr", (char*)"(J)J", (void*)mtl_context_base_context_ptr },
		{ (char*)"create_", (char*)"(JJJ)Z", (void*)mtl_context_create },
		{ (char*)"get_device", (char*)"(J)J", (void*)mtl_context_get_device },
		{ (char*)"get_queue", (char*)"(J)J", (void*)mtl_context_get_queue },
		{ (char*)"get_command", (char*)"(J)J", (void*)mtl_context_get_command },
		{ (char*)"get_encoder", (char*)"(J)J", (void*)mtl_context_get_encoder },
		{ (char*)"get_render_encoder", (char*)"(JJ)J", (void*)mtl_context_get_render_encoder },
		{ (char*)"get_compute_encoder", (char*)"(J)J", (void*)mtl_context_get_compute_encoder },
		{ (char*)"get_tracing_encoder", (char*)"(J)J", (void*)mtl_context_get_tracing_encoder },
		{ (char*)"get_blit_encoder", (char*)"(J)J", (void*)mtl_context_get_blit_encoder },
		{ (char*)"end_encoder", (char*)"(J)V", (void*)mtl_context_end_encoder },
	};
	
	// Tellusim::VKContext
	static jlong vk_context_new(TS_JNI_ARGS) {
		return newVKContext();
	}
	static void vk_context_delete(TS_JNI_ARGS, jlong self) {
		delete (VKContext*)self;
	}
	static jboolean vk_context_equal_context_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKContext(self).operator==(toContext(base));
	}
	static jlong vk_context_cast_context_ptr(TS_JNI_ARGS, jlong self) {
		return newVKContext(toContext(self));
	}
	static jlong vk_context_base_context_ptr(TS_JNI_ARGS, jlong self) {
		return newContext(toVKContext(self).getContext());
	}
	static jboolean vk_context_create(TS_JNI_ARGS, jlong self, jlong instance, jlong func, jlong adapter, jlong device, jint family, jint index) {
		return toVKContext(self).create((VkInstance)instance, (PFN_vkGetInstanceProcAddr)func, (VkPhysicalDevice)adapter, (VkDevice)device, (uint32_t)family, (uint32_t)index);
	}
	static jlong vk_context_get_instance(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKContext(self).getInstance();
	}
	static jlong vk_context_get_adapter(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKContext(self).getAdapter();
	}
	static jlong vk_context_get_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKContext(self).getDevice();
	}
	static jlong vk_context_get_queue(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKContext(self).getQueue();
	}
	static jlong vk_context_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKContext(self).getCommand();
	}
	static jint vk_context_get_family(TS_JNI_ARGS, jlong self) {
		return toVKContext(self).getFamily();
	}
	static jint vk_context_get_num_queues(TS_JNI_ARGS, jlong self) {
		return toVKContext(self).getNumQueues();
	}
	static jint vk_context_get_queue_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toVKContext(self).getQueueFlags((uint32_t)index);
	}
	static jint vk_context_get_queue_family(TS_JNI_ARGS, jlong self, jint index) {
		return toVKContext(self).getQueueFamily((uint32_t)index);
	}
	static void vk_context_add_context_extension(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		VKContext::addContextExtension(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void vk_context_add_adapter_extension(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		VKContext::addAdapterExtension(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void vk_context_add_adapter_features(TS_JNI_ARGS, jlong features) {
		VKContext::addAdapterFeatures((void*)features);
	}
	static jlong vk_context_get_instance_proc_address(TS_JNI_ARGS) {
		return (jlong)VKContext::getInstanceProcAddress();
	}
	static jlong vk_context_get_device_proc_address(TS_JNI_ARGS) {
		return (jlong)VKContext::getDeviceProcAddress();
	}
	static jlong vk_context_get_proc_address(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		void* ret_ = VKContext::getProcAddress(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jboolean vk_context_error(TS_JNI_ARGS, jint result) {
		return VKContext::error((uint32_t)result);
	}
	static const JNINativeMethod vk_context_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_context_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_context_delete },
		{ (char*)"equal_context_ptr", (char*)"(JJ)Z", (void*)vk_context_equal_context_ptr },
		{ (char*)"cast_context_ptr", (char*)"(J)J", (void*)vk_context_cast_context_ptr },
		{ (char*)"base_context_ptr", (char*)"(J)J", (void*)vk_context_base_context_ptr },
		{ (char*)"create_", (char*)"(JJJJJII)Z", (void*)vk_context_create },
		{ (char*)"get_instance", (char*)"(J)J", (void*)vk_context_get_instance },
		{ (char*)"get_adapter", (char*)"(J)J", (void*)vk_context_get_adapter },
		{ (char*)"get_device", (char*)"(J)J", (void*)vk_context_get_device },
		{ (char*)"get_queue", (char*)"(J)J", (void*)vk_context_get_queue },
		{ (char*)"get_command", (char*)"(J)J", (void*)vk_context_get_command },
		{ (char*)"get_family", (char*)"(J)I", (void*)vk_context_get_family },
		{ (char*)"get_num_queues", (char*)"(J)I", (void*)vk_context_get_num_queues },
		{ (char*)"get_queue_flags", (char*)"(JI)I", (void*)vk_context_get_queue_flags },
		{ (char*)"get_queue_family", (char*)"(JI)I", (void*)vk_context_get_queue_family },
		{ (char*)"add_context_extension", (char*)"(Ljava/lang/String;)V", (void*)vk_context_add_context_extension },
		{ (char*)"add_adapter_extension", (char*)"(Ljava/lang/String;)V", (void*)vk_context_add_adapter_extension },
		{ (char*)"add_adapter_features", (char*)"(J)V", (void*)vk_context_add_adapter_features },
		{ (char*)"get_instance_proc_address", (char*)"()J", (void*)vk_context_get_instance_proc_address },
		{ (char*)"get_device_proc_address", (char*)"()J", (void*)vk_context_get_device_proc_address },
		{ (char*)"get_proc_address", (char*)"(Ljava/lang/String;)J", (void*)vk_context_get_proc_address },
		{ (char*)"error_", (char*)"(I)Z", (void*)vk_context_error },
	};
	
	// Tellusim::GLContext
	static jlong gl_context_new(TS_JNI_ARGS) {
		return newGLContext();
	}
	static void gl_context_delete(TS_JNI_ARGS, jlong self) {
		delete (GLContext*)self;
	}
	static jboolean gl_context_equal_context_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLContext(self).operator==(toContext(base));
	}
	static jlong gl_context_cast_context_ptr(TS_JNI_ARGS, jlong self) {
		return newGLContext(toContext(self));
	}
	static jlong gl_context_base_context_ptr(TS_JNI_ARGS, jlong self) {
		return newContext(toGLContext(self).getContext());
	}
	static jboolean gl_context_create(TS_JNI_ARGS, jlong self, jlong context) {
		return toGLContext(self).create((void*)context);
	}
	static jlong gl_context_get_gl_display(TS_JNI_ARGS, jlong self) {
		return (jlong)toGLContext(self).getGLDisplay();
	}
	static jlong gl_context_get_gl_visual(TS_JNI_ARGS, jlong self) {
		return (jlong)toGLContext(self).getGLVisual();
	}
	static jlong gl_context_get_gl_config(TS_JNI_ARGS, jlong self) {
		return (jlong)toGLContext(self).getGLConfig();
	}
	static jlong gl_context_get_gl_surface(TS_JNI_ARGS, jlong self) {
		return (jlong)toGLContext(self).getGLSurface();
	}
	static jlong gl_context_get_gl_context(TS_JNI_ARGS, jlong self) {
		return (jlong)toGLContext(self).getGLContext();
	}
	static jlong gl_context_get_proc_address(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		void* ret_ = GLContext::getProcAddress(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jboolean gl_context_error(TS_JNI_ARGS, jint result) {
		return GLContext::error((uint32_t)result);
	}
	static jboolean gl_context_check(TS_JNI_ARGS) {
		return GLContext::check();
	}
	static const JNINativeMethod gl_context_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gl_context_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)gl_context_delete },
		{ (char*)"equal_context_ptr", (char*)"(JJ)Z", (void*)gl_context_equal_context_ptr },
		{ (char*)"cast_context_ptr", (char*)"(J)J", (void*)gl_context_cast_context_ptr },
		{ (char*)"base_context_ptr", (char*)"(J)J", (void*)gl_context_base_context_ptr },
		{ (char*)"create_", (char*)"(JJ)Z", (void*)gl_context_create },
		{ (char*)"get_gl_display", (char*)"(J)J", (void*)gl_context_get_gl_display },
		{ (char*)"get_gl_visual", (char*)"(J)J", (void*)gl_context_get_gl_visual },
		{ (char*)"get_gl_config", (char*)"(J)J", (void*)gl_context_get_gl_config },
		{ (char*)"get_gl_surface", (char*)"(J)J", (void*)gl_context_get_gl_surface },
		{ (char*)"get_gl_context", (char*)"(J)J", (void*)gl_context_get_gl_context },
		{ (char*)"get_proc_address", (char*)"(Ljava/lang/String;)J", (void*)gl_context_get_proc_address },
		{ (char*)"error_", (char*)"(I)Z", (void*)gl_context_error },
		{ (char*)"check_", (char*)"()Z", (void*)gl_context_check },
	};
	
	// Tellusim::GLESContext
	static jlong gles_context_new(TS_JNI_ARGS) {
		return newGLESContext();
	}
	static void gles_context_delete(TS_JNI_ARGS, jlong self) {
		delete (GLESContext*)self;
	}
	static jboolean gles_context_equal_context_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLESContext(self).operator==(toContext(base));
	}
	static jlong gles_context_cast_context_ptr(TS_JNI_ARGS, jlong self) {
		return newGLESContext(toContext(self));
	}
	static jlong gles_context_base_context_ptr(TS_JNI_ARGS, jlong self) {
		return newContext(toGLESContext(self).getContext());
	}
	static jboolean gles_context_create(TS_JNI_ARGS, jlong self, jlong context) {
		return toGLESContext(self).create((void*)context);
	}
	static jlong gles_context_get_gles_display(TS_JNI_ARGS, jlong self) {
		return (jlong)toGLESContext(self).getGLESDisplay();
	}
	static jlong gles_context_get_gles_config(TS_JNI_ARGS, jlong self) {
		return (jlong)toGLESContext(self).getGLESConfig();
	}
	static jlong gles_context_get_gles_context(TS_JNI_ARGS, jlong self) {
		return (jlong)toGLESContext(self).getGLESContext();
	}
	static jlong gles_context_get_proc_address(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		void* ret_ = GLESContext::getProcAddress(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jboolean gles_context_error(TS_JNI_ARGS, jint result) {
		return GLESContext::error((uint32_t)result);
	}
	static jboolean gles_context_check(TS_JNI_ARGS) {
		return GLESContext::check();
	}
	static const JNINativeMethod gles_context_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gles_context_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)gles_context_delete },
		{ (char*)"equal_context_ptr", (char*)"(JJ)Z", (void*)gles_context_equal_context_ptr },
		{ (char*)"cast_context_ptr", (char*)"(J)J", (void*)gles_context_cast_context_ptr },
		{ (char*)"base_context_ptr", (char*)"(J)J", (void*)gles_context_base_context_ptr },
		{ (char*)"create_", (char*)"(JJ)Z", (void*)gles_context_create },
		{ (char*)"get_gles_display", (char*)"(J)J", (void*)gles_context_get_gles_display },
		{ (char*)"get_gles_config", (char*)"(J)J", (void*)gles_context_get_gles_config },
		{ (char*)"get_gles_context", (char*)"(J)J", (void*)gles_context_get_gles_context },
		{ (char*)"get_proc_address", (char*)"(Ljava/lang/String;)J", (void*)gles_context_get_proc_address },
		{ (char*)"error_", (char*)"(I)Z", (void*)gles_context_error },
		{ (char*)"check_", (char*)"()Z", (void*)gles_context_check },
	};
	
	// Tellusim::WGContext
	static jlong wg_context_new(TS_JNI_ARGS) {
		return newWGContext();
	}
	static void wg_context_delete(TS_JNI_ARGS, jlong self) {
		delete (WGContext*)self;
	}
	static jboolean wg_context_equal_context_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toWGContext(self).operator==(toContext(base));
	}
	static jlong wg_context_cast_context_ptr(TS_JNI_ARGS, jlong self) {
		return newWGContext(toContext(self));
	}
	static jlong wg_context_base_context_ptr(TS_JNI_ARGS, jlong self) {
		return newContext(toWGContext(self).getContext());
	}
	static jboolean wg_context_open(TS_JNI_ARGS, jlong instance, jlong adapter, jlong device) {
		return WGContext::open((WGPUInstance)instance, (WGPUAdapter)adapter, (WGPUDevice)device);
	}
	static jboolean wg_context_create(TS_JNI_ARGS, jlong self, jlong instance, jlong adapter, jlong device) {
		return toWGContext(self).create((WGPUInstance)instance, (WGPUAdapter)adapter, (WGPUDevice)device);
	}
	static jlong wg_context_get_instance(TS_JNI_ARGS, jlong self) {
		return (jlong)toWGContext(self).getInstance();
	}
	static jlong wg_context_get_adapter(TS_JNI_ARGS, jlong self) {
		return (jlong)toWGContext(self).getAdapter();
	}
	static jlong wg_context_get_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toWGContext(self).getDevice();
	}
	static const JNINativeMethod wg_context_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)wg_context_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)wg_context_delete },
		{ (char*)"equal_context_ptr", (char*)"(JJ)Z", (void*)wg_context_equal_context_ptr },
		{ (char*)"cast_context_ptr", (char*)"(J)J", (void*)wg_context_cast_context_ptr },
		{ (char*)"base_context_ptr", (char*)"(J)J", (void*)wg_context_base_context_ptr },
		{ (char*)"open_", (char*)"(JJJ)Z", (void*)wg_context_open },
		{ (char*)"create_", (char*)"(JJJJ)Z", (void*)wg_context_create },
		{ (char*)"get_instance", (char*)"(J)J", (void*)wg_context_get_instance },
		{ (char*)"get_adapter", (char*)"(J)J", (void*)wg_context_get_adapter },
		{ (char*)"get_device", (char*)"(J)J", (void*)wg_context_get_device },
	};
	
	// Tellusim::CUContext
	static jlong cu_context_new(TS_JNI_ARGS) {
		return newCUContext();
	}
	static void cu_context_delete(TS_JNI_ARGS, jlong self) {
		delete (CUContext*)self;
	}
	static jboolean cu_context_equal_context_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCUContext(self).operator==(toContext(base));
	}
	static jlong cu_context_cast_context_ptr(TS_JNI_ARGS, jlong self) {
		return newCUContext(toContext(self));
	}
	static jlong cu_context_base_context_ptr(TS_JNI_ARGS, jlong self) {
		return newContext(toCUContext(self).getContext());
	}
	static jint cu_context_get_device(TS_JNI_ARGS, jlong self) {
		return toCUContext(self).getDevice();
	}
	static jlong cu_context_get_cu_context(TS_JNI_ARGS, jlong self) {
		return (jlong)toCUContext(self).getCUContext();
	}
	static jlong cu_context_get_stream(TS_JNI_ARGS, jlong self) {
		return (jlong)toCUContext(self).getStream();
	}
	static jlong cu_context_get_proc_address(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		void* ret_ = CUContext::getProcAddress(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jboolean cu_context_error(TS_JNI_ARGS, jint result) {
		return CUContext::error((uint32_t)result);
	}
	static const JNINativeMethod cu_context_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)cu_context_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)cu_context_delete },
		{ (char*)"equal_context_ptr", (char*)"(JJ)Z", (void*)cu_context_equal_context_ptr },
		{ (char*)"cast_context_ptr", (char*)"(J)J", (void*)cu_context_cast_context_ptr },
		{ (char*)"base_context_ptr", (char*)"(J)J", (void*)cu_context_base_context_ptr },
		{ (char*)"get_device", (char*)"(J)I", (void*)cu_context_get_device },
		{ (char*)"get_cu_context", (char*)"(J)J", (void*)cu_context_get_cu_context },
		{ (char*)"get_stream", (char*)"(J)J", (void*)cu_context_get_stream },
		{ (char*)"get_proc_address", (char*)"(Ljava/lang/String;)J", (void*)cu_context_get_proc_address },
		{ (char*)"error_", (char*)"(I)Z", (void*)cu_context_error },
	};
	
	// Tellusim::HIPContext
	static jlong hip_context_new(TS_JNI_ARGS) {
		return newHIPContext();
	}
	static void hip_context_delete(TS_JNI_ARGS, jlong self) {
		delete (HIPContext*)self;
	}
	static jboolean hip_context_equal_context_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toHIPContext(self).operator==(toContext(base));
	}
	static jlong hip_context_cast_context_ptr(TS_JNI_ARGS, jlong self) {
		return newHIPContext(toContext(self));
	}
	static jlong hip_context_base_context_ptr(TS_JNI_ARGS, jlong self) {
		return newContext(toHIPContext(self).getContext());
	}
	static jint hip_context_get_device(TS_JNI_ARGS, jlong self) {
		return toHIPContext(self).getDevice();
	}
	static jlong hip_context_get_hip_context(TS_JNI_ARGS, jlong self) {
		return (jlong)toHIPContext(self).getHIPContext();
	}
	static jlong hip_context_get_stream(TS_JNI_ARGS, jlong self) {
		return (jlong)toHIPContext(self).getStream();
	}
	static jlong hip_context_get_proc_address(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		void* ret_ = HIPContext::getProcAddress(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jboolean hip_context_error(TS_JNI_ARGS, jint result) {
		return HIPContext::error((uint32_t)result);
	}
	static const JNINativeMethod hip_context_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)hip_context_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)hip_context_delete },
		{ (char*)"equal_context_ptr", (char*)"(JJ)Z", (void*)hip_context_equal_context_ptr },
		{ (char*)"cast_context_ptr", (char*)"(J)J", (void*)hip_context_cast_context_ptr },
		{ (char*)"base_context_ptr", (char*)"(J)J", (void*)hip_context_base_context_ptr },
		{ (char*)"get_device", (char*)"(J)I", (void*)hip_context_get_device },
		{ (char*)"get_hip_context", (char*)"(J)J", (void*)hip_context_get_hip_context },
		{ (char*)"get_stream", (char*)"(J)J", (void*)hip_context_get_stream },
		{ (char*)"get_proc_address", (char*)"(Ljava/lang/String;)J", (void*)hip_context_get_proc_address },
		{ (char*)"error_", (char*)"(I)Z", (void*)hip_context_error },
	};
	
	// Tellusim::Query::Statistics
	static jlong query_statistics_new(TS_JNI_ARGS) {
		return newQueryStatistics();
	}
	static jlong query_statistics_copy(TS_JNI_ARGS, jlong self) {
		return newQueryStatistics(toQueryStatistics(self));
	}
	static void query_statistics_delete(TS_JNI_ARGS, jlong self) {
		delete (Query::Statistics*)self;
	}
	static void query_statistics_set_num_vertices(TS_JNI_ARGS, jlong self, jlong num_vertices) {
		toQueryStatistics(self).num_vertices = num_vertices;
	}
	static jlong query_statistics_get_num_vertices(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).num_vertices;
	}
	static void query_statistics_set_num_primitives(TS_JNI_ARGS, jlong self, jlong num_primitives) {
		toQueryStatistics(self).num_primitives = num_primitives;
	}
	static jlong query_statistics_get_num_primitives(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).num_primitives;
	}
	static void query_statistics_set_vertex_invocations(TS_JNI_ARGS, jlong self, jlong vertex_invocations) {
		toQueryStatistics(self).vertex_invocations = vertex_invocations;
	}
	static jlong query_statistics_get_vertex_invocations(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).vertex_invocations;
	}
	static void query_statistics_set_control_invocations(TS_JNI_ARGS, jlong self, jlong control_invocations) {
		toQueryStatistics(self).control_invocations = control_invocations;
	}
	static jlong query_statistics_get_control_invocations(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).control_invocations;
	}
	static void query_statistics_set_evaluate_invocations(TS_JNI_ARGS, jlong self, jlong evaluate_invocations) {
		toQueryStatistics(self).evaluate_invocations = evaluate_invocations;
	}
	static jlong query_statistics_get_evaluate_invocations(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).evaluate_invocations;
	}
	static void query_statistics_set_geometry_invocations(TS_JNI_ARGS, jlong self, jlong geometry_invocations) {
		toQueryStatistics(self).geometry_invocations = geometry_invocations;
	}
	static jlong query_statistics_get_geometry_invocations(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).geometry_invocations;
	}
	static void query_statistics_set_geometry_primitives(TS_JNI_ARGS, jlong self, jlong geometry_primitives) {
		toQueryStatistics(self).geometry_primitives = geometry_primitives;
	}
	static jlong query_statistics_get_geometry_primitives(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).geometry_primitives;
	}
	static void query_statistics_set_fragment_invocations(TS_JNI_ARGS, jlong self, jlong fragment_invocations) {
		toQueryStatistics(self).fragment_invocations = fragment_invocations;
	}
	static jlong query_statistics_get_fragment_invocations(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).fragment_invocations;
	}
	static void query_statistics_set_compute_invocations(TS_JNI_ARGS, jlong self, jlong compute_invocations) {
		toQueryStatistics(self).compute_invocations = compute_invocations;
	}
	static jlong query_statistics_get_compute_invocations(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).compute_invocations;
	}
	static void query_statistics_set_clipping_invocations(TS_JNI_ARGS, jlong self, jlong clipping_invocations) {
		toQueryStatistics(self).clipping_invocations = clipping_invocations;
	}
	static jlong query_statistics_get_clipping_invocations(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).clipping_invocations;
	}
	static void query_statistics_set_clipping_primitives(TS_JNI_ARGS, jlong self, jlong clipping_primitives) {
		toQueryStatistics(self).clipping_primitives = clipping_primitives;
	}
	static jlong query_statistics_get_clipping_primitives(TS_JNI_ARGS, jlong self) {
		return toQueryStatistics(self).clipping_primitives;
	}
	static const JNINativeMethod query_statistics_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)query_statistics_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)query_statistics_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)query_statistics_delete },
		{ (char*)"set_num_vertices_", (char*)"(JJ)V", (void*)query_statistics_set_num_vertices },
		{ (char*)"get_num_vertices_", (char*)"(J)J", (void*)query_statistics_get_num_vertices },
		{ (char*)"set_num_primitives_", (char*)"(JJ)V", (void*)query_statistics_set_num_primitives },
		{ (char*)"get_num_primitives_", (char*)"(J)J", (void*)query_statistics_get_num_primitives },
		{ (char*)"set_vertex_invocations_", (char*)"(JJ)V", (void*)query_statistics_set_vertex_invocations },
		{ (char*)"get_vertex_invocations_", (char*)"(J)J", (void*)query_statistics_get_vertex_invocations },
		{ (char*)"set_control_invocations_", (char*)"(JJ)V", (void*)query_statistics_set_control_invocations },
		{ (char*)"get_control_invocations_", (char*)"(J)J", (void*)query_statistics_get_control_invocations },
		{ (char*)"set_evaluate_invocations_", (char*)"(JJ)V", (void*)query_statistics_set_evaluate_invocations },
		{ (char*)"get_evaluate_invocations_", (char*)"(J)J", (void*)query_statistics_get_evaluate_invocations },
		{ (char*)"set_geometry_invocations_", (char*)"(JJ)V", (void*)query_statistics_set_geometry_invocations },
		{ (char*)"get_geometry_invocations_", (char*)"(J)J", (void*)query_statistics_get_geometry_invocations },
		{ (char*)"set_geometry_primitives_", (char*)"(JJ)V", (void*)query_statistics_set_geometry_primitives },
		{ (char*)"get_geometry_primitives_", (char*)"(J)J", (void*)query_statistics_get_geometry_primitives },
		{ (char*)"set_fragment_invocations_", (char*)"(JJ)V", (void*)query_statistics_set_fragment_invocations },
		{ (char*)"get_fragment_invocations_", (char*)"(J)J", (void*)query_statistics_get_fragment_invocations },
		{ (char*)"set_compute_invocations_", (char*)"(JJ)V", (void*)query_statistics_set_compute_invocations },
		{ (char*)"get_compute_invocations_", (char*)"(J)J", (void*)query_statistics_get_compute_invocations },
		{ (char*)"set_clipping_invocations_", (char*)"(JJ)V", (void*)query_statistics_set_clipping_invocations },
		{ (char*)"get_clipping_invocations_", (char*)"(J)J", (void*)query_statistics_get_clipping_invocations },
		{ (char*)"set_clipping_primitives_", (char*)"(JJ)V", (void*)query_statistics_set_clipping_primitives },
		{ (char*)"get_clipping_primitives_", (char*)"(J)J", (void*)query_statistics_get_clipping_primitives },
	};
	// Tellusim::Query
	static jlong query_new(TS_JNI_ARGS) {
		return newQuery();
	}
	static void query_delete(TS_JNI_ARGS, jlong self) {
		delete (Query*)self;
	}
	static jboolean query_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toQuery(self) == toQuery(ptr));
	}
	static jlong query_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newQuery(toQuery(self).clonePtr());
	}
	static void query_clear_ptr(TS_JNI_ARGS, jlong self) {
		toQuery(self).clearPtr();
	}
	static void query_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toQuery(self).destroyPtr();
	}
	static void query_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toQuery(self).acquirePtr();
	}
	static void query_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toQuery(self).unacquirePtr();
	}
	static jboolean query_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isValidPtr();
	}
	static jboolean query_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isOwnerPtr();
	}
	static jboolean query_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isConstPtr();
	}
	static jint query_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toQuery(self).getCountPtr();
	}
	static jlong query_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toQuery(self).getInternalPtr();
	}
	static jint query_get_platform(TS_JNI_ARGS, jlong self) {
		return toQuery(self).getPlatform();
	}
	static jstring query_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toQuery(self).getPlatformName());
	}
	static jint query_get_index(TS_JNI_ARGS, jlong self) {
		return toQuery(self).getIndex();
	}
	static void query_clear(TS_JNI_ARGS, jlong self) {
		toQuery(self).clear();
	}
	static jboolean query_is_created(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isCreated();
	}
	static jboolean query_is_available(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isAvailable();
	}
	static jboolean query_is_began(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isBegan();
	}
	static jboolean query_is_ended(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isEnded();
	}
	static jboolean query_create(TS_JNI_ARGS, jlong self, jint type) {
		return toQuery(self).create((Query::Type)type);
	}
	static jint query_get_type(TS_JNI_ARGS, jlong self) {
		return toQuery(self).getType();
	}
	static jstring query_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(Query::getTypeName((Query::Type)type));
	}
	static jstring query_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toQuery(self).getTypeName());
	}
	static jlong query_get_type_size(TS_JNI_ARGS, jlong self) {
		return (jlong)toQuery(self).getTypeSize();
	}
	static jboolean query_is_time(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isTime();
	}
	static jboolean query_is_clock(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isClock();
	}
	static jboolean query_is_samples(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isSamples();
	}
	static jboolean query_is_samples1(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isSamples1();
	}
	static jboolean query_is_statistics(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isStatistics();
	}
	static jboolean query_is_time_type(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isTimeType();
	}
	static jboolean query_is_samples_type(TS_JNI_ARGS, jlong self) {
		return toQuery(self).isSamplesType();
	}
	static jboolean query_get(TS_JNI_ARGS, jlong self, jbyteArray dest, jboolean wait) {
		return toQuery(self).get(ByteArray(env, dest).get(), env->GetArrayLength(dest), (bool)wait);
	}
	static jlong query_get_time(TS_JNI_ARGS, jlong self, jboolean wait, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		uint64_t ret_ = toQuery(self).getTime((bool)wait, status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return (jlong)ret_;
	}
	static jint query_get_samples(TS_JNI_ARGS, jlong self, jboolean wait, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		uint32_t ret_ = toQuery(self).getSamples((bool)wait, status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return ret_;
	}
	static jlong query_get_statistics(TS_JNI_ARGS, jlong self, jboolean wait, jbooleanArray status) {
		bool *status_ = (status) ? (bool*)env->GetBooleanArrayElements(status, nullptr) : nullptr;
		Query::Statistics ret_ = toQuery(self).getStatistics((bool)wait, status_);
		if(status) env->ReleaseBooleanArrayElements(status, (jboolean*)status_, 0);
		return newQueryStatistics(ret_);
	}
	static const JNINativeMethod query_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)query_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)query_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)query_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)query_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)query_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)query_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)query_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)query_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)query_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)query_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)query_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)query_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)query_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)query_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)query_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)query_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)query_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)query_is_created },
		{ (char*)"is_available", (char*)"(J)Z", (void*)query_is_available },
		{ (char*)"is_began", (char*)"(J)Z", (void*)query_is_began },
		{ (char*)"is_ended", (char*)"(J)Z", (void*)query_is_ended },
		{ (char*)"create_", (char*)"(JI)Z", (void*)query_create },
		{ (char*)"get_type", (char*)"(J)I", (void*)query_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)query_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)query_get_type_name_1 },
		{ (char*)"get_type_size", (char*)"(J)J", (void*)query_get_type_size },
		{ (char*)"is_time", (char*)"(J)Z", (void*)query_is_time },
		{ (char*)"is_clock", (char*)"(J)Z", (void*)query_is_clock },
		{ (char*)"is_samples", (char*)"(J)Z", (void*)query_is_samples },
		{ (char*)"is_samples1", (char*)"(J)Z", (void*)query_is_samples1 },
		{ (char*)"is_statistics", (char*)"(J)Z", (void*)query_is_statistics },
		{ (char*)"is_time_type", (char*)"(J)Z", (void*)query_is_time_type },
		{ (char*)"is_samples_type", (char*)"(J)Z", (void*)query_is_samples_type },
		{ (char*)"get_", (char*)"(J[BZ)Z", (void*)query_get },
		{ (char*)"get_time", (char*)"(JZ[Z)J", (void*)query_get_time },
		{ (char*)"get_samples", (char*)"(JZ[Z)I", (void*)query_get_samples },
		{ (char*)"get_statistics", (char*)"(JZ[Z)J", (void*)query_get_statistics },
	};
	
	// Tellusim::FUQuery
	static jlong fu_query_new(TS_JNI_ARGS) {
		return newFUQuery();
	}
	static jlong fu_query_new_1(TS_JNI_ARGS, jlongArray queries, jboolean owner) {
		Array<Query> queries_((uint32_t)env->GetArrayLength(queries));
		jlong *queries__ = env->GetLongArrayElements(queries, nullptr);
		for(uint32_t i = 0; i < queries_.size(); i++) queries_[i] = toQuery(queries__[i]);
		jlong ret_ = newFUQuery(queries_, (bool)owner);
		if(queries__) env->ReleaseLongArrayElements(queries, queries__, 0);
		return ret_;
	}
	static void fu_query_delete(TS_JNI_ARGS, jlong self) {
		delete (FUQuery*)self;
	}
	static jboolean fu_query_equal_query_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUQuery(self).operator==(toQuery(base));
	}
	static jlong fu_query_cast_query_ptr(TS_JNI_ARGS, jlong self) {
		return newFUQuery(toQuery(self));
	}
	static jlong fu_query_base_query_ptr(TS_JNI_ARGS, jlong self) {
		return newQuery(toFUQuery(self).getQuery());
	}
	static void fu_query_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUQuery(self).setMask((uint32_t)mask);
	}
	static jint fu_query_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUQuery(self).getMask();
	}
	static jint fu_query_get_num_queries(TS_JNI_ARGS, jlong self) {
		return toFUQuery(self).getNumQueries();
	}
	static jlong fu_query_get_query(TS_JNI_ARGS, jlong self, jint index) {
		return newQuery(toFUQuery(self).getQuery((uint32_t)index));
	}
	static jlong fu_query_get_query_1(TS_JNI_ARGS, jlong self, jint index) {
		return newQuery(toFUQuery(self).getQuery((uint32_t)index));
	}
	static const JNINativeMethod fu_query_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_query_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_query_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_query_delete },
		{ (char*)"equal_query_ptr", (char*)"(JJ)Z", (void*)fu_query_equal_query_ptr },
		{ (char*)"cast_query_ptr", (char*)"(J)J", (void*)fu_query_cast_query_ptr },
		{ (char*)"base_query_ptr", (char*)"(J)J", (void*)fu_query_base_query_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_query_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_query_get_mask },
		{ (char*)"get_num_queries", (char*)"(J)I", (void*)fu_query_get_num_queries },
		{ (char*)"get_query", (char*)"(JI)J", (void*)fu_query_get_query },
		{ (char*)"get_query_1", (char*)"(JI)J", (void*)fu_query_get_query_1 },
	};
	
	// Tellusim::Fence
	static jlong fence_new(TS_JNI_ARGS) {
		return newFence();
	}
	static void fence_delete(TS_JNI_ARGS, jlong self) {
		delete (Fence*)self;
	}
	static jboolean fence_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toFence(self) == toFence(ptr));
	}
	static jlong fence_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newFence(toFence(self).clonePtr());
	}
	static void fence_clear_ptr(TS_JNI_ARGS, jlong self) {
		toFence(self).clearPtr();
	}
	static void fence_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toFence(self).destroyPtr();
	}
	static void fence_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toFence(self).acquirePtr();
	}
	static void fence_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toFence(self).unacquirePtr();
	}
	static jboolean fence_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toFence(self).isValidPtr();
	}
	static jboolean fence_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toFence(self).isOwnerPtr();
	}
	static jboolean fence_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toFence(self).isConstPtr();
	}
	static jint fence_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toFence(self).getCountPtr();
	}
	static jlong fence_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toFence(self).getInternalPtr();
	}
	static jint fence_get_platform(TS_JNI_ARGS, jlong self) {
		return toFence(self).getPlatform();
	}
	static jstring fence_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toFence(self).getPlatformName());
	}
	static jint fence_get_index(TS_JNI_ARGS, jlong self) {
		return toFence(self).getIndex();
	}
	static void fence_clear(TS_JNI_ARGS, jlong self) {
		toFence(self).clear();
	}
	static jboolean fence_is_created(TS_JNI_ARGS, jlong self) {
		return toFence(self).isCreated();
	}
	static jboolean fence_create(TS_JNI_ARGS, jlong self, jint flags) {
		return toFence(self).create((Fence::Flags)flags);
	}
	static jint fence_get_flags(TS_JNI_ARGS, jlong self) {
		return toFence(self).getFlags();
	}
	static jboolean fence_has_flag(TS_JNI_ARGS, jlong self, jint flags) {
		return toFence(self).hasFlag((Fence::Flags)flags);
	}
	static jboolean fence_has_flags(TS_JNI_ARGS, jlong self, jint flags) {
		return toFence(self).hasFlags((Fence::Flags)flags);
	}
	static jstring fence_get_flags_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toFence(self).getFlagsName().get());
	}
	static jstring fence_get_description(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toFence(self).getDescription().get());
	}
	static const JNINativeMethod fence_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fence_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)fence_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)fence_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)fence_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)fence_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)fence_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)fence_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)fence_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)fence_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)fence_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)fence_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)fence_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)fence_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)fence_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)fence_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)fence_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)fence_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)fence_is_created },
		{ (char*)"create_", (char*)"(JI)Z", (void*)fence_create },
		{ (char*)"get_flags", (char*)"(J)I", (void*)fence_get_flags },
		{ (char*)"has_flag", (char*)"(JI)Z", (void*)fence_has_flag },
		{ (char*)"has_flags", (char*)"(JI)Z", (void*)fence_has_flags },
		{ (char*)"get_flags_name", (char*)"(J)Ljava/lang/String;", (void*)fence_get_flags_name },
		{ (char*)"get_description", (char*)"(J)Ljava/lang/String;", (void*)fence_get_description },
	};
	
	// Tellusim::VKFence
	static jlong vk_fence_new(TS_JNI_ARGS) {
		return newVKFence();
	}
	static void vk_fence_delete(TS_JNI_ARGS, jlong self) {
		delete (VKFence*)self;
	}
	static jboolean vk_fence_equal_fence_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKFence(self).operator==(toFence(base));
	}
	static jlong vk_fence_cast_fence_ptr(TS_JNI_ARGS, jlong self) {
		return newVKFence(toFence(self));
	}
	static jlong vk_fence_base_fence_ptr(TS_JNI_ARGS, jlong self) {
		return newFence(toVKFence(self).getFence());
	}
	static jlong vk_fence_get_vk_fence(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKFence(self).getVKFence();
	}
	static jlong vk_fence_get_semaphore(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKFence(self).getSemaphore();
	}
	static jlong vk_fence_get_shared_handle(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKFence(self).getSharedHandle();
	}
	static const JNINativeMethod vk_fence_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_fence_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_fence_delete },
		{ (char*)"equal_fence_ptr", (char*)"(JJ)Z", (void*)vk_fence_equal_fence_ptr },
		{ (char*)"cast_fence_ptr", (char*)"(J)J", (void*)vk_fence_cast_fence_ptr },
		{ (char*)"base_fence_ptr", (char*)"(J)J", (void*)vk_fence_base_fence_ptr },
		{ (char*)"get_vk_fence", (char*)"(J)J", (void*)vk_fence_get_vk_fence },
		{ (char*)"get_semaphore", (char*)"(J)J", (void*)vk_fence_get_semaphore },
		{ (char*)"get_shared_handle", (char*)"(J)J", (void*)vk_fence_get_shared_handle },
	};
	
	// Tellusim::FUFence
	static jlong fu_fence_new(TS_JNI_ARGS) {
		return newFUFence();
	}
	static jlong fu_fence_new_1(TS_JNI_ARGS, jlongArray fences, jboolean owner) {
		Array<Fence> fences_((uint32_t)env->GetArrayLength(fences));
		jlong *fences__ = env->GetLongArrayElements(fences, nullptr);
		for(uint32_t i = 0; i < fences_.size(); i++) fences_[i] = toFence(fences__[i]);
		jlong ret_ = newFUFence(fences_, (bool)owner);
		if(fences__) env->ReleaseLongArrayElements(fences, fences__, 0);
		return ret_;
	}
	static void fu_fence_delete(TS_JNI_ARGS, jlong self) {
		delete (FUFence*)self;
	}
	static jboolean fu_fence_equal_fence_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUFence(self).operator==(toFence(base));
	}
	static jlong fu_fence_cast_fence_ptr(TS_JNI_ARGS, jlong self) {
		return newFUFence(toFence(self));
	}
	static jlong fu_fence_base_fence_ptr(TS_JNI_ARGS, jlong self) {
		return newFence(toFUFence(self).getFence());
	}
	static void fu_fence_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUFence(self).setMask((uint32_t)mask);
	}
	static jint fu_fence_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUFence(self).getMask();
	}
	static jint fu_fence_get_num_fences(TS_JNI_ARGS, jlong self) {
		return toFUFence(self).getNumFences();
	}
	static jlong fu_fence_get_fence(TS_JNI_ARGS, jlong self, jint index) {
		return newFence(toFUFence(self).getFence((uint32_t)index));
	}
	static jlong fu_fence_get_fence_1(TS_JNI_ARGS, jlong self, jint index) {
		return newFence(toFUFence(self).getFence((uint32_t)index));
	}
	static const JNINativeMethod fu_fence_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_fence_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_fence_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_fence_delete },
		{ (char*)"equal_fence_ptr", (char*)"(JJ)Z", (void*)fu_fence_equal_fence_ptr },
		{ (char*)"cast_fence_ptr", (char*)"(J)J", (void*)fu_fence_cast_fence_ptr },
		{ (char*)"base_fence_ptr", (char*)"(J)J", (void*)fu_fence_base_fence_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_fence_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_fence_get_mask },
		{ (char*)"get_num_fences", (char*)"(J)I", (void*)fu_fence_get_num_fences },
		{ (char*)"get_fence", (char*)"(JI)J", (void*)fu_fence_get_fence },
		{ (char*)"get_fence_1", (char*)"(JI)J", (void*)fu_fence_get_fence_1 },
	};
	
	// Tellusim::Shader
	static jlong shader_new(TS_JNI_ARGS) {
		return newShader();
	}
	static void shader_delete(TS_JNI_ARGS, jlong self) {
		delete (Shader*)self;
	}
	static jboolean shader_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toShader(self) == toShader(ptr));
	}
	static jlong shader_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toShader(self).clonePtr());
	}
	static void shader_clear_ptr(TS_JNI_ARGS, jlong self) {
		toShader(self).clearPtr();
	}
	static void shader_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toShader(self).destroyPtr();
	}
	static void shader_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toShader(self).acquirePtr();
	}
	static void shader_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toShader(self).unacquirePtr();
	}
	static jboolean shader_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toShader(self).isValidPtr();
	}
	static jboolean shader_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toShader(self).isOwnerPtr();
	}
	static jboolean shader_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toShader(self).isConstPtr();
	}
	static jint shader_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toShader(self).getCountPtr();
	}
	static jlong shader_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toShader(self).getInternalPtr();
	}
	static jint shader_get_platform(TS_JNI_ARGS, jlong self) {
		return toShader(self).getPlatform();
	}
	static jstring shader_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toShader(self).getPlatformName());
	}
	static jint shader_get_index(TS_JNI_ARGS, jlong self) {
		return toShader(self).getIndex();
	}
	static void shader_clear(TS_JNI_ARGS, jlong self) {
		toShader(self).clear();
	}
	static jboolean shader_is_created(TS_JNI_ARGS, jlong self) {
		return toShader(self).isCreated();
	}
	static jboolean shader_save_state(TS_JNI_ARGS, jlong self, jlong stream) {
		return toShader(self).saveState(toStream(stream));
	}
	static jint shader_get_type(TS_JNI_ARGS, jlong self) {
		return toShader(self).getType();
	}
	static jstring shader_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(Shader::getTypeName((Shader::Type)type));
	}
	static jstring shader_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toShader(self).getTypeName());
	}
	static jboolean shader_is_vertex(TS_JNI_ARGS, jlong self) {
		return toShader(self).isVertex();
	}
	static jboolean shader_is_control(TS_JNI_ARGS, jlong self) {
		return toShader(self).isControl();
	}
	static jboolean shader_is_evaluate(TS_JNI_ARGS, jlong self) {
		return toShader(self).isEvaluate();
	}
	static jboolean shader_is_geometry(TS_JNI_ARGS, jlong self) {
		return toShader(self).isGeometry();
	}
	static jboolean shader_is_fragment(TS_JNI_ARGS, jlong self) {
		return toShader(self).isFragment();
	}
	static jboolean shader_is_compute(TS_JNI_ARGS, jlong self) {
		return toShader(self).isCompute();
	}
	static jboolean shader_is_task(TS_JNI_ARGS, jlong self) {
		return toShader(self).isTask();
	}
	static jboolean shader_is_mesh(TS_JNI_ARGS, jlong self) {
		return toShader(self).isMesh();
	}
	static jboolean shader_is_ray_gen(TS_JNI_ARGS, jlong self) {
		return toShader(self).isRayGen();
	}
	static jboolean shader_is_ray_miss(TS_JNI_ARGS, jlong self) {
		return toShader(self).isRayMiss();
	}
	static jboolean shader_is_closest(TS_JNI_ARGS, jlong self) {
		return toShader(self).isClosest();
	}
	static jboolean shader_is_first_hit(TS_JNI_ARGS, jlong self) {
		return toShader(self).isFirstHit();
	}
	static jboolean shader_is_intersection(TS_JNI_ARGS, jlong self) {
		return toShader(self).isIntersection();
	}
	static jboolean shader_is_callable(TS_JNI_ARGS, jlong self) {
		return toShader(self).isCallable();
	}
	static jboolean shader_is_graphics_type(TS_JNI_ARGS, jlong self) {
		return toShader(self).isGraphicsType();
	}
	static jboolean shader_is_tessellation_type(TS_JNI_ARGS, jlong self) {
		return toShader(self).isTessellationType();
	}
	static jboolean shader_is_tracing_type(TS_JNI_ARGS, jlong self) {
		return toShader(self).isTracingType();
	}
	static jboolean shader_is_mesh_type(TS_JNI_ARGS, jlong self) {
		return toShader(self).isMeshType();
	}
	static jstring shader_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toShader(self).getName().get());
	}
	static jstring shader_get_macros(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toShader(self).getMacros().get());
	}
	static void shader_set_sampler_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toShader(self).setSamplerOffset(offset);
	}
	static jint shader_get_sampler_offset(TS_JNI_ARGS, jlong self) {
		return toShader(self).getSamplerOffset();
	}
	static void shader_set_texture_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toShader(self).setTextureOffset(offset);
	}
	static jint shader_get_texture_offset(TS_JNI_ARGS, jlong self) {
		return toShader(self).getTextureOffset();
	}
	static void shader_set_surface_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toShader(self).setSurfaceOffset(offset);
	}
	static jint shader_get_surface_offset(TS_JNI_ARGS, jlong self) {
		return toShader(self).getSurfaceOffset();
	}
	static void shader_set_uniform_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toShader(self).setUniformOffset(offset);
	}
	static jint shader_get_uniform_offset(TS_JNI_ARGS, jlong self) {
		return toShader(self).getUniformOffset();
	}
	static void shader_set_storage_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toShader(self).setStorageOffset(offset);
	}
	static jint shader_get_storage_offset(TS_JNI_ARGS, jlong self) {
		return toShader(self).getStorageOffset();
	}
	static void shader_set_tracing_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toShader(self).setTracingOffset(offset);
	}
	static jint shader_get_tracing_offset(TS_JNI_ARGS, jlong self) {
		return toShader(self).getTracingOffset();
	}
	static void shader_set_texel_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toShader(self).setTexelOffset(offset);
	}
	static jint shader_get_texel_offset(TS_JNI_ARGS, jlong self) {
		return toShader(self).getTexelOffset();
	}
	static void shader_set_table_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toShader(self).setTableOffset(offset);
	}
	static jint shader_get_table_offset(TS_JNI_ARGS, jlong self) {
		return toShader(self).getTableOffset();
	}
	static void shader_set_patch_size(TS_JNI_ARGS, jlong self, jint size) {
		toShader(self).setPatchSize((uint32_t)size);
	}
	static jint shader_get_patch_size(TS_JNI_ARGS, jlong self) {
		return toShader(self).getPatchSize();
	}
	static void shader_set_input_size(TS_JNI_ARGS, jlong self, jint size) {
		toShader(self).setInputSize((uint32_t)size);
	}
	static jint shader_get_input_size(TS_JNI_ARGS, jlong self) {
		return toShader(self).getInputSize();
	}
	static void shader_set_output_size(TS_JNI_ARGS, jlong self, jint size) {
		toShader(self).setOutputSize((uint32_t)size);
	}
	static jint shader_get_output_size(TS_JNI_ARGS, jlong self) {
		return toShader(self).getOutputSize();
	}
	static jboolean shader_load(TS_JNI_ARGS, jlong self, jint type, jstring name, jstring format) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toShader(self).load((Shader::Type)type, name_, "%s", format_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean shader_create(TS_JNI_ARGS, jlong self, jint type, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toShader(self).create((Shader::Type)type, src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean shader_load_1(TS_JNI_ARGS, jlong self, jint type, jstring name, jlong macros, jstringArray includes, jint size) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toShader(self).load((Shader::Type)type, name_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(name, name_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean shader_create_1(TS_JNI_ARGS, jlong self, jint type, jstring src, jlong macros, jstringArray includes, jint size) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toShader(self).create((Shader::Type)type, src_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(src, src_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean shader_load_glsl(TS_JNI_ARGS, jlong self, jint type, jstring name, jstring format) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toShader(self).loadGLSL((Shader::Type)type, name_, "%s", format_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean shader_create_glsl(TS_JNI_ARGS, jlong self, jint type, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toShader(self).createGLSL((Shader::Type)type, src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean shader_load_glsl_1(TS_JNI_ARGS, jlong self, jint type, jstring name, jlong macros, jstringArray includes, jint size) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toShader(self).loadGLSL((Shader::Type)type, name_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(name, name_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean shader_create_glsl_1(TS_JNI_ARGS, jlong self, jint type, jstring src, jlong macros, jstringArray includes, jint size) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toShader(self).createGLSL((Shader::Type)type, src_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(src, src_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean shader_load_spirv(TS_JNI_ARGS, jlong self, jint type, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toShader(self).loadSPIRV((Shader::Type)type, name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean shader_create_spirv(TS_JNI_ARGS, jlong self, jint type, jintArray data) {
		uint32_t *data__ = (uint32_t*)env->GetIntArrayElements(data, nullptr);
		Array<uint32_t> data_((uint32_t)env->GetArrayLength(data), data__);
		bool ret_ = toShader(self).createSPIRV((Shader::Type)type, data_);
		if(data_) env->ReleaseIntArrayElements(data, (jint*)data__, 0);
		return ret_;
	}
	static jboolean shader_has_cache(TS_JNI_ARGS) {
		return Shader::hasCache();
	}
	static jboolean shader_set_cache(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Shader::setCache(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean shader_load_cache(TS_JNI_ARGS, jlong hash, jlong stream) {
		return Shader::loadCache(toString(hash), toStream(stream));
	}
	static jboolean shader_save_cache(TS_JNI_ARGS, jlong hash, jlong stream) {
		return Shader::saveCache(toString(hash), toStream(stream));
	}
	static void shader_clear_cache(TS_JNI_ARGS) {
		Shader::clearCache();
	}
	static jboolean shader_is_macro(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Shader::isMacro(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean shader_set_macro(TS_JNI_ARGS, jstring name, jint value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Shader::setMacro(name_, value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean shader_set_macro_1(TS_JNI_ARGS, jstring name, jint value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Shader::setMacro(name_, (uint32_t)value);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean shader_set_macro_2(TS_JNI_ARGS, jstring name, jstring value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *value_ = (value) ? env->GetStringUTFChars(value, nullptr) : nullptr;
		bool ret_ = Shader::setMacro(name_, value_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(value, value_);
		return ret_;
	}
	static jboolean shader_set_macros(TS_JNI_ARGS, jstring macros) {
		const char *macros_ = (macros) ? env->GetStringUTFChars(macros, nullptr) : nullptr;
		bool ret_ = Shader::setMacros(macros_);
		env->ReleaseStringUTFChars(macros, macros_);
		return ret_;
	}
	static jboolean shader_remove_macro(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Shader::removeMacro(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void shader_clear_macros(TS_JNI_ARGS) {
		Shader::clearMacros();
	}
	static jboolean shader_is_include(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Shader::isInclude(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean shader_set_include(TS_JNI_ARGS, jstring name, jlong src) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Shader::setInclude(name_, toString(src));
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean shader_remove_include(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = Shader::removeInclude(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void shader_clear_includes(TS_JNI_ARGS) {
		Shader::clearIncludes();
	}
	static jstring shader_preprocessor(TS_JNI_ARGS, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		String ret_ = Shader::preprocessor(src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return env->NewStringUTF(ret_.get());
	}
	static jstring shader_preprocessor_1(TS_JNI_ARGS, jstring src, jlong macros, jstringArray includes, jint size) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		String ret_ = Shader::preprocessor(src_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(src, src_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return env->NewStringUTF(ret_.get());
	}
	static const JNINativeMethod shader_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)shader_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)shader_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)shader_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)shader_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)shader_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)shader_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)shader_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)shader_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)shader_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)shader_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)shader_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)shader_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)shader_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)shader_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)shader_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)shader_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)shader_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)shader_is_created },
		{ (char*)"save_state", (char*)"(JJ)Z", (void*)shader_save_state },
		{ (char*)"get_type", (char*)"(J)I", (void*)shader_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)shader_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)shader_get_type_name_1 },
		{ (char*)"is_vertex", (char*)"(J)Z", (void*)shader_is_vertex },
		{ (char*)"is_control", (char*)"(J)Z", (void*)shader_is_control },
		{ (char*)"is_evaluate", (char*)"(J)Z", (void*)shader_is_evaluate },
		{ (char*)"is_geometry", (char*)"(J)Z", (void*)shader_is_geometry },
		{ (char*)"is_fragment", (char*)"(J)Z", (void*)shader_is_fragment },
		{ (char*)"is_compute", (char*)"(J)Z", (void*)shader_is_compute },
		{ (char*)"is_task", (char*)"(J)Z", (void*)shader_is_task },
		{ (char*)"is_mesh", (char*)"(J)Z", (void*)shader_is_mesh },
		{ (char*)"is_ray_gen", (char*)"(J)Z", (void*)shader_is_ray_gen },
		{ (char*)"is_ray_miss", (char*)"(J)Z", (void*)shader_is_ray_miss },
		{ (char*)"is_closest", (char*)"(J)Z", (void*)shader_is_closest },
		{ (char*)"is_first_hit", (char*)"(J)Z", (void*)shader_is_first_hit },
		{ (char*)"is_intersection", (char*)"(J)Z", (void*)shader_is_intersection },
		{ (char*)"is_callable", (char*)"(J)Z", (void*)shader_is_callable },
		{ (char*)"is_graphics_type", (char*)"(J)Z", (void*)shader_is_graphics_type },
		{ (char*)"is_tessellation_type", (char*)"(J)Z", (void*)shader_is_tessellation_type },
		{ (char*)"is_tracing_type", (char*)"(J)Z", (void*)shader_is_tracing_type },
		{ (char*)"is_mesh_type", (char*)"(J)Z", (void*)shader_is_mesh_type },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)shader_get_name },
		{ (char*)"get_macros", (char*)"(J)Ljava/lang/String;", (void*)shader_get_macros },
		{ (char*)"set_sampler_offset", (char*)"(JI)V", (void*)shader_set_sampler_offset },
		{ (char*)"get_sampler_offset", (char*)"(J)I", (void*)shader_get_sampler_offset },
		{ (char*)"set_texture_offset", (char*)"(JI)V", (void*)shader_set_texture_offset },
		{ (char*)"get_texture_offset", (char*)"(J)I", (void*)shader_get_texture_offset },
		{ (char*)"set_surface_offset", (char*)"(JI)V", (void*)shader_set_surface_offset },
		{ (char*)"get_surface_offset", (char*)"(J)I", (void*)shader_get_surface_offset },
		{ (char*)"set_uniform_offset", (char*)"(JI)V", (void*)shader_set_uniform_offset },
		{ (char*)"get_uniform_offset", (char*)"(J)I", (void*)shader_get_uniform_offset },
		{ (char*)"set_storage_offset", (char*)"(JI)V", (void*)shader_set_storage_offset },
		{ (char*)"get_storage_offset", (char*)"(J)I", (void*)shader_get_storage_offset },
		{ (char*)"set_tracing_offset", (char*)"(JI)V", (void*)shader_set_tracing_offset },
		{ (char*)"get_tracing_offset", (char*)"(J)I", (void*)shader_get_tracing_offset },
		{ (char*)"set_texel_offset", (char*)"(JI)V", (void*)shader_set_texel_offset },
		{ (char*)"get_texel_offset", (char*)"(J)I", (void*)shader_get_texel_offset },
		{ (char*)"set_table_offset", (char*)"(JI)V", (void*)shader_set_table_offset },
		{ (char*)"get_table_offset", (char*)"(J)I", (void*)shader_get_table_offset },
		{ (char*)"set_patch_size", (char*)"(JI)V", (void*)shader_set_patch_size },
		{ (char*)"get_patch_size", (char*)"(J)I", (void*)shader_get_patch_size },
		{ (char*)"set_input_size", (char*)"(JI)V", (void*)shader_set_input_size },
		{ (char*)"get_input_size", (char*)"(J)I", (void*)shader_get_input_size },
		{ (char*)"set_output_size", (char*)"(JI)V", (void*)shader_set_output_size },
		{ (char*)"get_output_size", (char*)"(J)I", (void*)shader_get_output_size },
		{ (char*)"load_", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)shader_load },
		{ (char*)"create_", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)shader_create },
		{ (char*)"load_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)shader_load_1 },
		{ (char*)"create_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)shader_create_1 },
		{ (char*)"load_glsl", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)shader_load_glsl },
		{ (char*)"create_glsl", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)shader_create_glsl },
		{ (char*)"load_glsl_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)shader_load_glsl_1 },
		{ (char*)"create_glsl_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)shader_create_glsl_1 },
		{ (char*)"load_spirv", (char*)"(JILjava/lang/String;)Z", (void*)shader_load_spirv },
		{ (char*)"create_spirv", (char*)"(JI[I)Z", (void*)shader_create_spirv },
		{ (char*)"has_cache", (char*)"()Z", (void*)shader_has_cache },
		{ (char*)"set_cache", (char*)"(Ljava/lang/String;)Z", (void*)shader_set_cache },
		{ (char*)"load_cache", (char*)"(JJ)Z", (void*)shader_load_cache },
		{ (char*)"save_cache", (char*)"(JJ)Z", (void*)shader_save_cache },
		{ (char*)"clear_cache", (char*)"()V", (void*)shader_clear_cache },
		{ (char*)"is_macro", (char*)"(Ljava/lang/String;)Z", (void*)shader_is_macro },
		{ (char*)"set_macro", (char*)"(Ljava/lang/String;I)Z", (void*)shader_set_macro },
		{ (char*)"set_macro_1", (char*)"(Ljava/lang/String;I)Z", (void*)shader_set_macro_1 },
		{ (char*)"set_macro_2", (char*)"(Ljava/lang/String;Ljava/lang/String;)Z", (void*)shader_set_macro_2 },
		{ (char*)"set_macros", (char*)"(Ljava/lang/String;)Z", (void*)shader_set_macros },
		{ (char*)"remove_macro", (char*)"(Ljava/lang/String;)Z", (void*)shader_remove_macro },
		{ (char*)"clear_macros", (char*)"()V", (void*)shader_clear_macros },
		{ (char*)"is_include", (char*)"(Ljava/lang/String;)Z", (void*)shader_is_include },
		{ (char*)"set_include", (char*)"(Ljava/lang/String;J)Z", (void*)shader_set_include },
		{ (char*)"remove_include", (char*)"(Ljava/lang/String;)Z", (void*)shader_remove_include },
		{ (char*)"clear_includes", (char*)"()V", (void*)shader_clear_includes },
		{ (char*)"preprocessor_", (char*)"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*)shader_preprocessor },
		{ (char*)"preprocessor_1", (char*)"(Ljava/lang/String;J[Ljava/lang/String;I)Ljava/lang/String;", (void*)shader_preprocessor_1 },
	};
	
	// Tellusim::ShaderCompiler
	static jlong shader_compiler_new(TS_JNI_ARGS) {
		return newShaderCompiler();
	}
	static void shader_compiler_delete(TS_JNI_ARGS, jlong self) {
		delete (ShaderCompiler*)self;
	}
	static jboolean shader_compiler_equal_shader_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toShaderCompiler(self).operator==(toShader(base));
	}
	static jlong shader_compiler_cast_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShaderCompiler(toShader(self));
	}
	static jlong shader_compiler_base_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toShaderCompiler(self).getShader());
	}
	static void shader_compiler_set_flags(TS_JNI_ARGS, jlong self, jint flags) {
		toShaderCompiler(self).setFlags((ShaderCompiler::Flags)flags);
	}
	static jint shader_compiler_get_flags(TS_JNI_ARGS, jlong self) {
		return toShaderCompiler(self).getFlags();
	}
	static jboolean shader_compiler_get_binary(TS_JNI_ARGS, jlong self, jlong stream, jint platform) {
		return toShaderCompiler(self).getBinary(toStream(stream), (Platform)platform);
	}
	static jstring shader_compiler_get_source(TS_JNI_ARGS, jlong self, jint platform) {
		return env->NewStringUTF(toShaderCompiler(self).getSource((Platform)platform).get());
	}
	static const JNINativeMethod shader_compiler_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)shader_compiler_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)shader_compiler_delete },
		{ (char*)"equal_shader_ptr", (char*)"(JJ)Z", (void*)shader_compiler_equal_shader_ptr },
		{ (char*)"cast_shader_ptr", (char*)"(J)J", (void*)shader_compiler_cast_shader_ptr },
		{ (char*)"base_shader_ptr", (char*)"(J)J", (void*)shader_compiler_base_shader_ptr },
		{ (char*)"set_flags", (char*)"(JI)V", (void*)shader_compiler_set_flags },
		{ (char*)"get_flags", (char*)"(J)I", (void*)shader_compiler_get_flags },
		{ (char*)"get_binary", (char*)"(JJI)Z", (void*)shader_compiler_get_binary },
		{ (char*)"get_source", (char*)"(JI)Ljava/lang/String;", (void*)shader_compiler_get_source },
	};
	
	// Tellusim::D3D12Shader
	static jlong d3d12_shader_new(TS_JNI_ARGS) {
		return newD3D12Shader();
	}
	static void d3d12_shader_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Shader*)self;
	}
	static jboolean d3d12_shader_equal_shader_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Shader(self).operator==(toShader(base));
	}
	static jlong d3d12_shader_cast_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Shader(toShader(self));
	}
	static jlong d3d12_shader_base_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toD3D12Shader(self).getShader());
	}
	static jlong d3d12_shader_get_shader_blob(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Shader(self).getShaderBlob();
	}
	static const JNINativeMethod d3d12_shader_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_shader_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_shader_delete },
		{ (char*)"equal_shader_ptr", (char*)"(JJ)Z", (void*)d3d12_shader_equal_shader_ptr },
		{ (char*)"cast_shader_ptr", (char*)"(J)J", (void*)d3d12_shader_cast_shader_ptr },
		{ (char*)"base_shader_ptr", (char*)"(J)J", (void*)d3d12_shader_base_shader_ptr },
		{ (char*)"get_shader_blob", (char*)"(J)J", (void*)d3d12_shader_get_shader_blob },
	};
	
	// Tellusim::D3D11Shader
	static jlong d3d11_shader_new(TS_JNI_ARGS) {
		return newD3D11Shader();
	}
	static void d3d11_shader_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D11Shader*)self;
	}
	static jboolean d3d11_shader_equal_shader_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D11Shader(self).operator==(toShader(base));
	}
	static jlong d3d11_shader_cast_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D11Shader(toShader(self));
	}
	static jlong d3d11_shader_base_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toD3D11Shader(self).getShader());
	}
	static jlong d3d11_shader_get_d3d11_shader(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Shader(self).getD3D11Shader();
	}
	static jlong d3d11_shader_get_shader_blob(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Shader(self).getShaderBlob();
	}
	static const JNINativeMethod d3d11_shader_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d11_shader_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d11_shader_delete },
		{ (char*)"equal_shader_ptr", (char*)"(JJ)Z", (void*)d3d11_shader_equal_shader_ptr },
		{ (char*)"cast_shader_ptr", (char*)"(J)J", (void*)d3d11_shader_cast_shader_ptr },
		{ (char*)"base_shader_ptr", (char*)"(J)J", (void*)d3d11_shader_base_shader_ptr },
		{ (char*)"get_d3d11_shader", (char*)"(J)J", (void*)d3d11_shader_get_d3d11_shader },
		{ (char*)"get_shader_blob", (char*)"(J)J", (void*)d3d11_shader_get_shader_blob },
	};
	
	// Tellusim::MTLShader
	static jlong mtl_shader_new(TS_JNI_ARGS) {
		return newMTLShader();
	}
	static void mtl_shader_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLShader*)self;
	}
	static jboolean mtl_shader_equal_shader_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLShader(self).operator==(toShader(base));
	}
	static jlong mtl_shader_cast_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLShader(toShader(self));
	}
	static jlong mtl_shader_base_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toMTLShader(self).getShader());
	}
	static void mtl_shader_set_indirect(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toMTLShader(self).setIndirect((bool)enabled);
	}
	static jboolean mtl_shader_is_indirect(TS_JNI_ARGS, jlong self) {
		return toMTLShader(self).isIndirect();
	}
	static jlong mtl_shader_get_library(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLShader(self).getLibrary();
	}
	static jlong mtl_shader_get_function(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLShader(self).getFunction();
	}
	static const JNINativeMethod mtl_shader_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_shader_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_shader_delete },
		{ (char*)"equal_shader_ptr", (char*)"(JJ)Z", (void*)mtl_shader_equal_shader_ptr },
		{ (char*)"cast_shader_ptr", (char*)"(J)J", (void*)mtl_shader_cast_shader_ptr },
		{ (char*)"base_shader_ptr", (char*)"(J)J", (void*)mtl_shader_base_shader_ptr },
		{ (char*)"set_indirect", (char*)"(JZ)V", (void*)mtl_shader_set_indirect },
		{ (char*)"is_indirect", (char*)"(J)Z", (void*)mtl_shader_is_indirect },
		{ (char*)"get_library", (char*)"(J)J", (void*)mtl_shader_get_library },
		{ (char*)"get_function", (char*)"(J)J", (void*)mtl_shader_get_function },
	};
	
	// Tellusim::VKShader
	static jlong vk_shader_new(TS_JNI_ARGS) {
		return newVKShader();
	}
	static void vk_shader_delete(TS_JNI_ARGS, jlong self) {
		delete (VKShader*)self;
	}
	static jboolean vk_shader_equal_shader_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKShader(self).operator==(toShader(base));
	}
	static jlong vk_shader_cast_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newVKShader(toShader(self));
	}
	static jlong vk_shader_base_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toVKShader(self).getShader());
	}
	static jlong vk_shader_get_module(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKShader(self).getModule();
	}
	static const JNINativeMethod vk_shader_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_shader_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_shader_delete },
		{ (char*)"equal_shader_ptr", (char*)"(JJ)Z", (void*)vk_shader_equal_shader_ptr },
		{ (char*)"cast_shader_ptr", (char*)"(J)J", (void*)vk_shader_cast_shader_ptr },
		{ (char*)"base_shader_ptr", (char*)"(J)J", (void*)vk_shader_base_shader_ptr },
		{ (char*)"get_module", (char*)"(J)J", (void*)vk_shader_get_module },
	};
	
	// Tellusim::GLShader
	static jlong gl_shader_new(TS_JNI_ARGS) {
		return newGLShader();
	}
	static void gl_shader_delete(TS_JNI_ARGS, jlong self) {
		delete (GLShader*)self;
	}
	static jboolean gl_shader_equal_shader_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLShader(self).operator==(toShader(base));
	}
	static jlong gl_shader_cast_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newGLShader(toShader(self));
	}
	static jlong gl_shader_base_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toGLShader(self).getShader());
	}
	static jboolean gl_shader_attach_shader(TS_JNI_ARGS, jlong self, jint program_id) {
		return toGLShader(self).attachShader((uint32_t)program_id);
	}
	static jint gl_shader_get_shader_type(TS_JNI_ARGS, jlong self) {
		return toGLShader(self).getShaderType();
	}
	static jint gl_shader_get_shader_id(TS_JNI_ARGS, jlong self) {
		return toGLShader(self).getShaderID();
	}
	static const JNINativeMethod gl_shader_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gl_shader_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)gl_shader_delete },
		{ (char*)"equal_shader_ptr", (char*)"(JJ)Z", (void*)gl_shader_equal_shader_ptr },
		{ (char*)"cast_shader_ptr", (char*)"(J)J", (void*)gl_shader_cast_shader_ptr },
		{ (char*)"base_shader_ptr", (char*)"(J)J", (void*)gl_shader_base_shader_ptr },
		{ (char*)"attach_shader", (char*)"(JI)Z", (void*)gl_shader_attach_shader },
		{ (char*)"get_shader_type", (char*)"(J)I", (void*)gl_shader_get_shader_type },
		{ (char*)"get_shader_id", (char*)"(J)I", (void*)gl_shader_get_shader_id },
	};
	
	// Tellusim::GLESShader
	static jlong gles_shader_new(TS_JNI_ARGS) {
		return newGLESShader();
	}
	static void gles_shader_delete(TS_JNI_ARGS, jlong self) {
		delete (GLESShader*)self;
	}
	static jboolean gles_shader_equal_shader_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLESShader(self).operator==(toShader(base));
	}
	static jlong gles_shader_cast_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newGLESShader(toShader(self));
	}
	static jlong gles_shader_base_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toGLESShader(self).getShader());
	}
	static jboolean gles_shader_attach_shader(TS_JNI_ARGS, jlong self, jint program_id) {
		return toGLESShader(self).attachShader((uint32_t)program_id);
	}
	static jint gles_shader_get_shader_type(TS_JNI_ARGS, jlong self) {
		return toGLESShader(self).getShaderType();
	}
	static jint gles_shader_get_shader_id(TS_JNI_ARGS, jlong self) {
		return toGLESShader(self).getShaderID();
	}
	static const JNINativeMethod gles_shader_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gles_shader_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)gles_shader_delete },
		{ (char*)"equal_shader_ptr", (char*)"(JJ)Z", (void*)gles_shader_equal_shader_ptr },
		{ (char*)"cast_shader_ptr", (char*)"(J)J", (void*)gles_shader_cast_shader_ptr },
		{ (char*)"base_shader_ptr", (char*)"(J)J", (void*)gles_shader_base_shader_ptr },
		{ (char*)"attach_shader", (char*)"(JI)Z", (void*)gles_shader_attach_shader },
		{ (char*)"get_shader_type", (char*)"(J)I", (void*)gles_shader_get_shader_type },
		{ (char*)"get_shader_id", (char*)"(J)I", (void*)gles_shader_get_shader_id },
	};
	
	// Tellusim::CUShader
	static jlong cu_shader_new(TS_JNI_ARGS) {
		return newCUShader();
	}
	static void cu_shader_delete(TS_JNI_ARGS, jlong self) {
		delete (CUShader*)self;
	}
	static jboolean cu_shader_equal_shader_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCUShader(self).operator==(toShader(base));
	}
	static jlong cu_shader_cast_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newCUShader(toShader(self));
	}
	static jlong cu_shader_base_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toCUShader(self).getShader());
	}
	static jlong cu_shader_get_module(TS_JNI_ARGS, jlong self) {
		return (jlong)toCUShader(self).getModule();
	}
	static jlong cu_shader_get_function(TS_JNI_ARGS, jlong self) {
		return (jlong)toCUShader(self).getFunction();
	}
	static const JNINativeMethod cu_shader_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)cu_shader_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)cu_shader_delete },
		{ (char*)"equal_shader_ptr", (char*)"(JJ)Z", (void*)cu_shader_equal_shader_ptr },
		{ (char*)"cast_shader_ptr", (char*)"(J)J", (void*)cu_shader_cast_shader_ptr },
		{ (char*)"base_shader_ptr", (char*)"(J)J", (void*)cu_shader_base_shader_ptr },
		{ (char*)"get_module", (char*)"(J)J", (void*)cu_shader_get_module },
		{ (char*)"get_function", (char*)"(J)J", (void*)cu_shader_get_function },
	};
	
	// Tellusim::HIPShader
	static jlong hip_shader_new(TS_JNI_ARGS) {
		return newHIPShader();
	}
	static void hip_shader_delete(TS_JNI_ARGS, jlong self) {
		delete (HIPShader*)self;
	}
	static jboolean hip_shader_equal_shader_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toHIPShader(self).operator==(toShader(base));
	}
	static jlong hip_shader_cast_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newHIPShader(toShader(self));
	}
	static jlong hip_shader_base_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toHIPShader(self).getShader());
	}
	static jlong hip_shader_get_module(TS_JNI_ARGS, jlong self) {
		return (jlong)toHIPShader(self).getModule();
	}
	static jlong hip_shader_get_function(TS_JNI_ARGS, jlong self) {
		return (jlong)toHIPShader(self).getFunction();
	}
	static const JNINativeMethod hip_shader_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)hip_shader_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)hip_shader_delete },
		{ (char*)"equal_shader_ptr", (char*)"(JJ)Z", (void*)hip_shader_equal_shader_ptr },
		{ (char*)"cast_shader_ptr", (char*)"(J)J", (void*)hip_shader_cast_shader_ptr },
		{ (char*)"base_shader_ptr", (char*)"(J)J", (void*)hip_shader_base_shader_ptr },
		{ (char*)"get_module", (char*)"(J)J", (void*)hip_shader_get_module },
		{ (char*)"get_function", (char*)"(J)J", (void*)hip_shader_get_function },
	};
	
	// Tellusim::FUShader
	static jlong fu_shader_new(TS_JNI_ARGS) {
		return newFUShader();
	}
	static jlong fu_shader_new_1(TS_JNI_ARGS, jlongArray shaders, jboolean owner) {
		Array<Shader> shaders_((uint32_t)env->GetArrayLength(shaders));
		jlong *shaders__ = env->GetLongArrayElements(shaders, nullptr);
		for(uint32_t i = 0; i < shaders_.size(); i++) shaders_[i] = toShader(shaders__[i]);
		jlong ret_ = newFUShader(shaders_, (bool)owner);
		if(shaders__) env->ReleaseLongArrayElements(shaders, shaders__, 0);
		return ret_;
	}
	static void fu_shader_delete(TS_JNI_ARGS, jlong self) {
		delete (FUShader*)self;
	}
	static jboolean fu_shader_equal_shader_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUShader(self).operator==(toShader(base));
	}
	static jlong fu_shader_cast_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newFUShader(toShader(self));
	}
	static jlong fu_shader_base_shader_ptr(TS_JNI_ARGS, jlong self) {
		return newShader(toFUShader(self).getShader());
	}
	static void fu_shader_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUShader(self).setMask((uint32_t)mask);
	}
	static jint fu_shader_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUShader(self).getMask();
	}
	static jint fu_shader_get_num_shaders(TS_JNI_ARGS, jlong self) {
		return toFUShader(self).getNumShaders();
	}
	static jlong fu_shader_get_shader(TS_JNI_ARGS, jlong self, jint index) {
		return newShader(toFUShader(self).getShader((uint32_t)index));
	}
	static jlong fu_shader_get_shader_1(TS_JNI_ARGS, jlong self, jint index) {
		return newShader(toFUShader(self).getShader((uint32_t)index));
	}
	static const JNINativeMethod fu_shader_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_shader_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_shader_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_shader_delete },
		{ (char*)"equal_shader_ptr", (char*)"(JJ)Z", (void*)fu_shader_equal_shader_ptr },
		{ (char*)"cast_shader_ptr", (char*)"(J)J", (void*)fu_shader_cast_shader_ptr },
		{ (char*)"base_shader_ptr", (char*)"(J)J", (void*)fu_shader_base_shader_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_shader_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_shader_get_mask },
		{ (char*)"get_num_shaders", (char*)"(J)I", (void*)fu_shader_get_num_shaders },
		{ (char*)"get_shader", (char*)"(JI)J", (void*)fu_shader_get_shader },
		{ (char*)"get_shader_1", (char*)"(JI)J", (void*)fu_shader_get_shader_1 },
	};
	
	// Tellusim::Sampler
	static jlong sampler_new(TS_JNI_ARGS) {
		return newSampler();
	}
	static void sampler_delete(TS_JNI_ARGS, jlong self) {
		delete (Sampler*)self;
	}
	static jboolean sampler_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toSampler(self) == toSampler(ptr));
	}
	static jlong sampler_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newSampler(toSampler(self).clonePtr());
	}
	static void sampler_clear_ptr(TS_JNI_ARGS, jlong self) {
		toSampler(self).clearPtr();
	}
	static void sampler_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toSampler(self).destroyPtr();
	}
	static void sampler_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toSampler(self).acquirePtr();
	}
	static void sampler_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toSampler(self).unacquirePtr();
	}
	static jboolean sampler_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toSampler(self).isValidPtr();
	}
	static jboolean sampler_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toSampler(self).isOwnerPtr();
	}
	static jboolean sampler_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toSampler(self).isConstPtr();
	}
	static jint sampler_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getCountPtr();
	}
	static jlong sampler_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toSampler(self).getInternalPtr();
	}
	static jint sampler_get_platform(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getPlatform();
	}
	static jstring sampler_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toSampler(self).getPlatformName());
	}
	static jint sampler_get_index(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getIndex();
	}
	static void sampler_clear(TS_JNI_ARGS, jlong self) {
		toSampler(self).clear();
	}
	static jboolean sampler_is_created(TS_JNI_ARGS, jlong self) {
		return toSampler(self).isCreated();
	}
	static jboolean sampler_create(TS_JNI_ARGS, jlong self) {
		return toSampler(self).create();
	}
	static void sampler_set_parameters(TS_JNI_ARGS, jlong self, jlong sampler) {
		toSampler(self).setParameters(toSampler(sampler));
	}
	static void sampler_set_filter(TS_JNI_ARGS, jlong self, jint filter) {
		toSampler(self).setFilter((Sampler::Filter)filter);
	}
	static jint sampler_get_filter(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getFilter();
	}
	static jboolean sampler_is_point_filter(TS_JNI_ARGS, jlong self) {
		return toSampler(self).isPointFilter();
	}
	static void sampler_set_anisotropy(TS_JNI_ARGS, jlong self, jint anisotropy) {
		toSampler(self).setAnisotropy((uint32_t)anisotropy);
	}
	static jint sampler_get_anisotropy(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getAnisotropy();
	}
	static jboolean sampler_has_anisotropy(TS_JNI_ARGS, jlong self) {
		return toSampler(self).hasAnisotropy();
	}
	static void sampler_set_wrap_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toSampler(self).setWrapMode((Sampler::WrapMode)mode);
	}
	static void sampler_set_wrap_mode_1(TS_JNI_ARGS, jlong self, jint mode_s, jint mode_t, jint mode_r) {
		toSampler(self).setWrapMode((Sampler::WrapMode)mode_s, (Sampler::WrapMode)mode_t, (Sampler::WrapMode)mode_r);
	}
	static void sampler_set_wrap_mode_s(TS_JNI_ARGS, jlong self, jint mode) {
		toSampler(self).setWrapModeS((Sampler::WrapMode)mode);
	}
	static jint sampler_get_wrap_mode_s(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getWrapModeS();
	}
	static void sampler_set_wrap_mode_t(TS_JNI_ARGS, jlong self, jint mode) {
		toSampler(self).setWrapModeT((Sampler::WrapMode)mode);
	}
	static jint sampler_get_wrap_mode_t(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getWrapModeT();
	}
	static void sampler_set_wrap_mode_r(TS_JNI_ARGS, jlong self, jint mode) {
		toSampler(self).setWrapModeR((Sampler::WrapMode)mode);
	}
	static jint sampler_get_wrap_mode_r(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getWrapModeR();
	}
	static void sampler_set_lod(TS_JNI_ARGS, jlong self, jfloat min, jfloat max, jfloat bias) {
		toSampler(self).setLod(min, max, bias);
	}
	static void sampler_set_lod_min(TS_JNI_ARGS, jlong self, jfloat min) {
		toSampler(self).setLodMin(min);
	}
	static jfloat sampler_get_lod_min(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getLodMin();
	}
	static void sampler_set_lod_max(TS_JNI_ARGS, jlong self, jfloat max) {
		toSampler(self).setLodMax(max);
	}
	static jfloat sampler_get_lod_max(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getLodMax();
	}
	static void sampler_set_lod_bias(TS_JNI_ARGS, jlong self, jfloat bias) {
		toSampler(self).setLodBias(bias);
	}
	static jfloat sampler_get_lod_bias(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getLodBias();
	}
	static void sampler_set_border_color(TS_JNI_ARGS, jlong self, jlong color) {
		toSampler(self).setBorderColor(toColor(color));
	}
	static void sampler_set_border_color_1(TS_JNI_ARGS, jlong self, jfloat r, jfloat g, jfloat b, jfloat a) {
		toSampler(self).setBorderColor(r, g, b, a);
	}
	static jlong sampler_get_border_color(TS_JNI_ARGS, jlong self) {
		return newColor(toSampler(self).getBorderColor());
	}
	static void sampler_set_compare_func(TS_JNI_ARGS, jlong self, jint func) {
		toSampler(self).setCompareFunc((Sampler::CompareFunc)func);
	}
	static jint sampler_get_compare_func(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getCompareFunc();
	}
	static void sampler_set_reduction_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toSampler(self).setReductionMode((Sampler::ReductionMode)mode);
	}
	static jint sampler_get_reduction_mode(TS_JNI_ARGS, jlong self) {
		return toSampler(self).getReductionMode();
	}
	static const JNINativeMethod sampler_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)sampler_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)sampler_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)sampler_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)sampler_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)sampler_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)sampler_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)sampler_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)sampler_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)sampler_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)sampler_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)sampler_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)sampler_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)sampler_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)sampler_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)sampler_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)sampler_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)sampler_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)sampler_is_created },
		{ (char*)"create_", (char*)"(J)Z", (void*)sampler_create },
		{ (char*)"set_parameters", (char*)"(JJ)V", (void*)sampler_set_parameters },
		{ (char*)"set_filter", (char*)"(JI)V", (void*)sampler_set_filter },
		{ (char*)"get_filter", (char*)"(J)I", (void*)sampler_get_filter },
		{ (char*)"is_point_filter", (char*)"(J)Z", (void*)sampler_is_point_filter },
		{ (char*)"set_anisotropy", (char*)"(JI)V", (void*)sampler_set_anisotropy },
		{ (char*)"get_anisotropy", (char*)"(J)I", (void*)sampler_get_anisotropy },
		{ (char*)"has_anisotropy", (char*)"(J)Z", (void*)sampler_has_anisotropy },
		{ (char*)"set_wrap_mode", (char*)"(JI)V", (void*)sampler_set_wrap_mode },
		{ (char*)"set_wrap_mode_1", (char*)"(JIII)V", (void*)sampler_set_wrap_mode_1 },
		{ (char*)"set_wrap_mode_s", (char*)"(JI)V", (void*)sampler_set_wrap_mode_s },
		{ (char*)"get_wrap_mode_s", (char*)"(J)I", (void*)sampler_get_wrap_mode_s },
		{ (char*)"set_wrap_mode_t", (char*)"(JI)V", (void*)sampler_set_wrap_mode_t },
		{ (char*)"get_wrap_mode_t", (char*)"(J)I", (void*)sampler_get_wrap_mode_t },
		{ (char*)"set_wrap_mode_r", (char*)"(JI)V", (void*)sampler_set_wrap_mode_r },
		{ (char*)"get_wrap_mode_r", (char*)"(J)I", (void*)sampler_get_wrap_mode_r },
		{ (char*)"set_lod", (char*)"(JFFF)V", (void*)sampler_set_lod },
		{ (char*)"set_lod_min", (char*)"(JF)V", (void*)sampler_set_lod_min },
		{ (char*)"get_lod_min", (char*)"(J)F", (void*)sampler_get_lod_min },
		{ (char*)"set_lod_max", (char*)"(JF)V", (void*)sampler_set_lod_max },
		{ (char*)"get_lod_max", (char*)"(J)F", (void*)sampler_get_lod_max },
		{ (char*)"set_lod_bias", (char*)"(JF)V", (void*)sampler_set_lod_bias },
		{ (char*)"get_lod_bias", (char*)"(J)F", (void*)sampler_get_lod_bias },
		{ (char*)"set_border_color", (char*)"(JJ)V", (void*)sampler_set_border_color },
		{ (char*)"set_border_color_1", (char*)"(JFFFF)V", (void*)sampler_set_border_color_1 },
		{ (char*)"get_border_color", (char*)"(J)J", (void*)sampler_get_border_color },
		{ (char*)"set_compare_func", (char*)"(JI)V", (void*)sampler_set_compare_func },
		{ (char*)"get_compare_func", (char*)"(J)I", (void*)sampler_get_compare_func },
		{ (char*)"set_reduction_mode", (char*)"(JI)V", (void*)sampler_set_reduction_mode },
		{ (char*)"get_reduction_mode", (char*)"(J)I", (void*)sampler_get_reduction_mode },
	};
	
	// Tellusim::MTLSampler
	static jlong mtl_sampler_new(TS_JNI_ARGS) {
		return newMTLSampler();
	}
	static void mtl_sampler_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLSampler*)self;
	}
	static jboolean mtl_sampler_equal_sampler_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLSampler(self).operator==(toSampler(base));
	}
	static jlong mtl_sampler_cast_sampler_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLSampler(toSampler(self));
	}
	static jlong mtl_sampler_base_sampler_ptr(TS_JNI_ARGS, jlong self) {
		return newSampler(toMTLSampler(self).getSampler());
	}
	static void mtl_sampler_set_indirect(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toMTLSampler(self).setIndirect((bool)enabled);
	}
	static jboolean mtl_sampler_is_indirect(TS_JNI_ARGS, jlong self) {
		return toMTLSampler(self).isIndirect();
	}
	static const JNINativeMethod mtl_sampler_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_sampler_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_sampler_delete },
		{ (char*)"equal_sampler_ptr", (char*)"(JJ)Z", (void*)mtl_sampler_equal_sampler_ptr },
		{ (char*)"cast_sampler_ptr", (char*)"(J)J", (void*)mtl_sampler_cast_sampler_ptr },
		{ (char*)"base_sampler_ptr", (char*)"(J)J", (void*)mtl_sampler_base_sampler_ptr },
		{ (char*)"set_indirect", (char*)"(JZ)V", (void*)mtl_sampler_set_indirect },
		{ (char*)"is_indirect", (char*)"(J)Z", (void*)mtl_sampler_is_indirect },
	};
	
	// Tellusim::FUSampler
	static jlong fu_sampler_new(TS_JNI_ARGS) {
		return newFUSampler();
	}
	static jlong fu_sampler_new_1(TS_JNI_ARGS, jlongArray samplers, jboolean owner) {
		Array<Sampler> samplers_((uint32_t)env->GetArrayLength(samplers));
		jlong *samplers__ = env->GetLongArrayElements(samplers, nullptr);
		for(uint32_t i = 0; i < samplers_.size(); i++) samplers_[i] = toSampler(samplers__[i]);
		jlong ret_ = newFUSampler(samplers_, (bool)owner);
		if(samplers__) env->ReleaseLongArrayElements(samplers, samplers__, 0);
		return ret_;
	}
	static void fu_sampler_delete(TS_JNI_ARGS, jlong self) {
		delete (FUSampler*)self;
	}
	static jboolean fu_sampler_equal_sampler_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUSampler(self).operator==(toSampler(base));
	}
	static jlong fu_sampler_cast_sampler_ptr(TS_JNI_ARGS, jlong self) {
		return newFUSampler(toSampler(self));
	}
	static jlong fu_sampler_base_sampler_ptr(TS_JNI_ARGS, jlong self) {
		return newSampler(toFUSampler(self).getSampler());
	}
	static void fu_sampler_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUSampler(self).setMask((uint32_t)mask);
	}
	static jint fu_sampler_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUSampler(self).getMask();
	}
	static jint fu_sampler_get_num_samplers(TS_JNI_ARGS, jlong self) {
		return toFUSampler(self).getNumSamplers();
	}
	static jlong fu_sampler_get_sampler(TS_JNI_ARGS, jlong self, jint index) {
		return newSampler(toFUSampler(self).getSampler((uint32_t)index));
	}
	static jlong fu_sampler_get_sampler_1(TS_JNI_ARGS, jlong self, jint index) {
		return newSampler(toFUSampler(self).getSampler((uint32_t)index));
	}
	static const JNINativeMethod fu_sampler_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_sampler_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_sampler_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_sampler_delete },
		{ (char*)"equal_sampler_ptr", (char*)"(JJ)Z", (void*)fu_sampler_equal_sampler_ptr },
		{ (char*)"cast_sampler_ptr", (char*)"(J)J", (void*)fu_sampler_cast_sampler_ptr },
		{ (char*)"base_sampler_ptr", (char*)"(J)J", (void*)fu_sampler_base_sampler_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_sampler_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_sampler_get_mask },
		{ (char*)"get_num_samplers", (char*)"(J)I", (void*)fu_sampler_get_num_samplers },
		{ (char*)"get_sampler", (char*)"(JI)J", (void*)fu_sampler_get_sampler },
		{ (char*)"get_sampler_1", (char*)"(JI)J", (void*)fu_sampler_get_sampler_1 },
	};
	
	// Tellusim::Texture
	static jlong texture_new(TS_JNI_ARGS) {
		return newTexture();
	}
	static void texture_delete(TS_JNI_ARGS, jlong self) {
		delete (Texture*)self;
	}
	static jboolean texture_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toTexture(self) == toTexture(ptr));
	}
	static jlong texture_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newTexture(toTexture(self).clonePtr());
	}
	static void texture_clear_ptr(TS_JNI_ARGS, jlong self) {
		toTexture(self).clearPtr();
	}
	static void texture_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toTexture(self).destroyPtr();
	}
	static void texture_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toTexture(self).acquirePtr();
	}
	static void texture_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toTexture(self).unacquirePtr();
	}
	static jboolean texture_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isValidPtr();
	}
	static jboolean texture_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isOwnerPtr();
	}
	static jboolean texture_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isConstPtr();
	}
	static jint texture_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getCountPtr();
	}
	static jlong texture_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toTexture(self).getInternalPtr();
	}
	static jint texture_get_platform(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getPlatform();
	}
	static jstring texture_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTexture(self).getPlatformName());
	}
	static jint texture_get_index(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getIndex();
	}
	static void texture_clear(TS_JNI_ARGS, jlong self) {
		toTexture(self).clear();
	}
	static jboolean texture_is_created(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isCreated();
	}
	static void texture_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toTexture(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring texture_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTexture(self).getName().get());
	}
	static jboolean texture_create(TS_JNI_ARGS, jlong self, jint type, jint format, jlong size, jint layers, jint flags) {
		return toTexture(self).create((Texture::Type)type, (Format)format, toSize(size), (uint32_t)layers, (Texture::Flags)flags);
	}
	static jboolean texture_create2d(TS_JNI_ARGS, jlong self, jint format, jint size, jint flags) {
		return toTexture(self).create2D((Format)format, (uint32_t)size, (Texture::Flags)flags);
	}
	static jboolean texture_create3d(TS_JNI_ARGS, jlong self, jint format, jint size, jint flags) {
		return toTexture(self).create3D((Format)format, (uint32_t)size, (Texture::Flags)flags);
	}
	static jboolean texture_create_cube(TS_JNI_ARGS, jlong self, jint format, jint size, jint flags) {
		return toTexture(self).createCube((Format)format, (uint32_t)size, (Texture::Flags)flags);
	}
	static jboolean texture_create2d_1(TS_JNI_ARGS, jlong self, jint format, jint width, jint height, jint flags) {
		return toTexture(self).create2D((Format)format, (uint32_t)width, (uint32_t)height, (Texture::Flags)flags);
	}
	static jboolean texture_create3d_1(TS_JNI_ARGS, jlong self, jint format, jint width, jint height, jint depth, jint flags) {
		return toTexture(self).create3D((Format)format, (uint32_t)width, (uint32_t)height, (uint32_t)depth, (Texture::Flags)flags);
	}
	static jboolean texture_create2d_2(TS_JNI_ARGS, jlong self, jint format, jint width, jint height, jint layers, jint flags) {
		return toTexture(self).create2D((Format)format, (uint32_t)width, (uint32_t)height, (uint32_t)layers, (Texture::Flags)flags);
	}
	static jboolean texture_create_cube_1(TS_JNI_ARGS, jlong self, jint format, jint size, jint layers, jint flags) {
		return toTexture(self).createCube((Format)format, (uint32_t)size, (uint32_t)layers, (Texture::Flags)flags);
	}
	static jint texture_get_type(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getType();
	}
	static jstring texture_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(Texture::getTypeName((Texture::Type)type));
	}
	static jstring texture_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTexture(self).getTypeName());
	}
	static jboolean texture_is2d_type(TS_JNI_ARGS, jlong self) {
		return toTexture(self).is2DType();
	}
	static jboolean texture_is3d_type(TS_JNI_ARGS, jlong self) {
		return toTexture(self).is3DType();
	}
	static jboolean texture_is_cube_type(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isCubeType();
	}
	static jint texture_get_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getFormat();
	}
	static jstring texture_get_format_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTexture(self).getFormatName());
	}
	static jboolean texture_is_color_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isColorFormat();
	}
	static jboolean texture_is_depth_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isDepthFormat();
	}
	static jboolean texture_is_pixel_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isPixelFormat();
	}
	static jboolean texture_is_plain_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isPlainFormat();
	}
	static jboolean texture_is_mixed_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isMixedFormat();
	}
	static jboolean texture_is_block_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isBlockFormat();
	}
	static jboolean texture_is_stencil_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isStencilFormat();
	}
	static jboolean texture_is_norm_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isNormFormat();
	}
	static jboolean texture_is_srgb_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isSRGBFormat();
	}
	static jboolean texture_is_float_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isFloatFormat();
	}
	static jboolean texture_is_signed_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isSignedFormat();
	}
	static jboolean texture_is_unsigned_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isUnsignedFormat();
	}
	static jboolean texture_is_integer_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isIntegerFormat();
	}
	static jboolean texture_isi8_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isi8Format();
	}
	static jboolean texture_isu8_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isu8Format();
	}
	static jboolean texture_is8_bit_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).is8BitFormat();
	}
	static jboolean texture_isi16_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isi16Format();
	}
	static jboolean texture_isu16_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isu16Format();
	}
	static jboolean texture_isf16_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isf16Format();
	}
	static jboolean texture_is16_bit_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).is16BitFormat();
	}
	static jboolean texture_isi32_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isi32Format();
	}
	static jboolean texture_isu32_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isu32Format();
	}
	static jboolean texture_isf32_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isf32Format();
	}
	static jboolean texture_is32_bit_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).is32BitFormat();
	}
	static jboolean texture_isi64_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isi64Format();
	}
	static jboolean texture_isu64_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isu64Format();
	}
	static jboolean texture_isf64_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isf64Format();
	}
	static jboolean texture_is64_bit_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).is64BitFormat();
	}
	static jboolean texture_is_bc15_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isBC15Format();
	}
	static jboolean texture_is_bc67_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isBC67Format();
	}
	static jboolean texture_is_etc2_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isETC2Format();
	}
	static jboolean texture_is_astc_format(TS_JNI_ARGS, jlong self) {
		return toTexture(self).isASTCFormat();
	}
	static jint texture_get_components(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getComponents();
	}
	static jint texture_get_pixel_size(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getPixelSize();
	}
	static jint texture_get_block_size(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getBlockSize();
	}
	static jint texture_get_block_width(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getBlockWidth();
	}
	static jint texture_get_block_height(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getBlockHeight();
	}
	static jint texture_get_flags(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getFlags();
	}
	static jboolean texture_has_flag(TS_JNI_ARGS, jlong self, jint flags) {
		return toTexture(self).hasFlag((Texture::Flags)flags);
	}
	static jboolean texture_has_flags(TS_JNI_ARGS, jlong self, jint flags) {
		return toTexture(self).hasFlags((Texture::Flags)flags);
	}
	static jstring texture_get_flags_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTexture(self).getFlagsName().get());
	}
	static jint texture_get_multisample(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getMultisample();
	}
	static jboolean texture_has_multisample(TS_JNI_ARGS, jlong self) {
		return toTexture(self).hasMultisample();
	}
	static jint texture_get_width(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getWidth();
	}
	static jint texture_get_height(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getHeight();
	}
	static jint texture_get_depth(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getDepth();
	}
	static jint texture_get_faces(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getFaces();
	}
	static jint texture_get_layers(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getLayers();
	}
	static jint texture_get_mipmaps(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getMipmaps();
	}
	static jint texture_find_mipmap(TS_JNI_ARGS, jlong self, jlong size) {
		return toTexture(self).findMipmap(toSize(size));
	}
	static jint texture_get_width_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return toTexture(self).getWidth((uint32_t)mipmap);
	}
	static jint texture_get_height_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return toTexture(self).getHeight((uint32_t)mipmap);
	}
	static jint texture_get_depth_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return toTexture(self).getDepth((uint32_t)mipmap);
	}
	static jboolean texture_has_faces(TS_JNI_ARGS, jlong self) {
		return toTexture(self).hasFaces();
	}
	static jboolean texture_has_layers(TS_JNI_ARGS, jlong self) {
		return toTexture(self).hasLayers();
	}
	static jboolean texture_has_mipmaps(TS_JNI_ARGS, jlong self) {
		return toTexture(self).hasMipmaps();
	}
	static jlong texture_get_size(TS_JNI_ARGS, jlong self) {
		return newSize(toTexture(self).getSize());
	}
	static jlong texture_get_region(TS_JNI_ARGS, jlong self) {
		return newRegion(toTexture(self).getRegion());
	}
	static jlong texture_get_slice(TS_JNI_ARGS, jlong self) {
		return newSlice(toTexture(self).getSlice());
	}
	static jlong texture_get_size_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return newSize(toTexture(self).getSize((uint32_t)mipmap));
	}
	static jlong texture_get_region_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return newRegion(toTexture(self).getRegion((uint32_t)mipmap));
	}
	static jlong texture_get_slice_1(TS_JNI_ARGS, jlong self, jint mipmap) {
		return newSlice(toTexture(self).getSlice((uint32_t)mipmap));
	}
	static jint texture_get_tile_width(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getTileWidth();
	}
	static jint texture_get_tile_height(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getTileHeight();
	}
	static jint texture_get_tile_depth(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getTileDepth();
	}
	static jint texture_get_tile_mipmaps(TS_JNI_ARGS, jlong self) {
		return toTexture(self).getTileMipmaps();
	}
	static jlong texture_get_tile_size(TS_JNI_ARGS, jlong self) {
		return newSize(toTexture(self).getTileSize());
	}
	static jstring texture_get_description(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTexture(self).getDescription().get());
	}
	static jlong texture_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toTexture(self).getMemory();
	}
	static const JNINativeMethod texture_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)texture_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)texture_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)texture_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)texture_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)texture_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)texture_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)texture_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)texture_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)texture_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)texture_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)texture_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)texture_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)texture_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)texture_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)texture_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)texture_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)texture_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)texture_is_created },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)texture_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)texture_get_name },
		{ (char*)"create_", (char*)"(JIIJII)Z", (void*)texture_create },
		{ (char*)"create2d_", (char*)"(JIII)Z", (void*)texture_create2d },
		{ (char*)"create3d_", (char*)"(JIII)Z", (void*)texture_create3d },
		{ (char*)"create_cube", (char*)"(JIII)Z", (void*)texture_create_cube },
		{ (char*)"create2d_1", (char*)"(JIIII)Z", (void*)texture_create2d_1 },
		{ (char*)"create3d_1", (char*)"(JIIIII)Z", (void*)texture_create3d_1 },
		{ (char*)"create2d_2", (char*)"(JIIIII)Z", (void*)texture_create2d_2 },
		{ (char*)"create_cube_1", (char*)"(JIIII)Z", (void*)texture_create_cube_1 },
		{ (char*)"get_type", (char*)"(J)I", (void*)texture_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)texture_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)texture_get_type_name_1 },
		{ (char*)"is2d_type", (char*)"(J)Z", (void*)texture_is2d_type },
		{ (char*)"is3d_type", (char*)"(J)Z", (void*)texture_is3d_type },
		{ (char*)"is_cube_type", (char*)"(J)Z", (void*)texture_is_cube_type },
		{ (char*)"get_format", (char*)"(J)I", (void*)texture_get_format },
		{ (char*)"get_format_name", (char*)"(J)Ljava/lang/String;", (void*)texture_get_format_name },
		{ (char*)"is_color_format", (char*)"(J)Z", (void*)texture_is_color_format },
		{ (char*)"is_depth_format", (char*)"(J)Z", (void*)texture_is_depth_format },
		{ (char*)"is_pixel_format", (char*)"(J)Z", (void*)texture_is_pixel_format },
		{ (char*)"is_plain_format", (char*)"(J)Z", (void*)texture_is_plain_format },
		{ (char*)"is_mixed_format", (char*)"(J)Z", (void*)texture_is_mixed_format },
		{ (char*)"is_block_format", (char*)"(J)Z", (void*)texture_is_block_format },
		{ (char*)"is_stencil_format", (char*)"(J)Z", (void*)texture_is_stencil_format },
		{ (char*)"is_norm_format", (char*)"(J)Z", (void*)texture_is_norm_format },
		{ (char*)"is_srgb_format", (char*)"(J)Z", (void*)texture_is_srgb_format },
		{ (char*)"is_float_format", (char*)"(J)Z", (void*)texture_is_float_format },
		{ (char*)"is_signed_format", (char*)"(J)Z", (void*)texture_is_signed_format },
		{ (char*)"is_unsigned_format", (char*)"(J)Z", (void*)texture_is_unsigned_format },
		{ (char*)"is_integer_format", (char*)"(J)Z", (void*)texture_is_integer_format },
		{ (char*)"isi8_format", (char*)"(J)Z", (void*)texture_isi8_format },
		{ (char*)"isu8_format", (char*)"(J)Z", (void*)texture_isu8_format },
		{ (char*)"is8_bit_format", (char*)"(J)Z", (void*)texture_is8_bit_format },
		{ (char*)"isi16_format", (char*)"(J)Z", (void*)texture_isi16_format },
		{ (char*)"isu16_format", (char*)"(J)Z", (void*)texture_isu16_format },
		{ (char*)"isf16_format", (char*)"(J)Z", (void*)texture_isf16_format },
		{ (char*)"is16_bit_format", (char*)"(J)Z", (void*)texture_is16_bit_format },
		{ (char*)"isi32_format", (char*)"(J)Z", (void*)texture_isi32_format },
		{ (char*)"isu32_format", (char*)"(J)Z", (void*)texture_isu32_format },
		{ (char*)"isf32_format", (char*)"(J)Z", (void*)texture_isf32_format },
		{ (char*)"is32_bit_format", (char*)"(J)Z", (void*)texture_is32_bit_format },
		{ (char*)"isi64_format", (char*)"(J)Z", (void*)texture_isi64_format },
		{ (char*)"isu64_format", (char*)"(J)Z", (void*)texture_isu64_format },
		{ (char*)"isf64_format", (char*)"(J)Z", (void*)texture_isf64_format },
		{ (char*)"is64_bit_format", (char*)"(J)Z", (void*)texture_is64_bit_format },
		{ (char*)"is_bc15_format", (char*)"(J)Z", (void*)texture_is_bc15_format },
		{ (char*)"is_bc67_format", (char*)"(J)Z", (void*)texture_is_bc67_format },
		{ (char*)"is_etc2_format", (char*)"(J)Z", (void*)texture_is_etc2_format },
		{ (char*)"is_astc_format", (char*)"(J)Z", (void*)texture_is_astc_format },
		{ (char*)"get_components", (char*)"(J)I", (void*)texture_get_components },
		{ (char*)"get_pixel_size", (char*)"(J)I", (void*)texture_get_pixel_size },
		{ (char*)"get_block_size", (char*)"(J)I", (void*)texture_get_block_size },
		{ (char*)"get_block_width", (char*)"(J)I", (void*)texture_get_block_width },
		{ (char*)"get_block_height", (char*)"(J)I", (void*)texture_get_block_height },
		{ (char*)"get_flags", (char*)"(J)I", (void*)texture_get_flags },
		{ (char*)"has_flag", (char*)"(JI)Z", (void*)texture_has_flag },
		{ (char*)"has_flags", (char*)"(JI)Z", (void*)texture_has_flags },
		{ (char*)"get_flags_name", (char*)"(J)Ljava/lang/String;", (void*)texture_get_flags_name },
		{ (char*)"get_multisample", (char*)"(J)I", (void*)texture_get_multisample },
		{ (char*)"has_multisample", (char*)"(J)Z", (void*)texture_has_multisample },
		{ (char*)"get_width", (char*)"(J)I", (void*)texture_get_width },
		{ (char*)"get_height", (char*)"(J)I", (void*)texture_get_height },
		{ (char*)"get_depth", (char*)"(J)I", (void*)texture_get_depth },
		{ (char*)"get_faces", (char*)"(J)I", (void*)texture_get_faces },
		{ (char*)"get_layers", (char*)"(J)I", (void*)texture_get_layers },
		{ (char*)"get_mipmaps", (char*)"(J)I", (void*)texture_get_mipmaps },
		{ (char*)"find_mipmap", (char*)"(JJ)I", (void*)texture_find_mipmap },
		{ (char*)"get_width_1", (char*)"(JI)I", (void*)texture_get_width_1 },
		{ (char*)"get_height_1", (char*)"(JI)I", (void*)texture_get_height_1 },
		{ (char*)"get_depth_1", (char*)"(JI)I", (void*)texture_get_depth_1 },
		{ (char*)"has_faces", (char*)"(J)Z", (void*)texture_has_faces },
		{ (char*)"has_layers", (char*)"(J)Z", (void*)texture_has_layers },
		{ (char*)"has_mipmaps", (char*)"(J)Z", (void*)texture_has_mipmaps },
		{ (char*)"get_size", (char*)"(J)J", (void*)texture_get_size },
		{ (char*)"get_region", (char*)"(J)J", (void*)texture_get_region },
		{ (char*)"get_slice", (char*)"(J)J", (void*)texture_get_slice },
		{ (char*)"get_size_1", (char*)"(JI)J", (void*)texture_get_size_1 },
		{ (char*)"get_region_1", (char*)"(JI)J", (void*)texture_get_region_1 },
		{ (char*)"get_slice_1", (char*)"(JI)J", (void*)texture_get_slice_1 },
		{ (char*)"get_tile_width", (char*)"(J)I", (void*)texture_get_tile_width },
		{ (char*)"get_tile_height", (char*)"(J)I", (void*)texture_get_tile_height },
		{ (char*)"get_tile_depth", (char*)"(J)I", (void*)texture_get_tile_depth },
		{ (char*)"get_tile_mipmaps", (char*)"(J)I", (void*)texture_get_tile_mipmaps },
		{ (char*)"get_tile_size", (char*)"(J)J", (void*)texture_get_tile_size },
		{ (char*)"get_description", (char*)"(J)Ljava/lang/String;", (void*)texture_get_description },
		{ (char*)"get_memory", (char*)"(J)J", (void*)texture_get_memory },
	};
	
	// Tellusim::TextureTable
	static jlong texture_table_new(TS_JNI_ARGS) {
		return newTextureTable();
	}
	static void texture_table_delete(TS_JNI_ARGS, jlong self) {
		delete (TextureTable*)self;
	}
	static jboolean texture_table_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toTextureTable(self) == toTextureTable(ptr));
	}
	static jlong texture_table_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newTextureTable(toTextureTable(self).clonePtr());
	}
	static void texture_table_clear_ptr(TS_JNI_ARGS, jlong self) {
		toTextureTable(self).clearPtr();
	}
	static void texture_table_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toTextureTable(self).destroyPtr();
	}
	static void texture_table_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toTextureTable(self).acquirePtr();
	}
	static void texture_table_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toTextureTable(self).unacquirePtr();
	}
	static jboolean texture_table_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toTextureTable(self).isValidPtr();
	}
	static jboolean texture_table_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toTextureTable(self).isOwnerPtr();
	}
	static jboolean texture_table_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toTextureTable(self).isConstPtr();
	}
	static jint texture_table_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toTextureTable(self).getCountPtr();
	}
	static jlong texture_table_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toTextureTable(self).getInternalPtr();
	}
	static jint texture_table_get_platform(TS_JNI_ARGS, jlong self) {
		return toTextureTable(self).getPlatform();
	}
	static jstring texture_table_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTextureTable(self).getPlatformName());
	}
	static jint texture_table_get_index(TS_JNI_ARGS, jlong self) {
		return toTextureTable(self).getIndex();
	}
	static void texture_table_clear(TS_JNI_ARGS, jlong self) {
		toTextureTable(self).clear();
	}
	static jboolean texture_table_is_created(TS_JNI_ARGS, jlong self) {
		return toTextureTable(self).isCreated();
	}
	static void texture_table_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toTextureTable(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring texture_table_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTextureTable(self).getName().get());
	}
	static jboolean texture_table_create(TS_JNI_ARGS, jlong self, jint type, jint size) {
		return toTextureTable(self).create((Texture::Type)type, (uint32_t)size);
	}
	static jint texture_table_get_type(TS_JNI_ARGS, jlong self) {
		return toTextureTable(self).getType();
	}
	static jstring texture_table_get_type_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTextureTable(self).getTypeName());
	}
	static jint texture_table_get_size(TS_JNI_ARGS, jlong self) {
		return toTextureTable(self).getSize();
	}
	static jlong texture_table_get(TS_JNI_ARGS, jlong self, jint index) {
		return newTexture(toTextureTable(self).get((uint32_t)index));
	}
	static jboolean texture_table_is_owner(TS_JNI_ARGS, jlong self, jint index) {
		return toTextureTable(self).isOwner((uint32_t)index);
	}
	static jlong texture_table_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toTextureTable(self).getMemory();
	}
	static const JNINativeMethod texture_table_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)texture_table_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)texture_table_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)texture_table_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)texture_table_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)texture_table_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)texture_table_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)texture_table_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)texture_table_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)texture_table_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)texture_table_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)texture_table_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)texture_table_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)texture_table_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)texture_table_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)texture_table_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)texture_table_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)texture_table_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)texture_table_is_created },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)texture_table_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)texture_table_get_name },
		{ (char*)"create_", (char*)"(JII)Z", (void*)texture_table_create },
		{ (char*)"get_type", (char*)"(J)I", (void*)texture_table_get_type },
		{ (char*)"get_type_name", (char*)"(J)Ljava/lang/String;", (void*)texture_table_get_type_name },
		{ (char*)"get_size", (char*)"(J)I", (void*)texture_table_get_size },
		{ (char*)"get_", (char*)"(JI)J", (void*)texture_table_get },
		{ (char*)"is_owner", (char*)"(JI)Z", (void*)texture_table_is_owner },
		{ (char*)"get_memory", (char*)"(J)J", (void*)texture_table_get_memory },
	};
	
	// Tellusim::D3D12Texture
	static jlong d3d12_texture_new(TS_JNI_ARGS) {
		return newD3D12Texture();
	}
	static void d3d12_texture_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Texture*)self;
	}
	static jboolean d3d12_texture_equal_texture_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Texture(self).operator==(toTexture(base));
	}
	static jlong d3d12_texture_cast_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Texture(toTexture(self));
	}
	static jlong d3d12_texture_base_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newTexture(toD3D12Texture(self).getTexture());
	}
	static jboolean d3d12_texture_create(TS_JNI_ARGS, jlong self, jint type, jlong texture, jint state, jint flags, jint format) {
		return toD3D12Texture(self).create((Texture::Type)type, (ID3D12Resource*)texture, (uint32_t)state, (Texture::Flags)flags, (Format)format);
	}
	static jint d3d12_texture_get_dxgi_format(TS_JNI_ARGS, jlong self) {
		return toD3D12Texture(self).getDXGIFormat();
	}
	static jlong d3d12_texture_get_d3d12_texture(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Texture(self).getD3D12Texture();
	}
	static jlong d3d12_texture_get_shader_resource_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Texture(self).getShaderResourceView();
	}
	static jlong d3d12_texture_get_render_target_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Texture(self).getRenderTargetView();
	}
	static jlong d3d12_texture_get_depth_stencil_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Texture(self).getDepthStencilView();
	}
	static jlong d3d12_texture_get_unordered_access_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Texture(self).getUnorderedAccessView();
	}
	static void d3d12_texture_set_texture_state(TS_JNI_ARGS, jlong self, jint state) {
		toD3D12Texture(self).setTextureState((uint32_t)state);
	}
	static jint d3d12_texture_get_texture_state(TS_JNI_ARGS, jlong self) {
		return toD3D12Texture(self).getTextureState();
	}
	static jlong d3d12_texture_get_shared_handle(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Texture(self).getSharedHandle();
	}
	static jlong d3d12_texture_get_interop_handle(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Texture(self).getInteropHandle();
	}
	static const JNINativeMethod d3d12_texture_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_texture_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_texture_delete },
		{ (char*)"equal_texture_ptr", (char*)"(JJ)Z", (void*)d3d12_texture_equal_texture_ptr },
		{ (char*)"cast_texture_ptr", (char*)"(J)J", (void*)d3d12_texture_cast_texture_ptr },
		{ (char*)"base_texture_ptr", (char*)"(J)J", (void*)d3d12_texture_base_texture_ptr },
		{ (char*)"create_", (char*)"(JIJIII)Z", (void*)d3d12_texture_create },
		{ (char*)"get_dxgi_format", (char*)"(J)I", (void*)d3d12_texture_get_dxgi_format },
		{ (char*)"get_d3d12_texture", (char*)"(J)J", (void*)d3d12_texture_get_d3d12_texture },
		{ (char*)"get_shader_resource_view", (char*)"(J)J", (void*)d3d12_texture_get_shader_resource_view },
		{ (char*)"get_render_target_view", (char*)"(J)J", (void*)d3d12_texture_get_render_target_view },
		{ (char*)"get_depth_stencil_view", (char*)"(J)J", (void*)d3d12_texture_get_depth_stencil_view },
		{ (char*)"get_unordered_access_view", (char*)"(J)J", (void*)d3d12_texture_get_unordered_access_view },
		{ (char*)"set_texture_state", (char*)"(JI)V", (void*)d3d12_texture_set_texture_state },
		{ (char*)"get_texture_state", (char*)"(J)I", (void*)d3d12_texture_get_texture_state },
		{ (char*)"get_shared_handle", (char*)"(J)J", (void*)d3d12_texture_get_shared_handle },
		{ (char*)"get_interop_handle", (char*)"(J)J", (void*)d3d12_texture_get_interop_handle },
	};
	
	// Tellusim::D3D11Texture
	static jlong d3d11_texture_new(TS_JNI_ARGS) {
		return newD3D11Texture();
	}
	static void d3d11_texture_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D11Texture*)self;
	}
	static jboolean d3d11_texture_equal_texture_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D11Texture(self).operator==(toTexture(base));
	}
	static jlong d3d11_texture_cast_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D11Texture(toTexture(self));
	}
	static jlong d3d11_texture_base_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newTexture(toD3D11Texture(self).getTexture());
	}
	static jboolean d3d11_texture_create(TS_JNI_ARGS, jlong self, jint type, jlong texture, jint flags, jint format) {
		return toD3D11Texture(self).create((Texture::Type)type, (ID3D11Texture2D*)texture, (Texture::Flags)flags, (Format)format);
	}
	static jint d3d11_texture_get_dxgi_format(TS_JNI_ARGS, jlong self) {
		return toD3D11Texture(self).getDXGIFormat();
	}
	static jlong d3d11_texture_get_d3d11_texture(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Texture(self).getD3D11Texture();
	}
	static jlong d3d11_texture_get_shader_resource_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Texture(self).getShaderResourceView();
	}
	static jlong d3d11_texture_get_render_target_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Texture(self).getRenderTargetView();
	}
	static jlong d3d11_texture_get_depth_stencil_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Texture(self).getDepthStencilView();
	}
	static jlong d3d11_texture_get_unordered_access_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Texture(self).getUnorderedAccessView();
	}
	static jlong d3d11_texture_get_interop_handle(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Texture(self).getInteropHandle();
	}
	static const JNINativeMethod d3d11_texture_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d11_texture_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d11_texture_delete },
		{ (char*)"equal_texture_ptr", (char*)"(JJ)Z", (void*)d3d11_texture_equal_texture_ptr },
		{ (char*)"cast_texture_ptr", (char*)"(J)J", (void*)d3d11_texture_cast_texture_ptr },
		{ (char*)"base_texture_ptr", (char*)"(J)J", (void*)d3d11_texture_base_texture_ptr },
		{ (char*)"create_", (char*)"(JIJII)Z", (void*)d3d11_texture_create },
		{ (char*)"get_dxgi_format", (char*)"(J)I", (void*)d3d11_texture_get_dxgi_format },
		{ (char*)"get_d3d11_texture", (char*)"(J)J", (void*)d3d11_texture_get_d3d11_texture },
		{ (char*)"get_shader_resource_view", (char*)"(J)J", (void*)d3d11_texture_get_shader_resource_view },
		{ (char*)"get_render_target_view", (char*)"(J)J", (void*)d3d11_texture_get_render_target_view },
		{ (char*)"get_depth_stencil_view", (char*)"(J)J", (void*)d3d11_texture_get_depth_stencil_view },
		{ (char*)"get_unordered_access_view", (char*)"(J)J", (void*)d3d11_texture_get_unordered_access_view },
		{ (char*)"get_interop_handle", (char*)"(J)J", (void*)d3d11_texture_get_interop_handle },
	};
	
	// Tellusim::MTLTexture
	static jlong mtl_texture_new(TS_JNI_ARGS) {
		return newMTLTexture();
	}
	static void mtl_texture_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLTexture*)self;
	}
	static jboolean mtl_texture_equal_texture_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLTexture(self).operator==(toTexture(base));
	}
	static jlong mtl_texture_cast_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLTexture(toTexture(self));
	}
	static jlong mtl_texture_base_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newTexture(toMTLTexture(self).getTexture());
	}
	static jboolean mtl_texture_create(TS_JNI_ARGS, jlong self, jlong texture, jint flags, jint format) {
		return toMTLTexture(self).create((void*)texture, (Texture::Flags)flags, (Format)format);
	}
	static jint mtl_texture_get_pixel_format(TS_JNI_ARGS, jlong self) {
		return toMTLTexture(self).getPixelFormat();
	}
	static jint mtl_texture_get_texture_type(TS_JNI_ARGS, jlong self) {
		return toMTLTexture(self).getTextureType();
	}
	static jlong mtl_texture_get_mtl_texture(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLTexture(self).getMTLTexture();
	}
	static jlong mtl_texture_get_mtl_buffer(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLTexture(self).getMTLBuffer();
	}
	static jlong mtl_texture_get_shared_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLTexture(self).getSharedPtr();
	}
	static const JNINativeMethod mtl_texture_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_texture_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_texture_delete },
		{ (char*)"equal_texture_ptr", (char*)"(JJ)Z", (void*)mtl_texture_equal_texture_ptr },
		{ (char*)"cast_texture_ptr", (char*)"(J)J", (void*)mtl_texture_cast_texture_ptr },
		{ (char*)"base_texture_ptr", (char*)"(J)J", (void*)mtl_texture_base_texture_ptr },
		{ (char*)"create_", (char*)"(JJII)Z", (void*)mtl_texture_create },
		{ (char*)"get_pixel_format", (char*)"(J)I", (void*)mtl_texture_get_pixel_format },
		{ (char*)"get_texture_type", (char*)"(J)I", (void*)mtl_texture_get_texture_type },
		{ (char*)"get_mtl_texture", (char*)"(J)J", (void*)mtl_texture_get_mtl_texture },
		{ (char*)"get_mtl_buffer", (char*)"(J)J", (void*)mtl_texture_get_mtl_buffer },
		{ (char*)"get_shared_ptr", (char*)"(J)J", (void*)mtl_texture_get_shared_ptr },
	};
	
	// Tellusim::VKTexture
	static jlong vk_texture_new(TS_JNI_ARGS) {
		return newVKTexture();
	}
	static void vk_texture_delete(TS_JNI_ARGS, jlong self) {
		delete (VKTexture*)self;
	}
	static jboolean vk_texture_equal_texture_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKTexture(self).operator==(toTexture(base));
	}
	static jlong vk_texture_cast_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newVKTexture(toTexture(self));
	}
	static jlong vk_texture_base_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newTexture(toVKTexture(self).getTexture());
	}
	static jboolean vk_texture_create(TS_JNI_ARGS, jlong self, jint type, jint format, jlong texture, jint layout, jint flags, jint texture_format) {
		return toVKTexture(self).create((Texture::Type)type, (uint32_t)format, (VkImage)texture, (uint32_t)layout, (Texture::Flags)flags, (Format)texture_format);
	}
	static jint vk_texture_get_pixel_format(TS_JNI_ARGS, jlong self) {
		return toVKTexture(self).getPixelFormat();
	}
	static jlong vk_texture_get_vk_texture(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKTexture(self).getVKTexture();
	}
	static jlong vk_texture_get_texture_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKTexture(self).getTextureView();
	}
	static void vk_texture_set_texture_layout(TS_JNI_ARGS, jlong self, jint layout) {
		toVKTexture(self).setTextureLayout((uint32_t)layout);
	}
	static jint vk_texture_get_texture_layout(TS_JNI_ARGS, jlong self) {
		return toVKTexture(self).getTextureLayout();
	}
	static void vk_texture_get_texture_range(TS_JNI_ARGS, jlong self, jlong range, jlong slice) {
		toVKTexture(self).getTextureRange((void*)range, toSlice(slice));
	}
	static jlong vk_texture_get_shared_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKTexture(self).getSharedPtr();
	}
	static jlong vk_texture_get_interop_handle(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKTexture(self).getInteropHandle();
	}
	static const JNINativeMethod vk_texture_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_texture_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_texture_delete },
		{ (char*)"equal_texture_ptr", (char*)"(JJ)Z", (void*)vk_texture_equal_texture_ptr },
		{ (char*)"cast_texture_ptr", (char*)"(J)J", (void*)vk_texture_cast_texture_ptr },
		{ (char*)"base_texture_ptr", (char*)"(J)J", (void*)vk_texture_base_texture_ptr },
		{ (char*)"create_", (char*)"(JIIJIII)Z", (void*)vk_texture_create },
		{ (char*)"get_pixel_format", (char*)"(J)I", (void*)vk_texture_get_pixel_format },
		{ (char*)"get_vk_texture", (char*)"(J)J", (void*)vk_texture_get_vk_texture },
		{ (char*)"get_texture_view", (char*)"(J)J", (void*)vk_texture_get_texture_view },
		{ (char*)"set_texture_layout", (char*)"(JI)V", (void*)vk_texture_set_texture_layout },
		{ (char*)"get_texture_layout", (char*)"(J)I", (void*)vk_texture_get_texture_layout },
		{ (char*)"get_texture_range", (char*)"(JJJ)V", (void*)vk_texture_get_texture_range },
		{ (char*)"get_shared_ptr", (char*)"(J)J", (void*)vk_texture_get_shared_ptr },
		{ (char*)"get_interop_handle", (char*)"(J)J", (void*)vk_texture_get_interop_handle },
	};
	
	// Tellusim::GLTexture
	static jlong gl_texture_new(TS_JNI_ARGS) {
		return newGLTexture();
	}
	static void gl_texture_delete(TS_JNI_ARGS, jlong self) {
		delete (GLTexture*)self;
	}
	static jboolean gl_texture_equal_texture_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLTexture(self).operator==(toTexture(base));
	}
	static jlong gl_texture_cast_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newGLTexture(toTexture(self));
	}
	static jlong gl_texture_base_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newTexture(toGLTexture(self).getTexture());
	}
	static jboolean gl_texture_create(TS_JNI_ARGS, jlong self, jint target, jint texture_id, jint flags, jint format) {
		return toGLTexture(self).create((uint32_t)target, (uint32_t)texture_id, (Texture::Flags)flags, (Format)format);
	}
	static jint gl_texture_get_target(TS_JNI_ARGS, jlong self) {
		return toGLTexture(self).getTarget();
	}
	static jint gl_texture_get_internal_format(TS_JNI_ARGS, jlong self) {
		return toGLTexture(self).getInternalFormat();
	}
	static jint gl_texture_get_texture_id(TS_JNI_ARGS, jlong self) {
		return toGLTexture(self).getTextureID();
	}
	static const JNINativeMethod gl_texture_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gl_texture_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)gl_texture_delete },
		{ (char*)"equal_texture_ptr", (char*)"(JJ)Z", (void*)gl_texture_equal_texture_ptr },
		{ (char*)"cast_texture_ptr", (char*)"(J)J", (void*)gl_texture_cast_texture_ptr },
		{ (char*)"base_texture_ptr", (char*)"(J)J", (void*)gl_texture_base_texture_ptr },
		{ (char*)"create_", (char*)"(JIIII)Z", (void*)gl_texture_create },
		{ (char*)"get_target", (char*)"(J)I", (void*)gl_texture_get_target },
		{ (char*)"get_internal_format", (char*)"(J)I", (void*)gl_texture_get_internal_format },
		{ (char*)"get_texture_id", (char*)"(J)I", (void*)gl_texture_get_texture_id },
	};
	
	// Tellusim::GLESTexture
	static jlong gles_texture_new(TS_JNI_ARGS) {
		return newGLESTexture();
	}
	static void gles_texture_delete(TS_JNI_ARGS, jlong self) {
		delete (GLESTexture*)self;
	}
	static jboolean gles_texture_equal_texture_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLESTexture(self).operator==(toTexture(base));
	}
	static jlong gles_texture_cast_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newGLESTexture(toTexture(self));
	}
	static jlong gles_texture_base_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newTexture(toGLESTexture(self).getTexture());
	}
	static jboolean gles_texture_create(TS_JNI_ARGS, jlong self, jint target, jint texture_id, jint flags, jint format) {
		return toGLESTexture(self).create((uint32_t)target, (uint32_t)texture_id, (Texture::Flags)flags, (Format)format);
	}
	static jint gles_texture_get_target(TS_JNI_ARGS, jlong self) {
		return toGLESTexture(self).getTarget();
	}
	static jint gles_texture_get_internal_format(TS_JNI_ARGS, jlong self) {
		return toGLESTexture(self).getInternalFormat();
	}
	static jint gles_texture_get_texture_id(TS_JNI_ARGS, jlong self) {
		return toGLESTexture(self).getTextureID();
	}
	static const JNINativeMethod gles_texture_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gles_texture_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)gles_texture_delete },
		{ (char*)"equal_texture_ptr", (char*)"(JJ)Z", (void*)gles_texture_equal_texture_ptr },
		{ (char*)"cast_texture_ptr", (char*)"(J)J", (void*)gles_texture_cast_texture_ptr },
		{ (char*)"base_texture_ptr", (char*)"(J)J", (void*)gles_texture_base_texture_ptr },
		{ (char*)"create_", (char*)"(JIIII)Z", (void*)gles_texture_create },
		{ (char*)"get_target", (char*)"(J)I", (void*)gles_texture_get_target },
		{ (char*)"get_internal_format", (char*)"(J)I", (void*)gles_texture_get_internal_format },
		{ (char*)"get_texture_id", (char*)"(J)I", (void*)gles_texture_get_texture_id },
	};
	
	// Tellusim::CUTexture
	static jlong cu_texture_new(TS_JNI_ARGS) {
		return newCUTexture();
	}
	static void cu_texture_delete(TS_JNI_ARGS, jlong self) {
		delete (CUTexture*)self;
	}
	static jboolean cu_texture_equal_texture_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCUTexture(self).operator==(toTexture(base));
	}
	static jlong cu_texture_cast_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newCUTexture(toTexture(self));
	}
	static jlong cu_texture_base_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newTexture(toCUTexture(self).getTexture());
	}
	static jlong cu_texture_get_texture_level(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toCUTexture(self).getTextureLevel((uint32_t)index);
	}
	static jint cu_texture_get_array_format(TS_JNI_ARGS, jlong self) {
		return toCUTexture(self).getArrayFormat();
	}
	static jint cu_texture_get_array_channels(TS_JNI_ARGS, jlong self) {
		return toCUTexture(self).getArrayChannels();
	}
	static jlong cu_texture_get_shared_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toCUTexture(self).getSharedMemory();
	}
	static const JNINativeMethod cu_texture_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)cu_texture_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)cu_texture_delete },
		{ (char*)"equal_texture_ptr", (char*)"(JJ)Z", (void*)cu_texture_equal_texture_ptr },
		{ (char*)"cast_texture_ptr", (char*)"(J)J", (void*)cu_texture_cast_texture_ptr },
		{ (char*)"base_texture_ptr", (char*)"(J)J", (void*)cu_texture_base_texture_ptr },
		{ (char*)"get_texture_level", (char*)"(JI)J", (void*)cu_texture_get_texture_level },
		{ (char*)"get_array_format", (char*)"(J)I", (void*)cu_texture_get_array_format },
		{ (char*)"get_array_channels", (char*)"(J)I", (void*)cu_texture_get_array_channels },
		{ (char*)"get_shared_memory", (char*)"(J)J", (void*)cu_texture_get_shared_memory },
	};
	
	// Tellusim::HIPTexture
	static jlong hip_texture_new(TS_JNI_ARGS) {
		return newHIPTexture();
	}
	static void hip_texture_delete(TS_JNI_ARGS, jlong self) {
		delete (HIPTexture*)self;
	}
	static jboolean hip_texture_equal_texture_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toHIPTexture(self).operator==(toTexture(base));
	}
	static jlong hip_texture_cast_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newHIPTexture(toTexture(self));
	}
	static jlong hip_texture_base_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newTexture(toHIPTexture(self).getTexture());
	}
	static jlong hip_texture_get_texture_array(TS_JNI_ARGS, jlong self) {
		return (jlong)toHIPTexture(self).getTextureArray();
	}
	static jlong hip_texture_get_texture_level(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toHIPTexture(self).getTextureLevel((uint32_t)index);
	}
	static jlong hip_texture_get_channel_format(TS_JNI_ARGS, jlong self) {
		return (jlong)toHIPTexture(self).getChannelFormat();
	}
	static const JNINativeMethod hip_texture_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)hip_texture_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)hip_texture_delete },
		{ (char*)"equal_texture_ptr", (char*)"(JJ)Z", (void*)hip_texture_equal_texture_ptr },
		{ (char*)"cast_texture_ptr", (char*)"(J)J", (void*)hip_texture_cast_texture_ptr },
		{ (char*)"base_texture_ptr", (char*)"(J)J", (void*)hip_texture_base_texture_ptr },
		{ (char*)"get_texture_array", (char*)"(J)J", (void*)hip_texture_get_texture_array },
		{ (char*)"get_texture_level", (char*)"(JI)J", (void*)hip_texture_get_texture_level },
		{ (char*)"get_channel_format", (char*)"(J)J", (void*)hip_texture_get_channel_format },
	};
	
	// Tellusim::FUTexture
	static jlong fu_texture_new(TS_JNI_ARGS) {
		return newFUTexture();
	}
	static jlong fu_texture_new_1(TS_JNI_ARGS, jlongArray textures, jboolean owner) {
		Array<Texture> textures_((uint32_t)env->GetArrayLength(textures));
		jlong *textures__ = env->GetLongArrayElements(textures, nullptr);
		for(uint32_t i = 0; i < textures_.size(); i++) textures_[i] = toTexture(textures__[i]);
		jlong ret_ = newFUTexture(textures_, (bool)owner);
		if(textures__) env->ReleaseLongArrayElements(textures, textures__, 0);
		return ret_;
	}
	static void fu_texture_delete(TS_JNI_ARGS, jlong self) {
		delete (FUTexture*)self;
	}
	static jboolean fu_texture_equal_texture_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUTexture(self).operator==(toTexture(base));
	}
	static jlong fu_texture_cast_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newFUTexture(toTexture(self));
	}
	static jlong fu_texture_base_texture_ptr(TS_JNI_ARGS, jlong self) {
		return newTexture(toFUTexture(self).getTexture());
	}
	static void fu_texture_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUTexture(self).setMask((uint32_t)mask);
	}
	static jint fu_texture_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUTexture(self).getMask();
	}
	static jint fu_texture_get_num_textures(TS_JNI_ARGS, jlong self) {
		return toFUTexture(self).getNumTextures();
	}
	static jlong fu_texture_get_texture(TS_JNI_ARGS, jlong self, jint index) {
		return newTexture(toFUTexture(self).getTexture((uint32_t)index));
	}
	static jlong fu_texture_get_texture_1(TS_JNI_ARGS, jlong self, jint index) {
		return newTexture(toFUTexture(self).getTexture((uint32_t)index));
	}
	static const JNINativeMethod fu_texture_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_texture_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_texture_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_texture_delete },
		{ (char*)"equal_texture_ptr", (char*)"(JJ)Z", (void*)fu_texture_equal_texture_ptr },
		{ (char*)"cast_texture_ptr", (char*)"(J)J", (void*)fu_texture_cast_texture_ptr },
		{ (char*)"base_texture_ptr", (char*)"(J)J", (void*)fu_texture_base_texture_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_texture_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_texture_get_mask },
		{ (char*)"get_num_textures", (char*)"(J)I", (void*)fu_texture_get_num_textures },
		{ (char*)"get_texture", (char*)"(JI)J", (void*)fu_texture_get_texture },
		{ (char*)"get_texture_1", (char*)"(JI)J", (void*)fu_texture_get_texture_1 },
	};
	
	// Tellusim::Tracing::Instance
	static jlong tracing_instance_new(TS_JNI_ARGS) {
		return newTracingInstance();
	}
	static jlong tracing_instance_copy(TS_JNI_ARGS, jlong self) {
		return newTracingInstance(toTracingInstance(self));
	}
	static void tracing_instance_delete(TS_JNI_ARGS, jlong self) {
		delete (Tracing::Instance*)self;
	}
	static void tracing_instance_set_transform(TS_JNI_ARGS, jlong self, jlong transform) {
		toMatrix4x3f(transform).get(toTracingInstance(self).transform);
	}
	static jlong tracing_instance_get_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x3f(toTracingInstance(self).transform);
	}
	static void tracing_instance_set_data(TS_JNI_ARGS, jlong self, jint data) {
		toTracingInstance(self).data = data;
	}
	static jint tracing_instance_get_data(TS_JNI_ARGS, jlong self) {
		return toTracingInstance(self).data;
	}
	static void tracing_instance_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toTracingInstance(self).mask = mask;
	}
	static jint tracing_instance_get_mask(TS_JNI_ARGS, jlong self) {
		return toTracingInstance(self).mask;
	}
	static void tracing_instance_set_flags(TS_JNI_ARGS, jlong self, jint flags) {
		toTracingInstance(self).flags = flags;
	}
	static jint tracing_instance_get_flags(TS_JNI_ARGS, jlong self) {
		return toTracingInstance(self).flags;
	}
	static void tracing_instance_set_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toTracingInstance(self).offset = offset;
	}
	static jint tracing_instance_get_offset(TS_JNI_ARGS, jlong self) {
		return toTracingInstance(self).offset;
	}
	static void tracing_instance_set_tracing(TS_JNI_ARGS, jlong self, jlong tracing) {
		toTracingInstance(self).tracing = (Tracing*)tracing;
	}
	static jlong tracing_instance_get_tracing(TS_JNI_ARGS, jlong self) {
		Tracing *ret = toTracingInstance(self).tracing;
		if(ret) return newTracing(*ret);
		return newTracing();
	}
	static const JNINativeMethod tracing_instance_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)tracing_instance_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)tracing_instance_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)tracing_instance_delete },
		{ (char*)"set_transform_", (char*)"(JJ)V", (void*)tracing_instance_set_transform },
		{ (char*)"get_transform_", (char*)"(J)J", (void*)tracing_instance_get_transform },
		{ (char*)"set_data_", (char*)"(JI)V", (void*)tracing_instance_set_data },
		{ (char*)"get_data_", (char*)"(J)I", (void*)tracing_instance_get_data },
		{ (char*)"set_mask_", (char*)"(JI)V", (void*)tracing_instance_set_mask },
		{ (char*)"get_mask_", (char*)"(J)I", (void*)tracing_instance_get_mask },
		{ (char*)"set_flags_", (char*)"(JI)V", (void*)tracing_instance_set_flags },
		{ (char*)"get_flags_", (char*)"(J)I", (void*)tracing_instance_get_flags },
		{ (char*)"set_offset_", (char*)"(JI)V", (void*)tracing_instance_set_offset },
		{ (char*)"get_offset_", (char*)"(J)I", (void*)tracing_instance_get_offset },
		{ (char*)"set_tracing_", (char*)"(JJ)V", (void*)tracing_instance_set_tracing },
		{ (char*)"get_tracing_", (char*)"(J)J", (void*)tracing_instance_get_tracing },
	};
	// Tellusim::Tracing::BuildIndirect
	static jlong tracing_build_indirect_new(TS_JNI_ARGS) {
		return newTracingBuildIndirect();
	}
	static jlong tracing_build_indirect_copy(TS_JNI_ARGS, jlong self) {
		return newTracingBuildIndirect(toTracingBuildIndirect(self));
	}
	static void tracing_build_indirect_delete(TS_JNI_ARGS, jlong self) {
		delete (Tracing::BuildIndirect*)self;
	}
	static void tracing_build_indirect_set_num_primitives(TS_JNI_ARGS, jlong self, jint num_primitives) {
		toTracingBuildIndirect(self).num_primitives = num_primitives;
	}
	static jint tracing_build_indirect_get_num_primitives(TS_JNI_ARGS, jlong self) {
		return toTracingBuildIndirect(self).num_primitives;
	}
	static void tracing_build_indirect_set_base_primitive(TS_JNI_ARGS, jlong self, jint base_primitive) {
		toTracingBuildIndirect(self).base_primitive = base_primitive;
	}
	static jint tracing_build_indirect_get_base_primitive(TS_JNI_ARGS, jlong self) {
		return toTracingBuildIndirect(self).base_primitive;
	}
	static void tracing_build_indirect_set_base_vertex(TS_JNI_ARGS, jlong self, jint base_vertex) {
		toTracingBuildIndirect(self).base_vertex = base_vertex;
	}
	static jint tracing_build_indirect_get_base_vertex(TS_JNI_ARGS, jlong self) {
		return toTracingBuildIndirect(self).base_vertex;
	}
	static void tracing_build_indirect_set_base_transform(TS_JNI_ARGS, jlong self, jint base_transform) {
		toTracingBuildIndirect(self).base_transform = base_transform;
	}
	static jint tracing_build_indirect_get_base_transform(TS_JNI_ARGS, jlong self) {
		return toTracingBuildIndirect(self).base_transform;
	}
	static const JNINativeMethod tracing_build_indirect_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)tracing_build_indirect_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)tracing_build_indirect_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)tracing_build_indirect_delete },
		{ (char*)"set_num_primitives_", (char*)"(JI)V", (void*)tracing_build_indirect_set_num_primitives },
		{ (char*)"get_num_primitives_", (char*)"(J)I", (void*)tracing_build_indirect_get_num_primitives },
		{ (char*)"set_base_primitive_", (char*)"(JI)V", (void*)tracing_build_indirect_set_base_primitive },
		{ (char*)"get_base_primitive_", (char*)"(J)I", (void*)tracing_build_indirect_get_base_primitive },
		{ (char*)"set_base_vertex_", (char*)"(JI)V", (void*)tracing_build_indirect_set_base_vertex },
		{ (char*)"get_base_vertex_", (char*)"(J)I", (void*)tracing_build_indirect_get_base_vertex },
		{ (char*)"set_base_transform_", (char*)"(JI)V", (void*)tracing_build_indirect_set_base_transform },
		{ (char*)"get_base_transform_", (char*)"(J)I", (void*)tracing_build_indirect_get_base_transform },
	};
	// Tellusim::Tracing
	static jlong tracing_new(TS_JNI_ARGS) {
		return newTracing();
	}
	static void tracing_delete(TS_JNI_ARGS, jlong self) {
		delete (Tracing*)self;
	}
	static jboolean tracing_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toTracing(self) == toTracing(ptr));
	}
	static jlong tracing_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newTracing(toTracing(self).clonePtr());
	}
	static void tracing_clear_ptr(TS_JNI_ARGS, jlong self) {
		toTracing(self).clearPtr();
	}
	static void tracing_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toTracing(self).destroyPtr();
	}
	static void tracing_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toTracing(self).acquirePtr();
	}
	static void tracing_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toTracing(self).unacquirePtr();
	}
	static jboolean tracing_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toTracing(self).isValidPtr();
	}
	static jboolean tracing_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toTracing(self).isOwnerPtr();
	}
	static jboolean tracing_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toTracing(self).isConstPtr();
	}
	static jint tracing_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toTracing(self).getCountPtr();
	}
	static jlong tracing_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toTracing(self).getInternalPtr();
	}
	static jint tracing_get_platform(TS_JNI_ARGS, jlong self) {
		return toTracing(self).getPlatform();
	}
	static jstring tracing_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTracing(self).getPlatformName());
	}
	static jint tracing_get_index(TS_JNI_ARGS, jlong self) {
		return toTracing(self).getIndex();
	}
	static void tracing_clear(TS_JNI_ARGS, jlong self) {
		toTracing(self).clear();
	}
	static jboolean tracing_is_created(TS_JNI_ARGS, jlong self) {
		return toTracing(self).isCreated();
	}
	static jboolean tracing_is_built(TS_JNI_ARGS, jlong self) {
		return toTracing(self).isBuilt();
	}
	static void tracing_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toTracing(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring tracing_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTracing(self).getName().get());
	}
	static jboolean tracing_create(TS_JNI_ARGS, jlong self, jint type, jint flags) {
		return toTracing(self).create((Tracing::Type)type, (Tracing::Flags)flags);
	}
	static jint tracing_get_type(TS_JNI_ARGS, jlong self) {
		return toTracing(self).getType();
	}
	static jstring tracing_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(Tracing::getTypeName((Tracing::Type)type));
	}
	static jstring tracing_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTracing(self).getTypeName());
	}
	static jboolean tracing_is_instance_type(TS_JNI_ARGS, jlong self) {
		return toTracing(self).isInstanceType();
	}
	static jboolean tracing_is_triangle_type(TS_JNI_ARGS, jlong self) {
		return toTracing(self).isTriangleType();
	}
	static jboolean tracing_is_bound_type(TS_JNI_ARGS, jlong self) {
		return toTracing(self).isBoundType();
	}
	static jboolean tracing_is_geometry_type(TS_JNI_ARGS, jlong self) {
		return toTracing(self).isGeometryType();
	}
	static void tracing_set_parameters(TS_JNI_ARGS, jlong self, jlong tracing) {
		toTracing(self).setParameters(toTracing(tracing));
	}
	static jint tracing_get_num_geometries(TS_JNI_ARGS, jlong self) {
		return toTracing(self).getNumGeometries();
	}
	static void tracing_set_instance_buffer(TS_JNI_ARGS, jlong self, jint num_instances, jlong buffer, jlong offset) {
		toTracing(self).setInstanceBuffer((uint32_t)num_instances, toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_instance_buffer_1(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset) {
		toTracing(self).setInstanceBuffer(toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_num_instances(TS_JNI_ARGS, jlong self, jint num_instances) {
		toTracing(self).setNumInstances((uint32_t)num_instances);
	}
	static jint tracing_get_num_instances(TS_JNI_ARGS, jlong self) {
		return toTracing(self).getNumInstances();
	}
	static jlong tracing_get_instance_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toTracing(self).getInstanceBuffer());
	}
	static jlong tracing_get_instance_offset(TS_JNI_ARGS, jlong self) {
		return (jlong)toTracing(self).getInstanceOffset();
	}
	static void tracing_set_indirect_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset) {
		toTracing(self).setIndirectBuffer(toBuffer(buffer), (size_t)offset);
	}
	static jlong tracing_get_indirect_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toTracing(self).getIndirectBuffer());
	}
	static jlong tracing_get_indirect_offset(TS_JNI_ARGS, jlong self) {
		return (jlong)toTracing(self).getIndirectOffset();
	}
	static jint tracing_add_vertex_buffer(TS_JNI_ARGS, jlong self, jint num_vertices, jint format, jlong stride, jlong buffer, jlong offset) {
		return toTracing(self).addVertexBuffer((uint32_t)num_vertices, (Format)format, (size_t)stride, toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_vertex_buffer(TS_JNI_ARGS, jlong self, jint index, jint num_vertices, jlong buffer, jlong offset) {
		toTracing(self).setVertexBuffer((uint32_t)index, (uint32_t)num_vertices, toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_vertex_buffer_1(TS_JNI_ARGS, jlong self, jint index, jlong buffer, jlong offset) {
		toTracing(self).setVertexBuffer((uint32_t)index, toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_num_vertices(TS_JNI_ARGS, jlong self, jint index, jint num_vertices) {
		toTracing(self).setNumVertices((uint32_t)index, (uint32_t)num_vertices);
	}
	static jint tracing_get_num_vertices(TS_JNI_ARGS, jlong self, jint index) {
		return toTracing(self).getNumVertices((uint32_t)index);
	}
	static jint tracing_get_vertex_format(TS_JNI_ARGS, jlong self, jint index) {
		return toTracing(self).getVertexFormat((uint32_t)index);
	}
	static jint tracing_get_vertex_stride(TS_JNI_ARGS, jlong self, jint index) {
		return toTracing(self).getVertexStride((uint32_t)index);
	}
	static jlong tracing_get_vertex_buffer(TS_JNI_ARGS, jlong self, jint index) {
		return newBuffer(toTracing(self).getVertexBuffer((uint32_t)index));
	}
	static jlong tracing_get_vertex_offset(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toTracing(self).getVertexOffset((uint32_t)index);
	}
	static jint tracing_add_index_buffer(TS_JNI_ARGS, jlong self, jint num_indices, jint format, jlong buffer, jlong offset) {
		return toTracing(self).addIndexBuffer((uint32_t)num_indices, (Format)format, toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_index_buffer(TS_JNI_ARGS, jlong self, jint index, jint num_indices, jlong buffer, jlong offset) {
		toTracing(self).setIndexBuffer((uint32_t)index, (uint32_t)num_indices, toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_index_buffer_1(TS_JNI_ARGS, jlong self, jint index, jlong buffer, jlong offset) {
		toTracing(self).setIndexBuffer((uint32_t)index, toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_num_indices(TS_JNI_ARGS, jlong self, jint index, jint num_indices) {
		toTracing(self).setNumIndices((uint32_t)index, (uint32_t)num_indices);
	}
	static jint tracing_get_num_indices(TS_JNI_ARGS, jlong self, jint index) {
		return toTracing(self).getNumIndices((uint32_t)index);
	}
	static jint tracing_get_index_format(TS_JNI_ARGS, jlong self, jint index) {
		return toTracing(self).getIndexFormat((uint32_t)index);
	}
	static jlong tracing_get_index_buffer(TS_JNI_ARGS, jlong self, jint index) {
		return newBuffer(toTracing(self).getIndexBuffer((uint32_t)index));
	}
	static jlong tracing_get_index_offset(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toTracing(self).getIndexOffset((uint32_t)index);
	}
	static jint tracing_add_bound_buffer(TS_JNI_ARGS, jlong self, jint num_bounds, jlong stride, jlong buffer, jlong offset) {
		return toTracing(self).addBoundBuffer((uint32_t)num_bounds, (size_t)stride, toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_bound_buffer(TS_JNI_ARGS, jlong self, jint index, jint num_bounds, jlong buffer, jlong offset) {
		toTracing(self).setBoundBuffer((uint32_t)index, (uint32_t)num_bounds, toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_bound_buffer_1(TS_JNI_ARGS, jlong self, jint index, jlong buffer, jlong offset) {
		toTracing(self).setBoundBuffer((uint32_t)index, toBuffer(buffer), (size_t)offset);
	}
	static void tracing_set_num_bounds(TS_JNI_ARGS, jlong self, jint index, jint num_bounds) {
		toTracing(self).setNumBounds((uint32_t)index, (uint32_t)num_bounds);
	}
	static jint tracing_get_num_bounds(TS_JNI_ARGS, jlong self, jint index) {
		return toTracing(self).getNumBounds((uint32_t)index);
	}
	static jint tracing_get_bound_stride(TS_JNI_ARGS, jlong self, jint index) {
		return toTracing(self).getBoundStride((uint32_t)index);
	}
	static jlong tracing_get_bound_buffer(TS_JNI_ARGS, jlong self, jint index) {
		return newBuffer(toTracing(self).getBoundBuffer((uint32_t)index));
	}
	static jlong tracing_get_bound_offset(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toTracing(self).getBoundOffset((uint32_t)index);
	}
	static jstring tracing_get_description(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTracing(self).getDescription().get());
	}
	static jlong tracing_get_tracing_address(TS_JNI_ARGS, jlong self) {
		return (jlong)toTracing(self).getTracingAddress();
	}
	static jlong tracing_get_build_size(TS_JNI_ARGS, jlong self) {
		return (jlong)toTracing(self).getBuildSize();
	}
	static jlong tracing_get_update_size(TS_JNI_ARGS, jlong self) {
		return (jlong)toTracing(self).getUpdateSize();
	}
	static jlong tracing_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toTracing(self).getMemory();
	}
	static const JNINativeMethod tracing_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)tracing_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)tracing_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)tracing_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)tracing_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)tracing_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)tracing_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)tracing_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)tracing_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)tracing_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)tracing_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)tracing_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)tracing_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)tracing_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)tracing_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)tracing_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)tracing_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)tracing_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)tracing_is_created },
		{ (char*)"is_built", (char*)"(J)Z", (void*)tracing_is_built },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)tracing_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)tracing_get_name },
		{ (char*)"create_", (char*)"(JII)Z", (void*)tracing_create },
		{ (char*)"get_type", (char*)"(J)I", (void*)tracing_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)tracing_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)tracing_get_type_name_1 },
		{ (char*)"is_instance_type", (char*)"(J)Z", (void*)tracing_is_instance_type },
		{ (char*)"is_triangle_type", (char*)"(J)Z", (void*)tracing_is_triangle_type },
		{ (char*)"is_bound_type", (char*)"(J)Z", (void*)tracing_is_bound_type },
		{ (char*)"is_geometry_type", (char*)"(J)Z", (void*)tracing_is_geometry_type },
		{ (char*)"set_parameters", (char*)"(JJ)V", (void*)tracing_set_parameters },
		{ (char*)"get_num_geometries", (char*)"(J)I", (void*)tracing_get_num_geometries },
		{ (char*)"set_instance_buffer", (char*)"(JIJJ)V", (void*)tracing_set_instance_buffer },
		{ (char*)"set_instance_buffer_1", (char*)"(JJJ)V", (void*)tracing_set_instance_buffer_1 },
		{ (char*)"set_num_instances", (char*)"(JI)V", (void*)tracing_set_num_instances },
		{ (char*)"get_num_instances", (char*)"(J)I", (void*)tracing_get_num_instances },
		{ (char*)"get_instance_buffer", (char*)"(J)J", (void*)tracing_get_instance_buffer },
		{ (char*)"get_instance_offset", (char*)"(J)J", (void*)tracing_get_instance_offset },
		{ (char*)"set_indirect_buffer", (char*)"(JJJ)V", (void*)tracing_set_indirect_buffer },
		{ (char*)"get_indirect_buffer", (char*)"(J)J", (void*)tracing_get_indirect_buffer },
		{ (char*)"get_indirect_offset", (char*)"(J)J", (void*)tracing_get_indirect_offset },
		{ (char*)"add_vertex_buffer", (char*)"(JIIJJJ)I", (void*)tracing_add_vertex_buffer },
		{ (char*)"set_vertex_buffer", (char*)"(JIIJJ)V", (void*)tracing_set_vertex_buffer },
		{ (char*)"set_vertex_buffer_1", (char*)"(JIJJ)V", (void*)tracing_set_vertex_buffer_1 },
		{ (char*)"set_num_vertices", (char*)"(JII)V", (void*)tracing_set_num_vertices },
		{ (char*)"get_num_vertices", (char*)"(JI)I", (void*)tracing_get_num_vertices },
		{ (char*)"get_vertex_format", (char*)"(JI)I", (void*)tracing_get_vertex_format },
		{ (char*)"get_vertex_stride", (char*)"(JI)I", (void*)tracing_get_vertex_stride },
		{ (char*)"get_vertex_buffer", (char*)"(JI)J", (void*)tracing_get_vertex_buffer },
		{ (char*)"get_vertex_offset", (char*)"(JI)J", (void*)tracing_get_vertex_offset },
		{ (char*)"add_index_buffer", (char*)"(JIIJJ)I", (void*)tracing_add_index_buffer },
		{ (char*)"set_index_buffer", (char*)"(JIIJJ)V", (void*)tracing_set_index_buffer },
		{ (char*)"set_index_buffer_1", (char*)"(JIJJ)V", (void*)tracing_set_index_buffer_1 },
		{ (char*)"set_num_indices", (char*)"(JII)V", (void*)tracing_set_num_indices },
		{ (char*)"get_num_indices", (char*)"(JI)I", (void*)tracing_get_num_indices },
		{ (char*)"get_index_format", (char*)"(JI)I", (void*)tracing_get_index_format },
		{ (char*)"get_index_buffer", (char*)"(JI)J", (void*)tracing_get_index_buffer },
		{ (char*)"get_index_offset", (char*)"(JI)J", (void*)tracing_get_index_offset },
		{ (char*)"add_bound_buffer", (char*)"(JIJJJ)I", (void*)tracing_add_bound_buffer },
		{ (char*)"set_bound_buffer", (char*)"(JIIJJ)V", (void*)tracing_set_bound_buffer },
		{ (char*)"set_bound_buffer_1", (char*)"(JIJJ)V", (void*)tracing_set_bound_buffer_1 },
		{ (char*)"set_num_bounds", (char*)"(JII)V", (void*)tracing_set_num_bounds },
		{ (char*)"get_num_bounds", (char*)"(JI)I", (void*)tracing_get_num_bounds },
		{ (char*)"get_bound_stride", (char*)"(JI)I", (void*)tracing_get_bound_stride },
		{ (char*)"get_bound_buffer", (char*)"(JI)J", (void*)tracing_get_bound_buffer },
		{ (char*)"get_bound_offset", (char*)"(JI)J", (void*)tracing_get_bound_offset },
		{ (char*)"get_description", (char*)"(J)Ljava/lang/String;", (void*)tracing_get_description },
		{ (char*)"get_tracing_address", (char*)"(J)J", (void*)tracing_get_tracing_address },
		{ (char*)"get_build_size", (char*)"(J)J", (void*)tracing_get_build_size },
		{ (char*)"get_update_size", (char*)"(J)J", (void*)tracing_get_update_size },
		{ (char*)"get_memory", (char*)"(J)J", (void*)tracing_get_memory },
	};
	
	// Tellusim::D3D12Tracing
	static jlong d3d12_tracing_new(TS_JNI_ARGS) {
		return newD3D12Tracing();
	}
	static void d3d12_tracing_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Tracing*)self;
	}
	static jboolean d3d12_tracing_equal_tracing_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Tracing(self).operator==(toTracing(base));
	}
	static jlong d3d12_tracing_cast_tracing_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Tracing(toTracing(self));
	}
	static jlong d3d12_tracing_base_tracing_ptr(TS_JNI_ARGS, jlong self) {
		return newTracing(toD3D12Tracing(self).getTracing());
	}
	static jlong d3d12_tracing_get_geometry_desc(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toD3D12Tracing(self).getGeometryDesc((uint32_t)index);
	}
	static jlong d3d12_tracing_get_build_inputs(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Tracing(self).getBuildInputs();
	}
	static jlong d3d12_tracing_get_prebuild_info(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Tracing(self).getPrebuildInfo();
	}
	static jlong d3d12_tracing_get_build_desc(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Tracing(self).getBuildDesc();
	}
	static jlong d3d12_tracing_get_tracing_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toD3D12Tracing(self).getTracingBuffer());
	}
	static jlong d3d12_tracing_get_shader_resource_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Tracing(self).getShaderResourceView();
	}
	static const JNINativeMethod d3d12_tracing_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_tracing_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_tracing_delete },
		{ (char*)"equal_tracing_ptr", (char*)"(JJ)Z", (void*)d3d12_tracing_equal_tracing_ptr },
		{ (char*)"cast_tracing_ptr", (char*)"(J)J", (void*)d3d12_tracing_cast_tracing_ptr },
		{ (char*)"base_tracing_ptr", (char*)"(J)J", (void*)d3d12_tracing_base_tracing_ptr },
		{ (char*)"get_geometry_desc", (char*)"(JI)J", (void*)d3d12_tracing_get_geometry_desc },
		{ (char*)"get_build_inputs", (char*)"(J)J", (void*)d3d12_tracing_get_build_inputs },
		{ (char*)"get_prebuild_info", (char*)"(J)J", (void*)d3d12_tracing_get_prebuild_info },
		{ (char*)"get_build_desc", (char*)"(J)J", (void*)d3d12_tracing_get_build_desc },
		{ (char*)"get_tracing_buffer", (char*)"(J)J", (void*)d3d12_tracing_get_tracing_buffer },
		{ (char*)"get_shader_resource_view", (char*)"(J)J", (void*)d3d12_tracing_get_shader_resource_view },
	};
	
	// Tellusim::MTLTracing
	static jlong mtl_tracing_new(TS_JNI_ARGS) {
		return newMTLTracing();
	}
	static void mtl_tracing_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLTracing*)self;
	}
	static jboolean mtl_tracing_equal_tracing_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLTracing(self).operator==(toTracing(base));
	}
	static jlong mtl_tracing_cast_tracing_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLTracing(toTracing(self));
	}
	static jlong mtl_tracing_base_tracing_ptr(TS_JNI_ARGS, jlong self) {
		return newTracing(toMTLTracing(self).getTracing());
	}
	static jlong mtl_tracing_get_geometry_desc(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toMTLTracing(self).getGeometryDesc((uint32_t)index);
	}
	static jlong mtl_tracing_get_primitive_desc(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLTracing(self).getPrimitiveDesc();
	}
	static jlong mtl_tracing_get_instance_desc(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLTracing(self).getInstanceDesc();
	}
	static jlong mtl_tracing_get_acceleration_structure(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLTracing(self).getAccelerationStructure();
	}
	static const JNINativeMethod mtl_tracing_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_tracing_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_tracing_delete },
		{ (char*)"equal_tracing_ptr", (char*)"(JJ)Z", (void*)mtl_tracing_equal_tracing_ptr },
		{ (char*)"cast_tracing_ptr", (char*)"(J)J", (void*)mtl_tracing_cast_tracing_ptr },
		{ (char*)"base_tracing_ptr", (char*)"(J)J", (void*)mtl_tracing_base_tracing_ptr },
		{ (char*)"get_geometry_desc", (char*)"(JI)J", (void*)mtl_tracing_get_geometry_desc },
		{ (char*)"get_primitive_desc", (char*)"(J)J", (void*)mtl_tracing_get_primitive_desc },
		{ (char*)"get_instance_desc", (char*)"(J)J", (void*)mtl_tracing_get_instance_desc },
		{ (char*)"get_acceleration_structure", (char*)"(J)J", (void*)mtl_tracing_get_acceleration_structure },
	};
	
	// Tellusim::VKTracing
	static jlong vk_tracing_new(TS_JNI_ARGS) {
		return newVKTracing();
	}
	static void vk_tracing_delete(TS_JNI_ARGS, jlong self) {
		delete (VKTracing*)self;
	}
	static jboolean vk_tracing_equal_tracing_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKTracing(self).operator==(toTracing(base));
	}
	static jlong vk_tracing_cast_tracing_ptr(TS_JNI_ARGS, jlong self) {
		return newVKTracing(toTracing(self));
	}
	static jlong vk_tracing_base_tracing_ptr(TS_JNI_ARGS, jlong self) {
		return newTracing(toVKTracing(self).getTracing());
	}
	static jlong vk_tracing_get_build_geometry_info(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKTracing(self).getBuildGeometryInfo();
	}
	static jlong vk_tracing_get_build_size_info(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKTracing(self).getBuildSizeInfo();
	}
	static jlong vk_tracing_get_tracing_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toVKTracing(self).getTracingBuffer());
	}
	static jlong vk_tracing_get_acceleration_structure(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKTracing(self).getAccelerationStructure();
	}
	static const JNINativeMethod vk_tracing_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_tracing_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_tracing_delete },
		{ (char*)"equal_tracing_ptr", (char*)"(JJ)Z", (void*)vk_tracing_equal_tracing_ptr },
		{ (char*)"cast_tracing_ptr", (char*)"(J)J", (void*)vk_tracing_cast_tracing_ptr },
		{ (char*)"base_tracing_ptr", (char*)"(J)J", (void*)vk_tracing_base_tracing_ptr },
		{ (char*)"get_build_geometry_info", (char*)"(J)J", (void*)vk_tracing_get_build_geometry_info },
		{ (char*)"get_build_size_info", (char*)"(J)J", (void*)vk_tracing_get_build_size_info },
		{ (char*)"get_tracing_buffer", (char*)"(J)J", (void*)vk_tracing_get_tracing_buffer },
		{ (char*)"get_acceleration_structure", (char*)"(J)J", (void*)vk_tracing_get_acceleration_structure },
	};
	
	// Tellusim::FUTracing
	static jlong fu_tracing_new(TS_JNI_ARGS) {
		return newFUTracing();
	}
	static jlong fu_tracing_new_1(TS_JNI_ARGS, jlongArray tracings, jboolean owner) {
		Array<Tracing> tracings_((uint32_t)env->GetArrayLength(tracings));
		jlong *tracings__ = env->GetLongArrayElements(tracings, nullptr);
		for(uint32_t i = 0; i < tracings_.size(); i++) tracings_[i] = toTracing(tracings__[i]);
		jlong ret_ = newFUTracing(tracings_, (bool)owner);
		if(tracings__) env->ReleaseLongArrayElements(tracings, tracings__, 0);
		return ret_;
	}
	static void fu_tracing_delete(TS_JNI_ARGS, jlong self) {
		delete (FUTracing*)self;
	}
	static jboolean fu_tracing_equal_tracing_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUTracing(self).operator==(toTracing(base));
	}
	static jlong fu_tracing_cast_tracing_ptr(TS_JNI_ARGS, jlong self) {
		return newFUTracing(toTracing(self));
	}
	static jlong fu_tracing_base_tracing_ptr(TS_JNI_ARGS, jlong self) {
		return newTracing(toFUTracing(self).getTracing());
	}
	static void fu_tracing_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUTracing(self).setMask((uint32_t)mask);
	}
	static jint fu_tracing_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUTracing(self).getMask();
	}
	static jint fu_tracing_get_num_tracings(TS_JNI_ARGS, jlong self) {
		return toFUTracing(self).getNumTracings();
	}
	static jlong fu_tracing_get_tracing(TS_JNI_ARGS, jlong self, jint index) {
		return newTracing(toFUTracing(self).getTracing((uint32_t)index));
	}
	static jlong fu_tracing_get_tracing_1(TS_JNI_ARGS, jlong self, jint index) {
		return newTracing(toFUTracing(self).getTracing((uint32_t)index));
	}
	static const JNINativeMethod fu_tracing_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_tracing_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_tracing_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_tracing_delete },
		{ (char*)"equal_tracing_ptr", (char*)"(JJ)Z", (void*)fu_tracing_equal_tracing_ptr },
		{ (char*)"cast_tracing_ptr", (char*)"(J)J", (void*)fu_tracing_cast_tracing_ptr },
		{ (char*)"base_tracing_ptr", (char*)"(J)J", (void*)fu_tracing_base_tracing_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_tracing_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_tracing_get_mask },
		{ (char*)"get_num_tracings", (char*)"(J)I", (void*)fu_tracing_get_num_tracings },
		{ (char*)"get_tracing", (char*)"(JI)J", (void*)fu_tracing_get_tracing },
		{ (char*)"get_tracing_1", (char*)"(JI)J", (void*)fu_tracing_get_tracing_1 },
	};
	
	// Tellusim::Target
	static jlong target_new(TS_JNI_ARGS) {
		return newTarget();
	}
	static void target_delete(TS_JNI_ARGS, jlong self) {
		delete (Target*)self;
	}
	static jboolean target_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toTarget(self) == toTarget(ptr));
	}
	static jlong target_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newTarget(toTarget(self).clonePtr());
	}
	static void target_clear_ptr(TS_JNI_ARGS, jlong self) {
		toTarget(self).clearPtr();
	}
	static void target_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toTarget(self).destroyPtr();
	}
	static void target_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toTarget(self).acquirePtr();
	}
	static void target_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toTarget(self).unacquirePtr();
	}
	static jboolean target_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toTarget(self).isValidPtr();
	}
	static jboolean target_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toTarget(self).isOwnerPtr();
	}
	static jboolean target_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toTarget(self).isConstPtr();
	}
	static jint target_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getCountPtr();
	}
	static jlong target_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toTarget(self).getInternalPtr();
	}
	static jint target_get_platform(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getPlatform();
	}
	static jstring target_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTarget(self).getPlatformName());
	}
	static jint target_get_index(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getIndex();
	}
	static jboolean target_begin(TS_JNI_ARGS, jlong self, jlong fence) {
		return toTarget(self).begin(toFence(fence));
	}
	static jboolean target_begin_1(TS_JNI_ARGS, jlong self) {
		return toTarget(self).begin();
	}
	static void target_end(TS_JNI_ARGS, jlong self, jlong fence) {
		toTarget(self).end(toFence(fence));
	}
	static void target_end_1(TS_JNI_ARGS, jlong self) {
		toTarget(self).end();
	}
	static void target_swap(TS_JNI_ARGS, jlong self, jlong surface) {
		toTarget(self).swap(toSurface(surface));
	}
	static jboolean target_is_enabled(TS_JNI_ARGS, jlong self) {
		return toTarget(self).isEnabled();
	}
	static jint target_get_color_format(TS_JNI_ARGS, jlong self, jint index) {
		return toTarget(self).getColorFormat((uint32_t)index);
	}
	static jint target_get_depth_format(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getDepthFormat();
	}
	static jint target_get_multisample(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getMultisample();
	}
	static jboolean target_has_multisample(TS_JNI_ARGS, jlong self) {
		return toTarget(self).hasMultisample();
	}
	static jboolean target_is_flipped(TS_JNI_ARGS, jlong self) {
		return toTarget(self).isFlipped();
	}
	static jboolean target_is_atomic(TS_JNI_ARGS, jlong self) {
		return toTarget(self).isAtomic();
	}
	static jint target_get_width(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getWidth();
	}
	static jint target_get_height(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getHeight();
	}
	static jint target_get_depth(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getDepth();
	}
	static jint target_get_faces(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getFaces();
	}
	static jint target_get_layers(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getLayers();
	}
	static jint target_get_mipmaps(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getMipmaps();
	}
	static void target_set_clear_color(TS_JNI_ARGS, jlong self, jlong color) {
		toTarget(self).setClearColor(toColor(color));
	}
	static void target_set_clear_color_1(TS_JNI_ARGS, jlong self, jint index, jlong color) {
		toTarget(self).setClearColor((uint32_t)index, toColor(color));
	}
	static void target_set_clear_color_2(TS_JNI_ARGS, jlong self, jfloat r, jfloat g, jfloat b, jfloat a) {
		toTarget(self).setClearColor(r, g, b, a);
	}
	static void target_set_clear_color_3(TS_JNI_ARGS, jlong self, jint index, jfloat r, jfloat g, jfloat b, jfloat a) {
		toTarget(self).setClearColor((uint32_t)index, r, g, b, a);
	}
	static void target_set_color_texture(TS_JNI_ARGS, jlong self, jlong texture, jint op, jlong slice) {
		toTarget(self).setColorTexture(toTexture(texture), (Target::Operation)op, toSlice(slice));
	}
	static void target_set_color_texture_1(TS_JNI_ARGS, jlong self, jint index, jlong texture, jint op, jlong slice) {
		toTarget(self).setColorTexture((uint32_t)index, toTexture(texture), (Target::Operation)op, toSlice(slice));
	}
	static void target_set_color_resolve(TS_JNI_ARGS, jlong self, jlong texture, jlong slice) {
		toTarget(self).setColorResolve(toTexture(texture), toSlice(slice));
	}
	static void target_set_color_resolve_1(TS_JNI_ARGS, jlong self, jint index, jlong texture, jlong slice) {
		toTarget(self).setColorResolve((uint32_t)index, toTexture(texture), toSlice(slice));
	}
	static jint target_get_num_targets(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getNumTargets();
	}
	static jlong target_get_clear_color(TS_JNI_ARGS, jlong self, jint index) {
		return newColor(toTarget(self).getClearColor((uint32_t)index));
	}
	static jint target_get_color_op(TS_JNI_ARGS, jlong self, jint index) {
		return toTarget(self).getColorOp((uint32_t)index);
	}
	static jlong target_get_color_texture(TS_JNI_ARGS, jlong self, jint index) {
		return newTexture(toTarget(self).getColorTexture((uint32_t)index));
	}
	static jlong target_get_color_resolve(TS_JNI_ARGS, jlong self, jint index) {
		return newTexture(toTarget(self).getColorResolve((uint32_t)index));
	}
	static jlong target_get_color_texture_slice(TS_JNI_ARGS, jlong self, jint index) {
		return newSlice(toTarget(self).getColorTextureSlice((uint32_t)index));
	}
	static jlong target_get_color_resolve_slice(TS_JNI_ARGS, jlong self, jint index) {
		return newSlice(toTarget(self).getColorResolveSlice((uint32_t)index));
	}
	static void target_set_clear_depth(TS_JNI_ARGS, jlong self, jfloat depth, jint stencil) {
		toTarget(self).setClearDepth(depth, (uint32_t)stencil);
	}
	static void target_set_depth_texture(TS_JNI_ARGS, jlong self, jlong texture, jint op, jlong slice) {
		toTarget(self).setDepthTexture(toTexture(texture), (Target::Operation)op, toSlice(slice));
	}
	static void target_set_depth_resolve(TS_JNI_ARGS, jlong self, jlong texture, jlong slice) {
		toTarget(self).setDepthResolve(toTexture(texture), toSlice(slice));
	}
	static jfloat target_get_clear_depth(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getClearDepth();
	}
	static jint target_get_clear_stencil(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getClearStencil();
	}
	static jint target_get_depth_op(TS_JNI_ARGS, jlong self) {
		return toTarget(self).getDepthOp();
	}
	static jlong target_get_depth_texture(TS_JNI_ARGS, jlong self) {
		return newTexture(toTarget(self).getDepthTexture());
	}
	static jlong target_get_depth_resolve(TS_JNI_ARGS, jlong self) {
		return newTexture(toTarget(self).getDepthResolve());
	}
	static jlong target_get_depth_texture_slice(TS_JNI_ARGS, jlong self) {
		return newSlice(toTarget(self).getDepthTextureSlice());
	}
	static jlong target_get_depth_resolve_slice(TS_JNI_ARGS, jlong self) {
		return newSlice(toTarget(self).getDepthResolveSlice());
	}
	static const JNINativeMethod target_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)target_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)target_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)target_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)target_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)target_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)target_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)target_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)target_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)target_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)target_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)target_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)target_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)target_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)target_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)target_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)target_get_index },
		{ (char*)"begin_", (char*)"(JJ)Z", (void*)target_begin },
		{ (char*)"begin_1", (char*)"(J)Z", (void*)target_begin_1 },
		{ (char*)"end_", (char*)"(JJ)V", (void*)target_end },
		{ (char*)"end_1", (char*)"(J)V", (void*)target_end_1 },
		{ (char*)"swap_", (char*)"(JJ)V", (void*)target_swap },
		{ (char*)"is_enabled", (char*)"(J)Z", (void*)target_is_enabled },
		{ (char*)"get_color_format", (char*)"(JI)I", (void*)target_get_color_format },
		{ (char*)"get_depth_format", (char*)"(J)I", (void*)target_get_depth_format },
		{ (char*)"get_multisample", (char*)"(J)I", (void*)target_get_multisample },
		{ (char*)"has_multisample", (char*)"(J)Z", (void*)target_has_multisample },
		{ (char*)"is_flipped", (char*)"(J)Z", (void*)target_is_flipped },
		{ (char*)"is_atomic", (char*)"(J)Z", (void*)target_is_atomic },
		{ (char*)"get_width", (char*)"(J)I", (void*)target_get_width },
		{ (char*)"get_height", (char*)"(J)I", (void*)target_get_height },
		{ (char*)"get_depth", (char*)"(J)I", (void*)target_get_depth },
		{ (char*)"get_faces", (char*)"(J)I", (void*)target_get_faces },
		{ (char*)"get_layers", (char*)"(J)I", (void*)target_get_layers },
		{ (char*)"get_mipmaps", (char*)"(J)I", (void*)target_get_mipmaps },
		{ (char*)"set_clear_color", (char*)"(JJ)V", (void*)target_set_clear_color },
		{ (char*)"set_clear_color_1", (char*)"(JIJ)V", (void*)target_set_clear_color_1 },
		{ (char*)"set_clear_color_2", (char*)"(JFFFF)V", (void*)target_set_clear_color_2 },
		{ (char*)"set_clear_color_3", (char*)"(JIFFFF)V", (void*)target_set_clear_color_3 },
		{ (char*)"set_color_texture", (char*)"(JJIJ)V", (void*)target_set_color_texture },
		{ (char*)"set_color_texture_1", (char*)"(JIJIJ)V", (void*)target_set_color_texture_1 },
		{ (char*)"set_color_resolve", (char*)"(JJJ)V", (void*)target_set_color_resolve },
		{ (char*)"set_color_resolve_1", (char*)"(JIJJ)V", (void*)target_set_color_resolve_1 },
		{ (char*)"get_num_targets", (char*)"(J)I", (void*)target_get_num_targets },
		{ (char*)"get_clear_color", (char*)"(JI)J", (void*)target_get_clear_color },
		{ (char*)"get_color_op", (char*)"(JI)I", (void*)target_get_color_op },
		{ (char*)"get_color_texture", (char*)"(JI)J", (void*)target_get_color_texture },
		{ (char*)"get_color_resolve", (char*)"(JI)J", (void*)target_get_color_resolve },
		{ (char*)"get_color_texture_slice", (char*)"(JI)J", (void*)target_get_color_texture_slice },
		{ (char*)"get_color_resolve_slice", (char*)"(JI)J", (void*)target_get_color_resolve_slice },
		{ (char*)"set_clear_depth", (char*)"(JFI)V", (void*)target_set_clear_depth },
		{ (char*)"set_depth_texture", (char*)"(JJIJ)V", (void*)target_set_depth_texture },
		{ (char*)"set_depth_resolve", (char*)"(JJJ)V", (void*)target_set_depth_resolve },
		{ (char*)"get_clear_depth", (char*)"(J)F", (void*)target_get_clear_depth },
		{ (char*)"get_clear_stencil", (char*)"(J)I", (void*)target_get_clear_stencil },
		{ (char*)"get_depth_op", (char*)"(J)I", (void*)target_get_depth_op },
		{ (char*)"get_depth_texture", (char*)"(J)J", (void*)target_get_depth_texture },
		{ (char*)"get_depth_resolve", (char*)"(J)J", (void*)target_get_depth_resolve },
		{ (char*)"get_depth_texture_slice", (char*)"(J)J", (void*)target_get_depth_texture_slice },
		{ (char*)"get_depth_resolve_slice", (char*)"(J)J", (void*)target_get_depth_resolve_slice },
	};
	
	// Tellusim::D3D12Target
	static jlong d3d12_target_new(TS_JNI_ARGS) {
		return newD3D12Target();
	}
	static void d3d12_target_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Target*)self;
	}
	static jboolean d3d12_target_equal_target_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Target(self).operator==(toTarget(base));
	}
	static jlong d3d12_target_cast_target_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Target(toTarget(self));
	}
	static jlong d3d12_target_base_target_ptr(TS_JNI_ARGS, jlong self) {
		return newTarget(toD3D12Target(self).getTarget());
	}
	static jlong d3d12_target_get_render_target_views(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Target(self).getRenderTargetViews();
	}
	static jlong d3d12_target_get_depth_stencil_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Target(self).getDepthStencilView();
	}
	static const JNINativeMethod d3d12_target_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_target_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_target_delete },
		{ (char*)"equal_target_ptr", (char*)"(JJ)Z", (void*)d3d12_target_equal_target_ptr },
		{ (char*)"cast_target_ptr", (char*)"(J)J", (void*)d3d12_target_cast_target_ptr },
		{ (char*)"base_target_ptr", (char*)"(J)J", (void*)d3d12_target_base_target_ptr },
		{ (char*)"get_render_target_views", (char*)"(J)J", (void*)d3d12_target_get_render_target_views },
		{ (char*)"get_depth_stencil_view", (char*)"(J)J", (void*)d3d12_target_get_depth_stencil_view },
	};
	
	// Tellusim::D3D11Target
	static jlong d3d11_target_new(TS_JNI_ARGS) {
		return newD3D11Target();
	}
	static void d3d11_target_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D11Target*)self;
	}
	static jboolean d3d11_target_equal_target_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D11Target(self).operator==(toTarget(base));
	}
	static jlong d3d11_target_cast_target_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D11Target(toTarget(self));
	}
	static jlong d3d11_target_base_target_ptr(TS_JNI_ARGS, jlong self) {
		return newTarget(toD3D11Target(self).getTarget());
	}
	static jlong d3d11_target_get_render_target_views(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Target(self).getRenderTargetViews();
	}
	static jlong d3d11_target_get_depth_stencil_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Target(self).getDepthStencilView();
	}
	static const JNINativeMethod d3d11_target_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d11_target_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d11_target_delete },
		{ (char*)"equal_target_ptr", (char*)"(JJ)Z", (void*)d3d11_target_equal_target_ptr },
		{ (char*)"cast_target_ptr", (char*)"(J)J", (void*)d3d11_target_cast_target_ptr },
		{ (char*)"base_target_ptr", (char*)"(J)J", (void*)d3d11_target_base_target_ptr },
		{ (char*)"get_render_target_views", (char*)"(J)J", (void*)d3d11_target_get_render_target_views },
		{ (char*)"get_depth_stencil_view", (char*)"(J)J", (void*)d3d11_target_get_depth_stencil_view },
	};
	
	// Tellusim::MTLTarget
	static jlong mtl_target_new(TS_JNI_ARGS) {
		return newMTLTarget();
	}
	static void mtl_target_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLTarget*)self;
	}
	static jboolean mtl_target_equal_target_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLTarget(self).operator==(toTarget(base));
	}
	static jlong mtl_target_cast_target_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLTarget(toTarget(self));
	}
	static jlong mtl_target_base_target_ptr(TS_JNI_ARGS, jlong self) {
		return newTarget(toMTLTarget(self).getTarget());
	}
	static jlong mtl_target_get_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLTarget(self).getDescriptor();
	}
	static const JNINativeMethod mtl_target_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_target_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_target_delete },
		{ (char*)"equal_target_ptr", (char*)"(JJ)Z", (void*)mtl_target_equal_target_ptr },
		{ (char*)"cast_target_ptr", (char*)"(J)J", (void*)mtl_target_cast_target_ptr },
		{ (char*)"base_target_ptr", (char*)"(J)J", (void*)mtl_target_base_target_ptr },
		{ (char*)"get_descriptor", (char*)"(J)J", (void*)mtl_target_get_descriptor },
	};
	
	// Tellusim::VKTarget
	static jlong vk_target_new(TS_JNI_ARGS) {
		return newVKTarget();
	}
	static void vk_target_delete(TS_JNI_ARGS, jlong self) {
		delete (VKTarget*)self;
	}
	static jboolean vk_target_equal_target_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKTarget(self).operator==(toTarget(base));
	}
	static jlong vk_target_cast_target_ptr(TS_JNI_ARGS, jlong self) {
		return newVKTarget(toTarget(self));
	}
	static jlong vk_target_base_target_ptr(TS_JNI_ARGS, jlong self) {
		return newTarget(toVKTarget(self).getTarget());
	}
	static jlong vk_target_get_render_pass(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKTarget(self).getRenderPass();
	}
	static jlong vk_target_get_framebuffer(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKTarget(self).getFramebuffer();
	}
	static const JNINativeMethod vk_target_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_target_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_target_delete },
		{ (char*)"equal_target_ptr", (char*)"(JJ)Z", (void*)vk_target_equal_target_ptr },
		{ (char*)"cast_target_ptr", (char*)"(J)J", (void*)vk_target_cast_target_ptr },
		{ (char*)"base_target_ptr", (char*)"(J)J", (void*)vk_target_base_target_ptr },
		{ (char*)"get_render_pass", (char*)"(J)J", (void*)vk_target_get_render_pass },
		{ (char*)"get_framebuffer", (char*)"(J)J", (void*)vk_target_get_framebuffer },
	};
	
	// Tellusim::GLTarget
	static jlong gl_target_new(TS_JNI_ARGS) {
		return newGLTarget();
	}
	static void gl_target_delete(TS_JNI_ARGS, jlong self) {
		delete (GLTarget*)self;
	}
	static jboolean gl_target_equal_target_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLTarget(self).operator==(toTarget(base));
	}
	static jlong gl_target_cast_target_ptr(TS_JNI_ARGS, jlong self) {
		return newGLTarget(toTarget(self));
	}
	static jlong gl_target_base_target_ptr(TS_JNI_ARGS, jlong self) {
		return newTarget(toGLTarget(self).getTarget());
	}
	static jint gl_target_get_framebuffer_id(TS_JNI_ARGS, jlong self) {
		return toGLTarget(self).getFramebufferID();
	}
	static const JNINativeMethod gl_target_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gl_target_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)gl_target_delete },
		{ (char*)"equal_target_ptr", (char*)"(JJ)Z", (void*)gl_target_equal_target_ptr },
		{ (char*)"cast_target_ptr", (char*)"(J)J", (void*)gl_target_cast_target_ptr },
		{ (char*)"base_target_ptr", (char*)"(J)J", (void*)gl_target_base_target_ptr },
		{ (char*)"get_framebuffer_id", (char*)"(J)I", (void*)gl_target_get_framebuffer_id },
	};
	
	// Tellusim::GLESTarget
	static jlong gles_target_new(TS_JNI_ARGS) {
		return newGLESTarget();
	}
	static void gles_target_delete(TS_JNI_ARGS, jlong self) {
		delete (GLESTarget*)self;
	}
	static jboolean gles_target_equal_target_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLESTarget(self).operator==(toTarget(base));
	}
	static jlong gles_target_cast_target_ptr(TS_JNI_ARGS, jlong self) {
		return newGLESTarget(toTarget(self));
	}
	static jlong gles_target_base_target_ptr(TS_JNI_ARGS, jlong self) {
		return newTarget(toGLESTarget(self).getTarget());
	}
	static jint gles_target_get_framebuffer_id(TS_JNI_ARGS, jlong self) {
		return toGLESTarget(self).getFramebufferID();
	}
	static const JNINativeMethod gles_target_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gles_target_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)gles_target_delete },
		{ (char*)"equal_target_ptr", (char*)"(JJ)Z", (void*)gles_target_equal_target_ptr },
		{ (char*)"cast_target_ptr", (char*)"(J)J", (void*)gles_target_cast_target_ptr },
		{ (char*)"base_target_ptr", (char*)"(J)J", (void*)gles_target_base_target_ptr },
		{ (char*)"get_framebuffer_id", (char*)"(J)I", (void*)gles_target_get_framebuffer_id },
	};
	
	// Tellusim::FUTarget
	static jlong fu_target_new(TS_JNI_ARGS) {
		return newFUTarget();
	}
	static jlong fu_target_new_1(TS_JNI_ARGS, jlongArray targets, jboolean owner) {
		Array<Target> targets_((uint32_t)env->GetArrayLength(targets));
		jlong *targets__ = env->GetLongArrayElements(targets, nullptr);
		for(uint32_t i = 0; i < targets_.size(); i++) targets_[i] = toTarget(targets__[i]);
		jlong ret_ = newFUTarget(targets_, (bool)owner);
		if(targets__) env->ReleaseLongArrayElements(targets, targets__, 0);
		return ret_;
	}
	static void fu_target_delete(TS_JNI_ARGS, jlong self) {
		delete (FUTarget*)self;
	}
	static jboolean fu_target_equal_target_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUTarget(self).operator==(toTarget(base));
	}
	static jlong fu_target_cast_target_ptr(TS_JNI_ARGS, jlong self) {
		return newFUTarget(toTarget(self));
	}
	static jlong fu_target_base_target_ptr(TS_JNI_ARGS, jlong self) {
		return newTarget(toFUTarget(self).getTarget());
	}
	static void fu_target_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUTarget(self).setMask((uint32_t)mask);
	}
	static jint fu_target_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUTarget(self).getMask();
	}
	static jint fu_target_get_num_targets(TS_JNI_ARGS, jlong self) {
		return toFUTarget(self).getNumTargets();
	}
	static jlong fu_target_get_target(TS_JNI_ARGS, jlong self, jint index) {
		return newTarget(toFUTarget(self).getTarget((uint32_t)index));
	}
	static jlong fu_target_get_target_1(TS_JNI_ARGS, jlong self, jint index) {
		return newTarget(toFUTarget(self).getTarget((uint32_t)index));
	}
	static const JNINativeMethod fu_target_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_target_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_target_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_target_delete },
		{ (char*)"equal_target_ptr", (char*)"(JJ)Z", (void*)fu_target_equal_target_ptr },
		{ (char*)"cast_target_ptr", (char*)"(J)J", (void*)fu_target_cast_target_ptr },
		{ (char*)"base_target_ptr", (char*)"(J)J", (void*)fu_target_base_target_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_target_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_target_get_mask },
		{ (char*)"get_num_targets", (char*)"(J)I", (void*)fu_target_get_num_targets },
		{ (char*)"get_target", (char*)"(JI)J", (void*)fu_target_get_target },
		{ (char*)"get_target_1", (char*)"(JI)J", (void*)fu_target_get_target_1 },
	};
	
	// Tellusim::Device::Features
	static jlong device_features_new(TS_JNI_ARGS) {
		return newDeviceFeatures();
	}
	static jlong device_features_copy(TS_JNI_ARGS, jlong self) {
		return newDeviceFeatures(toDeviceFeatures(self));
	}
	static void device_features_delete(TS_JNI_ARGS, jlong self) {
		delete (Device::Features*)self;
	}
	static void device_features_set_threadAccess(TS_JNI_ARGS, jlong self, jboolean threadAccess) {
		toDeviceFeatures(self).threadAccess = threadAccess;
	}
	static jboolean device_features_get_threadAccess(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).threadAccess;
	}
	static void device_features_set_sparseBuffer(TS_JNI_ARGS, jlong self, jboolean sparseBuffer) {
		toDeviceFeatures(self).sparseBuffer = sparseBuffer;
	}
	static jboolean device_features_get_sparseBuffer(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).sparseBuffer;
	}
	static void device_features_set_bufferTable(TS_JNI_ARGS, jlong self, jboolean bufferTable) {
		toDeviceFeatures(self).bufferTable = bufferTable;
	}
	static jboolean device_features_get_bufferTable(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).bufferTable;
	}
	static void device_features_set_sparseTexture(TS_JNI_ARGS, jlong self, jboolean sparseTexture) {
		toDeviceFeatures(self).sparseTexture = sparseTexture;
	}
	static jboolean device_features_get_sparseTexture(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).sparseTexture;
	}
	static void device_features_set_sparseArrayTexture(TS_JNI_ARGS, jlong self, jboolean sparseArrayTexture) {
		toDeviceFeatures(self).sparseArrayTexture = sparseArrayTexture;
	}
	static jboolean device_features_get_sparseArrayTexture(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).sparseArrayTexture;
	}
	static void device_features_set_cubeArrayTexture(TS_JNI_ARGS, jlong self, jboolean cubeArrayTexture) {
		toDeviceFeatures(self).cubeArrayTexture = cubeArrayTexture;
	}
	static jboolean device_features_get_cubeArrayTexture(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).cubeArrayTexture;
	}
	static void device_features_set_textureTable(TS_JNI_ARGS, jlong self, jboolean textureTable) {
		toDeviceFeatures(self).textureTable = textureTable;
	}
	static jboolean device_features_get_textureTable(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).textureTable;
	}
	static void device_features_set_baseInstanceIndex(TS_JNI_ARGS, jlong self, jboolean baseInstanceIndex) {
		toDeviceFeatures(self).baseInstanceIndex = baseInstanceIndex;
	}
	static jboolean device_features_get_baseInstanceIndex(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).baseInstanceIndex;
	}
	static void device_features_set_drawIndirectIndex(TS_JNI_ARGS, jlong self, jboolean drawIndirectIndex) {
		toDeviceFeatures(self).drawIndirectIndex = drawIndirectIndex;
	}
	static jboolean device_features_get_drawIndirectIndex(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).drawIndirectIndex;
	}
	static void device_features_set_drawIndirectCount(TS_JNI_ARGS, jlong self, jboolean drawIndirectCount) {
		toDeviceFeatures(self).drawIndirectCount = drawIndirectCount;
	}
	static jboolean device_features_get_drawIndirectCount(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).drawIndirectCount;
	}
	static void device_features_set_taskIndirectCount(TS_JNI_ARGS, jlong self, jboolean taskIndirectCount) {
		toDeviceFeatures(self).taskIndirectCount = taskIndirectCount;
	}
	static jboolean device_features_get_taskIndirectCount(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).taskIndirectCount;
	}
	static void device_features_set_vertexStorage(TS_JNI_ARGS, jlong self, jboolean vertexStorage) {
		toDeviceFeatures(self).vertexStorage = vertexStorage;
	}
	static jboolean device_features_get_vertexStorage(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).vertexStorage;
	}
	static void device_features_set_vertexIndexLayer(TS_JNI_ARGS, jlong self, jboolean vertexIndexLayer) {
		toDeviceFeatures(self).vertexIndexLayer = vertexIndexLayer;
	}
	static jboolean device_features_get_vertexIndexLayer(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).vertexIndexLayer;
	}
	static void device_features_set_geometryPassthrough(TS_JNI_ARGS, jlong self, jboolean geometryPassthrough) {
		toDeviceFeatures(self).geometryPassthrough = geometryPassthrough;
	}
	static jboolean device_features_get_geometryPassthrough(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).geometryPassthrough;
	}
	static void device_features_set_fragmentBarycentric(TS_JNI_ARGS, jlong self, jboolean fragmentBarycentric) {
		toDeviceFeatures(self).fragmentBarycentric = fragmentBarycentric;
	}
	static jboolean device_features_get_fragmentBarycentric(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).fragmentBarycentric;
	}
	static void device_features_set_fragmentStencilExport(TS_JNI_ARGS, jlong self, jboolean fragmentStencilExport) {
		toDeviceFeatures(self).fragmentStencilExport = fragmentStencilExport;
	}
	static jboolean device_features_get_fragmentStencilExport(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).fragmentStencilExport;
	}
	static void device_features_set_dualSourceBlending(TS_JNI_ARGS, jlong self, jboolean dualSourceBlending) {
		toDeviceFeatures(self).dualSourceBlending = dualSourceBlending;
	}
	static jboolean device_features_get_dualSourceBlending(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).dualSourceBlending;
	}
	static void device_features_set_depthRangeOneToOne(TS_JNI_ARGS, jlong self, jboolean depthRangeOneToOne) {
		toDeviceFeatures(self).depthRangeOneToOne = depthRangeOneToOne;
	}
	static jboolean device_features_get_depthRangeOneToOne(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).depthRangeOneToOne;
	}
	static void device_features_set_conservativeRaster(TS_JNI_ARGS, jlong self, jboolean conservativeRaster) {
		toDeviceFeatures(self).conservativeRaster = conservativeRaster;
	}
	static jboolean device_features_get_conservativeRaster(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).conservativeRaster;
	}
	static void device_features_set_conditionalRendering(TS_JNI_ARGS, jlong self, jboolean conditionalRendering) {
		toDeviceFeatures(self).conditionalRendering = conditionalRendering;
	}
	static jboolean device_features_get_conditionalRendering(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).conditionalRendering;
	}
	static void device_features_set_rayTracing(TS_JNI_ARGS, jlong self, jboolean rayTracing) {
		toDeviceFeatures(self).rayTracing = rayTracing;
	}
	static jboolean device_features_get_rayTracing(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).rayTracing;
	}
	static void device_features_set_computeTracing(TS_JNI_ARGS, jlong self, jboolean computeTracing) {
		toDeviceFeatures(self).computeTracing = computeTracing;
	}
	static jboolean device_features_get_computeTracing(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).computeTracing;
	}
	static void device_features_set_fragmentTracing(TS_JNI_ARGS, jlong self, jboolean fragmentTracing) {
		toDeviceFeatures(self).fragmentTracing = fragmentTracing;
	}
	static jboolean device_features_get_fragmentTracing(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).fragmentTracing;
	}
	static void device_features_set_indirectTracing(TS_JNI_ARGS, jlong self, jboolean indirectTracing) {
		toDeviceFeatures(self).indirectTracing = indirectTracing;
	}
	static jboolean device_features_get_indirectTracing(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).indirectTracing;
	}
	static void device_features_set_recursionDepth(TS_JNI_ARGS, jlong self, jint recursionDepth) {
		toDeviceFeatures(self).recursionDepth = recursionDepth;
	}
	static jint device_features_get_recursionDepth(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).recursionDepth;
	}
	static void device_features_set_subgroupVote(TS_JNI_ARGS, jlong self, jboolean subgroupVote) {
		toDeviceFeatures(self).subgroupVote = subgroupVote;
	}
	static jboolean device_features_get_subgroupVote(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).subgroupVote;
	}
	static void device_features_set_subgroupMath(TS_JNI_ARGS, jlong self, jboolean subgroupMath) {
		toDeviceFeatures(self).subgroupMath = subgroupMath;
	}
	static jboolean device_features_get_subgroupMath(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).subgroupMath;
	}
	static void device_features_set_subgroupShuffle(TS_JNI_ARGS, jlong self, jboolean subgroupShuffle) {
		toDeviceFeatures(self).subgroupShuffle = subgroupShuffle;
	}
	static jboolean device_features_get_subgroupShuffle(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).subgroupShuffle;
	}
	static void device_features_set_subgroupSize(TS_JNI_ARGS, jlong self, jint subgroupSize) {
		toDeviceFeatures(self).subgroupSize = subgroupSize;
	}
	static jint device_features_get_subgroupSize(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).subgroupSize;
	}
	static void device_features_set_minSubgroupSize(TS_JNI_ARGS, jlong self, jint minSubgroupSize) {
		toDeviceFeatures(self).minSubgroupSize = minSubgroupSize;
	}
	static jint device_features_get_minSubgroupSize(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).minSubgroupSize;
	}
	static void device_features_set_maxSubgroupSize(TS_JNI_ARGS, jlong self, jint maxSubgroupSize) {
		toDeviceFeatures(self).maxSubgroupSize = maxSubgroupSize;
	}
	static jint device_features_get_maxSubgroupSize(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxSubgroupSize;
	}
	static void device_features_set_shaderu8(TS_JNI_ARGS, jlong self, jboolean shaderu8) {
		toDeviceFeatures(self).shaderu8 = shaderu8;
	}
	static jboolean device_features_get_shaderu8(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).shaderu8;
	}
	static void device_features_set_shaderf16(TS_JNI_ARGS, jlong self, jboolean shaderf16) {
		toDeviceFeatures(self).shaderf16 = shaderf16;
	}
	static jboolean device_features_get_shaderf16(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).shaderf16;
	}
	static void device_features_set_shaderu16(TS_JNI_ARGS, jlong self, jboolean shaderu16) {
		toDeviceFeatures(self).shaderu16 = shaderu16;
	}
	static jboolean device_features_get_shaderu16(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).shaderu16;
	}
	static void device_features_set_shaderf64(TS_JNI_ARGS, jlong self, jboolean shaderf64) {
		toDeviceFeatures(self).shaderf64 = shaderf64;
	}
	static jboolean device_features_get_shaderf64(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).shaderf64;
	}
	static void device_features_set_shaderu64(TS_JNI_ARGS, jlong self, jboolean shaderu64) {
		toDeviceFeatures(self).shaderu64 = shaderu64;
	}
	static jboolean device_features_get_shaderu64(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).shaderu64;
	}
	static void device_features_set_atomicGroupf32(TS_JNI_ARGS, jlong self, jboolean atomicGroupf32) {
		toDeviceFeatures(self).atomicGroupf32 = atomicGroupf32;
	}
	static jboolean device_features_get_atomicGroupf32(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).atomicGroupf32;
	}
	static void device_features_set_atomicGroupu64(TS_JNI_ARGS, jlong self, jboolean atomicGroupu64) {
		toDeviceFeatures(self).atomicGroupu64 = atomicGroupu64;
	}
	static jboolean device_features_get_atomicGroupu64(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).atomicGroupu64;
	}
	static void device_features_set_atomicBufferf32(TS_JNI_ARGS, jlong self, jboolean atomicBufferf32) {
		toDeviceFeatures(self).atomicBufferf32 = atomicBufferf32;
	}
	static jboolean device_features_get_atomicBufferf32(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).atomicBufferf32;
	}
	static void device_features_set_atomicBufferu64(TS_JNI_ARGS, jlong self, jboolean atomicBufferu64) {
		toDeviceFeatures(self).atomicBufferu64 = atomicBufferu64;
	}
	static jboolean device_features_get_atomicBufferu64(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).atomicBufferu64;
	}
	static void device_features_set_atomicTexturef32(TS_JNI_ARGS, jlong self, jboolean atomicTexturef32) {
		toDeviceFeatures(self).atomicTexturef32 = atomicTexturef32;
	}
	static jboolean device_features_get_atomicTexturef32(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).atomicTexturef32;
	}
	static void device_features_set_atomicTextureu32(TS_JNI_ARGS, jlong self, jboolean atomicTextureu32) {
		toDeviceFeatures(self).atomicTextureu32 = atomicTextureu32;
	}
	static jboolean device_features_get_atomicTextureu32(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).atomicTextureu32;
	}
	static void device_features_set_atomicTextureu64(TS_JNI_ARGS, jlong self, jboolean atomicTextureu64) {
		toDeviceFeatures(self).atomicTextureu64 = atomicTextureu64;
	}
	static jboolean device_features_get_atomicTextureu64(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).atomicTextureu64;
	}
	static void device_features_set_matrix16f16(TS_JNI_ARGS, jlong self, jboolean matrix16f16) {
		toDeviceFeatures(self).matrix16f16 = matrix16f16;
	}
	static jboolean device_features_get_matrix16f16(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).matrix16f16;
	}
	static void device_features_set_matrix16x8x8f16(TS_JNI_ARGS, jlong self, jboolean matrix16x8x8f16) {
		toDeviceFeatures(self).matrix16x8x8f16 = matrix16x8x8f16;
	}
	static jboolean device_features_get_matrix16x8x8f16(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).matrix16x8x8f16;
	}
	static void device_features_set_matrix16x8x16f16(TS_JNI_ARGS, jlong self, jboolean matrix16x8x16f16) {
		toDeviceFeatures(self).matrix16x8x16f16 = matrix16x8x16f16;
	}
	static jboolean device_features_get_matrix16x8x16f16(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).matrix16x8x16f16;
	}
	static void device_features_set_matrix16f16f32(TS_JNI_ARGS, jlong self, jboolean matrix16f16f32) {
		toDeviceFeatures(self).matrix16f16f32 = matrix16f16f32;
	}
	static jboolean device_features_get_matrix16f16f32(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).matrix16f16f32;
	}
	static void device_features_set_matrix16x8x8f16f32(TS_JNI_ARGS, jlong self, jboolean matrix16x8x8f16f32) {
		toDeviceFeatures(self).matrix16x8x8f16f32 = matrix16x8x8f16f32;
	}
	static jboolean device_features_get_matrix16x8x8f16f32(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).matrix16x8x8f16f32;
	}
	static void device_features_set_matrix16x8x16f16f32(TS_JNI_ARGS, jlong self, jboolean matrix16x8x16f16f32) {
		toDeviceFeatures(self).matrix16x8x16f16f32 = matrix16x8x16f16f32;
	}
	static jboolean device_features_get_matrix16x8x16f16f32(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).matrix16x8x16f16f32;
	}
	static void device_features_set_uniformAlignment(TS_JNI_ARGS, jlong self, jint uniformAlignment) {
		toDeviceFeatures(self).uniformAlignment = uniformAlignment;
	}
	static jint device_features_get_uniformAlignment(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).uniformAlignment;
	}
	static void device_features_set_storageAlignment(TS_JNI_ARGS, jlong self, jint storageAlignment) {
		toDeviceFeatures(self).storageAlignment = storageAlignment;
	}
	static jint device_features_get_storageAlignment(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).storageAlignment;
	}
	static void device_features_set_maxTextureSamples(TS_JNI_ARGS, jlong self, jint maxTextureSamples) {
		toDeviceFeatures(self).maxTextureSamples = maxTextureSamples;
	}
	static jint device_features_get_maxTextureSamples(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxTextureSamples;
	}
	static void device_features_set_maxTexture2DSize(TS_JNI_ARGS, jlong self, jint maxTexture2DSize) {
		toDeviceFeatures(self).maxTexture2DSize = maxTexture2DSize;
	}
	static jint device_features_get_maxTexture2DSize(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxTexture2DSize;
	}
	static void device_features_set_maxTexture3DSize(TS_JNI_ARGS, jlong self, jint maxTexture3DSize) {
		toDeviceFeatures(self).maxTexture3DSize = maxTexture3DSize;
	}
	static jint device_features_get_maxTexture3DSize(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxTexture3DSize;
	}
	static void device_features_set_maxTextureLayers(TS_JNI_ARGS, jlong self, jint maxTextureLayers) {
		toDeviceFeatures(self).maxTextureLayers = maxTextureLayers;
	}
	static jint device_features_get_maxTextureLayers(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxTextureLayers;
	}
	static void device_features_set_maxGroupSizeX(TS_JNI_ARGS, jlong self, jint maxGroupSizeX) {
		toDeviceFeatures(self).maxGroupSizeX = maxGroupSizeX;
	}
	static jint device_features_get_maxGroupSizeX(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxGroupSizeX;
	}
	static void device_features_set_maxGroupSizeY(TS_JNI_ARGS, jlong self, jint maxGroupSizeY) {
		toDeviceFeatures(self).maxGroupSizeY = maxGroupSizeY;
	}
	static jint device_features_get_maxGroupSizeY(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxGroupSizeY;
	}
	static void device_features_set_maxGroupSizeZ(TS_JNI_ARGS, jlong self, jint maxGroupSizeZ) {
		toDeviceFeatures(self).maxGroupSizeZ = maxGroupSizeZ;
	}
	static jint device_features_get_maxGroupSizeZ(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxGroupSizeZ;
	}
	static void device_features_set_maxGroupCountX(TS_JNI_ARGS, jlong self, jint maxGroupCountX) {
		toDeviceFeatures(self).maxGroupCountX = maxGroupCountX;
	}
	static jint device_features_get_maxGroupCountX(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxGroupCountX;
	}
	static void device_features_set_maxGroupCountY(TS_JNI_ARGS, jlong self, jint maxGroupCountY) {
		toDeviceFeatures(self).maxGroupCountY = maxGroupCountY;
	}
	static jint device_features_get_maxGroupCountY(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxGroupCountY;
	}
	static void device_features_set_maxGroupCountZ(TS_JNI_ARGS, jlong self, jint maxGroupCountZ) {
		toDeviceFeatures(self).maxGroupCountZ = maxGroupCountZ;
	}
	static jint device_features_get_maxGroupCountZ(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxGroupCountZ;
	}
	static void device_features_set_maxTaskCount(TS_JNI_ARGS, jlong self, jint maxTaskCount) {
		toDeviceFeatures(self).maxTaskCount = maxTaskCount;
	}
	static jint device_features_get_maxTaskCount(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxTaskCount;
	}
	static void device_features_set_maxTaskMemory(TS_JNI_ARGS, jlong self, jint maxTaskMemory) {
		toDeviceFeatures(self).maxTaskMemory = maxTaskMemory;
	}
	static jint device_features_get_maxTaskMemory(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxTaskMemory;
	}
	static void device_features_set_maxTaskMeshes(TS_JNI_ARGS, jlong self, jint maxTaskMeshes) {
		toDeviceFeatures(self).maxTaskMeshes = maxTaskMeshes;
	}
	static jint device_features_get_maxTaskMeshes(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxTaskMeshes;
	}
	static void device_features_set_maxMeshMemory(TS_JNI_ARGS, jlong self, jint maxMeshMemory) {
		toDeviceFeatures(self).maxMeshMemory = maxMeshMemory;
	}
	static jint device_features_get_maxMeshMemory(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxMeshMemory;
	}
	static void device_features_set_maxMeshVertices(TS_JNI_ARGS, jlong self, jint maxMeshVertices) {
		toDeviceFeatures(self).maxMeshVertices = maxMeshVertices;
	}
	static jint device_features_get_maxMeshVertices(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxMeshVertices;
	}
	static void device_features_set_maxMeshPrimitives(TS_JNI_ARGS, jlong self, jint maxMeshPrimitives) {
		toDeviceFeatures(self).maxMeshPrimitives = maxMeshPrimitives;
	}
	static jint device_features_get_maxMeshPrimitives(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxMeshPrimitives;
	}
	static void device_features_set_maxViewportCount(TS_JNI_ARGS, jlong self, jint maxViewportCount) {
		toDeviceFeatures(self).maxViewportCount = maxViewportCount;
	}
	static jint device_features_get_maxViewportCount(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxViewportCount;
	}
	static void device_features_set_maxClipCullCount(TS_JNI_ARGS, jlong self, jint maxClipCullCount) {
		toDeviceFeatures(self).maxClipCullCount = maxClipCullCount;
	}
	static jint device_features_get_maxClipCullCount(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxClipCullCount;
	}
	static void device_features_set_maxUniformSize(TS_JNI_ARGS, jlong self, jlong maxUniformSize) {
		toDeviceFeatures(self).maxUniformSize = maxUniformSize;
	}
	static jlong device_features_get_maxUniformSize(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxUniformSize;
	}
	static void device_features_set_maxStorageSize(TS_JNI_ARGS, jlong self, jlong maxStorageSize) {
		toDeviceFeatures(self).maxStorageSize = maxStorageSize;
	}
	static jlong device_features_get_maxStorageSize(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).maxStorageSize;
	}
	static void device_features_set_groupMemory(TS_JNI_ARGS, jlong self, jint groupMemory) {
		toDeviceFeatures(self).groupMemory = groupMemory;
	}
	static jint device_features_get_groupMemory(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).groupMemory;
	}
	static void device_features_set_videoMemory(TS_JNI_ARGS, jlong self, jlong videoMemory) {
		toDeviceFeatures(self).videoMemory = videoMemory;
	}
	static jlong device_features_get_videoMemory(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).videoMemory;
	}
	static void device_features_set_vendorID(TS_JNI_ARGS, jlong self, jint vendorID) {
		toDeviceFeatures(self).vendorID = vendorID;
	}
	static jint device_features_get_vendorID(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).vendorID;
	}
	static void device_features_set_deviceID(TS_JNI_ARGS, jlong self, jint deviceID) {
		toDeviceFeatures(self).deviceID = deviceID;
	}
	static jint device_features_get_deviceID(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).deviceID;
	}
	static void device_features_set_pciBusID(TS_JNI_ARGS, jlong self, jint pciBusID) {
		toDeviceFeatures(self).pciBusID = pciBusID;
	}
	static jint device_features_get_pciBusID(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).pciBusID;
	}
	static void device_features_set_pciDomainID(TS_JNI_ARGS, jlong self, jint pciDomainID) {
		toDeviceFeatures(self).pciDomainID = pciDomainID;
	}
	static jint device_features_get_pciDomainID(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).pciDomainID;
	}
	static void device_features_set_pciDeviceID(TS_JNI_ARGS, jlong self, jint pciDeviceID) {
		toDeviceFeatures(self).pciDeviceID = pciDeviceID;
	}
	static jint device_features_get_pciDeviceID(TS_JNI_ARGS, jlong self) {
		return toDeviceFeatures(self).pciDeviceID;
	}
	static const JNINativeMethod device_features_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)device_features_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)device_features_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)device_features_delete },
		{ (char*)"set_threadAccess_", (char*)"(JZ)V", (void*)device_features_set_threadAccess },
		{ (char*)"get_threadAccess_", (char*)"(J)Z", (void*)device_features_get_threadAccess },
		{ (char*)"set_sparseBuffer_", (char*)"(JZ)V", (void*)device_features_set_sparseBuffer },
		{ (char*)"get_sparseBuffer_", (char*)"(J)Z", (void*)device_features_get_sparseBuffer },
		{ (char*)"set_bufferTable_", (char*)"(JZ)V", (void*)device_features_set_bufferTable },
		{ (char*)"get_bufferTable_", (char*)"(J)Z", (void*)device_features_get_bufferTable },
		{ (char*)"set_sparseTexture_", (char*)"(JZ)V", (void*)device_features_set_sparseTexture },
		{ (char*)"get_sparseTexture_", (char*)"(J)Z", (void*)device_features_get_sparseTexture },
		{ (char*)"set_sparseArrayTexture_", (char*)"(JZ)V", (void*)device_features_set_sparseArrayTexture },
		{ (char*)"get_sparseArrayTexture_", (char*)"(J)Z", (void*)device_features_get_sparseArrayTexture },
		{ (char*)"set_cubeArrayTexture_", (char*)"(JZ)V", (void*)device_features_set_cubeArrayTexture },
		{ (char*)"get_cubeArrayTexture_", (char*)"(J)Z", (void*)device_features_get_cubeArrayTexture },
		{ (char*)"set_textureTable_", (char*)"(JZ)V", (void*)device_features_set_textureTable },
		{ (char*)"get_textureTable_", (char*)"(J)Z", (void*)device_features_get_textureTable },
		{ (char*)"set_baseInstanceIndex_", (char*)"(JZ)V", (void*)device_features_set_baseInstanceIndex },
		{ (char*)"get_baseInstanceIndex_", (char*)"(J)Z", (void*)device_features_get_baseInstanceIndex },
		{ (char*)"set_drawIndirectIndex_", (char*)"(JZ)V", (void*)device_features_set_drawIndirectIndex },
		{ (char*)"get_drawIndirectIndex_", (char*)"(J)Z", (void*)device_features_get_drawIndirectIndex },
		{ (char*)"set_drawIndirectCount_", (char*)"(JZ)V", (void*)device_features_set_drawIndirectCount },
		{ (char*)"get_drawIndirectCount_", (char*)"(J)Z", (void*)device_features_get_drawIndirectCount },
		{ (char*)"set_taskIndirectCount_", (char*)"(JZ)V", (void*)device_features_set_taskIndirectCount },
		{ (char*)"get_taskIndirectCount_", (char*)"(J)Z", (void*)device_features_get_taskIndirectCount },
		{ (char*)"set_vertexStorage_", (char*)"(JZ)V", (void*)device_features_set_vertexStorage },
		{ (char*)"get_vertexStorage_", (char*)"(J)Z", (void*)device_features_get_vertexStorage },
		{ (char*)"set_vertexIndexLayer_", (char*)"(JZ)V", (void*)device_features_set_vertexIndexLayer },
		{ (char*)"get_vertexIndexLayer_", (char*)"(J)Z", (void*)device_features_get_vertexIndexLayer },
		{ (char*)"set_geometryPassthrough_", (char*)"(JZ)V", (void*)device_features_set_geometryPassthrough },
		{ (char*)"get_geometryPassthrough_", (char*)"(J)Z", (void*)device_features_get_geometryPassthrough },
		{ (char*)"set_fragmentBarycentric_", (char*)"(JZ)V", (void*)device_features_set_fragmentBarycentric },
		{ (char*)"get_fragmentBarycentric_", (char*)"(J)Z", (void*)device_features_get_fragmentBarycentric },
		{ (char*)"set_fragmentStencilExport_", (char*)"(JZ)V", (void*)device_features_set_fragmentStencilExport },
		{ (char*)"get_fragmentStencilExport_", (char*)"(J)Z", (void*)device_features_get_fragmentStencilExport },
		{ (char*)"set_dualSourceBlending_", (char*)"(JZ)V", (void*)device_features_set_dualSourceBlending },
		{ (char*)"get_dualSourceBlending_", (char*)"(J)Z", (void*)device_features_get_dualSourceBlending },
		{ (char*)"set_depthRangeOneToOne_", (char*)"(JZ)V", (void*)device_features_set_depthRangeOneToOne },
		{ (char*)"get_depthRangeOneToOne_", (char*)"(J)Z", (void*)device_features_get_depthRangeOneToOne },
		{ (char*)"set_conservativeRaster_", (char*)"(JZ)V", (void*)device_features_set_conservativeRaster },
		{ (char*)"get_conservativeRaster_", (char*)"(J)Z", (void*)device_features_get_conservativeRaster },
		{ (char*)"set_conditionalRendering_", (char*)"(JZ)V", (void*)device_features_set_conditionalRendering },
		{ (char*)"get_conditionalRendering_", (char*)"(J)Z", (void*)device_features_get_conditionalRendering },
		{ (char*)"set_rayTracing_", (char*)"(JZ)V", (void*)device_features_set_rayTracing },
		{ (char*)"get_rayTracing_", (char*)"(J)Z", (void*)device_features_get_rayTracing },
		{ (char*)"set_computeTracing_", (char*)"(JZ)V", (void*)device_features_set_computeTracing },
		{ (char*)"get_computeTracing_", (char*)"(J)Z", (void*)device_features_get_computeTracing },
		{ (char*)"set_fragmentTracing_", (char*)"(JZ)V", (void*)device_features_set_fragmentTracing },
		{ (char*)"get_fragmentTracing_", (char*)"(J)Z", (void*)device_features_get_fragmentTracing },
		{ (char*)"set_indirectTracing_", (char*)"(JZ)V", (void*)device_features_set_indirectTracing },
		{ (char*)"get_indirectTracing_", (char*)"(J)Z", (void*)device_features_get_indirectTracing },
		{ (char*)"set_recursionDepth_", (char*)"(JI)V", (void*)device_features_set_recursionDepth },
		{ (char*)"get_recursionDepth_", (char*)"(J)I", (void*)device_features_get_recursionDepth },
		{ (char*)"set_subgroupVote_", (char*)"(JZ)V", (void*)device_features_set_subgroupVote },
		{ (char*)"get_subgroupVote_", (char*)"(J)Z", (void*)device_features_get_subgroupVote },
		{ (char*)"set_subgroupMath_", (char*)"(JZ)V", (void*)device_features_set_subgroupMath },
		{ (char*)"get_subgroupMath_", (char*)"(J)Z", (void*)device_features_get_subgroupMath },
		{ (char*)"set_subgroupShuffle_", (char*)"(JZ)V", (void*)device_features_set_subgroupShuffle },
		{ (char*)"get_subgroupShuffle_", (char*)"(J)Z", (void*)device_features_get_subgroupShuffle },
		{ (char*)"set_subgroupSize_", (char*)"(JI)V", (void*)device_features_set_subgroupSize },
		{ (char*)"get_subgroupSize_", (char*)"(J)I", (void*)device_features_get_subgroupSize },
		{ (char*)"set_minSubgroupSize_", (char*)"(JI)V", (void*)device_features_set_minSubgroupSize },
		{ (char*)"get_minSubgroupSize_", (char*)"(J)I", (void*)device_features_get_minSubgroupSize },
		{ (char*)"set_maxSubgroupSize_", (char*)"(JI)V", (void*)device_features_set_maxSubgroupSize },
		{ (char*)"get_maxSubgroupSize_", (char*)"(J)I", (void*)device_features_get_maxSubgroupSize },
		{ (char*)"set_shaderu8_", (char*)"(JZ)V", (void*)device_features_set_shaderu8 },
		{ (char*)"get_shaderu8_", (char*)"(J)Z", (void*)device_features_get_shaderu8 },
		{ (char*)"set_shaderf16_", (char*)"(JZ)V", (void*)device_features_set_shaderf16 },
		{ (char*)"get_shaderf16_", (char*)"(J)Z", (void*)device_features_get_shaderf16 },
		{ (char*)"set_shaderu16_", (char*)"(JZ)V", (void*)device_features_set_shaderu16 },
		{ (char*)"get_shaderu16_", (char*)"(J)Z", (void*)device_features_get_shaderu16 },
		{ (char*)"set_shaderf64_", (char*)"(JZ)V", (void*)device_features_set_shaderf64 },
		{ (char*)"get_shaderf64_", (char*)"(J)Z", (void*)device_features_get_shaderf64 },
		{ (char*)"set_shaderu64_", (char*)"(JZ)V", (void*)device_features_set_shaderu64 },
		{ (char*)"get_shaderu64_", (char*)"(J)Z", (void*)device_features_get_shaderu64 },
		{ (char*)"set_atomicGroupf32_", (char*)"(JZ)V", (void*)device_features_set_atomicGroupf32 },
		{ (char*)"get_atomicGroupf32_", (char*)"(J)Z", (void*)device_features_get_atomicGroupf32 },
		{ (char*)"set_atomicGroupu64_", (char*)"(JZ)V", (void*)device_features_set_atomicGroupu64 },
		{ (char*)"get_atomicGroupu64_", (char*)"(J)Z", (void*)device_features_get_atomicGroupu64 },
		{ (char*)"set_atomicBufferf32_", (char*)"(JZ)V", (void*)device_features_set_atomicBufferf32 },
		{ (char*)"get_atomicBufferf32_", (char*)"(J)Z", (void*)device_features_get_atomicBufferf32 },
		{ (char*)"set_atomicBufferu64_", (char*)"(JZ)V", (void*)device_features_set_atomicBufferu64 },
		{ (char*)"get_atomicBufferu64_", (char*)"(J)Z", (void*)device_features_get_atomicBufferu64 },
		{ (char*)"set_atomicTexturef32_", (char*)"(JZ)V", (void*)device_features_set_atomicTexturef32 },
		{ (char*)"get_atomicTexturef32_", (char*)"(J)Z", (void*)device_features_get_atomicTexturef32 },
		{ (char*)"set_atomicTextureu32_", (char*)"(JZ)V", (void*)device_features_set_atomicTextureu32 },
		{ (char*)"get_atomicTextureu32_", (char*)"(J)Z", (void*)device_features_get_atomicTextureu32 },
		{ (char*)"set_atomicTextureu64_", (char*)"(JZ)V", (void*)device_features_set_atomicTextureu64 },
		{ (char*)"get_atomicTextureu64_", (char*)"(J)Z", (void*)device_features_get_atomicTextureu64 },
		{ (char*)"set_matrix16f16_", (char*)"(JZ)V", (void*)device_features_set_matrix16f16 },
		{ (char*)"get_matrix16f16_", (char*)"(J)Z", (void*)device_features_get_matrix16f16 },
		{ (char*)"set_matrix16x8x8f16_", (char*)"(JZ)V", (void*)device_features_set_matrix16x8x8f16 },
		{ (char*)"get_matrix16x8x8f16_", (char*)"(J)Z", (void*)device_features_get_matrix16x8x8f16 },
		{ (char*)"set_matrix16x8x16f16_", (char*)"(JZ)V", (void*)device_features_set_matrix16x8x16f16 },
		{ (char*)"get_matrix16x8x16f16_", (char*)"(J)Z", (void*)device_features_get_matrix16x8x16f16 },
		{ (char*)"set_matrix16f16f32_", (char*)"(JZ)V", (void*)device_features_set_matrix16f16f32 },
		{ (char*)"get_matrix16f16f32_", (char*)"(J)Z", (void*)device_features_get_matrix16f16f32 },
		{ (char*)"set_matrix16x8x8f16f32_", (char*)"(JZ)V", (void*)device_features_set_matrix16x8x8f16f32 },
		{ (char*)"get_matrix16x8x8f16f32_", (char*)"(J)Z", (void*)device_features_get_matrix16x8x8f16f32 },
		{ (char*)"set_matrix16x8x16f16f32_", (char*)"(JZ)V", (void*)device_features_set_matrix16x8x16f16f32 },
		{ (char*)"get_matrix16x8x16f16f32_", (char*)"(J)Z", (void*)device_features_get_matrix16x8x16f16f32 },
		{ (char*)"set_uniformAlignment_", (char*)"(JI)V", (void*)device_features_set_uniformAlignment },
		{ (char*)"get_uniformAlignment_", (char*)"(J)I", (void*)device_features_get_uniformAlignment },
		{ (char*)"set_storageAlignment_", (char*)"(JI)V", (void*)device_features_set_storageAlignment },
		{ (char*)"get_storageAlignment_", (char*)"(J)I", (void*)device_features_get_storageAlignment },
		{ (char*)"set_maxTextureSamples_", (char*)"(JI)V", (void*)device_features_set_maxTextureSamples },
		{ (char*)"get_maxTextureSamples_", (char*)"(J)I", (void*)device_features_get_maxTextureSamples },
		{ (char*)"set_maxTexture2DSize_", (char*)"(JI)V", (void*)device_features_set_maxTexture2DSize },
		{ (char*)"get_maxTexture2DSize_", (char*)"(J)I", (void*)device_features_get_maxTexture2DSize },
		{ (char*)"set_maxTexture3DSize_", (char*)"(JI)V", (void*)device_features_set_maxTexture3DSize },
		{ (char*)"get_maxTexture3DSize_", (char*)"(J)I", (void*)device_features_get_maxTexture3DSize },
		{ (char*)"set_maxTextureLayers_", (char*)"(JI)V", (void*)device_features_set_maxTextureLayers },
		{ (char*)"get_maxTextureLayers_", (char*)"(J)I", (void*)device_features_get_maxTextureLayers },
		{ (char*)"set_maxGroupSizeX_", (char*)"(JI)V", (void*)device_features_set_maxGroupSizeX },
		{ (char*)"get_maxGroupSizeX_", (char*)"(J)I", (void*)device_features_get_maxGroupSizeX },
		{ (char*)"set_maxGroupSizeY_", (char*)"(JI)V", (void*)device_features_set_maxGroupSizeY },
		{ (char*)"get_maxGroupSizeY_", (char*)"(J)I", (void*)device_features_get_maxGroupSizeY },
		{ (char*)"set_maxGroupSizeZ_", (char*)"(JI)V", (void*)device_features_set_maxGroupSizeZ },
		{ (char*)"get_maxGroupSizeZ_", (char*)"(J)I", (void*)device_features_get_maxGroupSizeZ },
		{ (char*)"set_maxGroupCountX_", (char*)"(JI)V", (void*)device_features_set_maxGroupCountX },
		{ (char*)"get_maxGroupCountX_", (char*)"(J)I", (void*)device_features_get_maxGroupCountX },
		{ (char*)"set_maxGroupCountY_", (char*)"(JI)V", (void*)device_features_set_maxGroupCountY },
		{ (char*)"get_maxGroupCountY_", (char*)"(J)I", (void*)device_features_get_maxGroupCountY },
		{ (char*)"set_maxGroupCountZ_", (char*)"(JI)V", (void*)device_features_set_maxGroupCountZ },
		{ (char*)"get_maxGroupCountZ_", (char*)"(J)I", (void*)device_features_get_maxGroupCountZ },
		{ (char*)"set_maxTaskCount_", (char*)"(JI)V", (void*)device_features_set_maxTaskCount },
		{ (char*)"get_maxTaskCount_", (char*)"(J)I", (void*)device_features_get_maxTaskCount },
		{ (char*)"set_maxTaskMemory_", (char*)"(JI)V", (void*)device_features_set_maxTaskMemory },
		{ (char*)"get_maxTaskMemory_", (char*)"(J)I", (void*)device_features_get_maxTaskMemory },
		{ (char*)"set_maxTaskMeshes_", (char*)"(JI)V", (void*)device_features_set_maxTaskMeshes },
		{ (char*)"get_maxTaskMeshes_", (char*)"(J)I", (void*)device_features_get_maxTaskMeshes },
		{ (char*)"set_maxMeshMemory_", (char*)"(JI)V", (void*)device_features_set_maxMeshMemory },
		{ (char*)"get_maxMeshMemory_", (char*)"(J)I", (void*)device_features_get_maxMeshMemory },
		{ (char*)"set_maxMeshVertices_", (char*)"(JI)V", (void*)device_features_set_maxMeshVertices },
		{ (char*)"get_maxMeshVertices_", (char*)"(J)I", (void*)device_features_get_maxMeshVertices },
		{ (char*)"set_maxMeshPrimitives_", (char*)"(JI)V", (void*)device_features_set_maxMeshPrimitives },
		{ (char*)"get_maxMeshPrimitives_", (char*)"(J)I", (void*)device_features_get_maxMeshPrimitives },
		{ (char*)"set_maxViewportCount_", (char*)"(JI)V", (void*)device_features_set_maxViewportCount },
		{ (char*)"get_maxViewportCount_", (char*)"(J)I", (void*)device_features_get_maxViewportCount },
		{ (char*)"set_maxClipCullCount_", (char*)"(JI)V", (void*)device_features_set_maxClipCullCount },
		{ (char*)"get_maxClipCullCount_", (char*)"(J)I", (void*)device_features_get_maxClipCullCount },
		{ (char*)"set_maxUniformSize_", (char*)"(JJ)V", (void*)device_features_set_maxUniformSize },
		{ (char*)"get_maxUniformSize_", (char*)"(J)J", (void*)device_features_get_maxUniformSize },
		{ (char*)"set_maxStorageSize_", (char*)"(JJ)V", (void*)device_features_set_maxStorageSize },
		{ (char*)"get_maxStorageSize_", (char*)"(J)J", (void*)device_features_get_maxStorageSize },
		{ (char*)"set_groupMemory_", (char*)"(JI)V", (void*)device_features_set_groupMemory },
		{ (char*)"get_groupMemory_", (char*)"(J)I", (void*)device_features_get_groupMemory },
		{ (char*)"set_videoMemory_", (char*)"(JJ)V", (void*)device_features_set_videoMemory },
		{ (char*)"get_videoMemory_", (char*)"(J)J", (void*)device_features_get_videoMemory },
		{ (char*)"set_vendorID_", (char*)"(JI)V", (void*)device_features_set_vendorID },
		{ (char*)"get_vendorID_", (char*)"(J)I", (void*)device_features_get_vendorID },
		{ (char*)"set_deviceID_", (char*)"(JI)V", (void*)device_features_set_deviceID },
		{ (char*)"get_deviceID_", (char*)"(J)I", (void*)device_features_get_deviceID },
		{ (char*)"set_pciBusID_", (char*)"(JI)V", (void*)device_features_set_pciBusID },
		{ (char*)"get_pciBusID_", (char*)"(J)I", (void*)device_features_get_pciBusID },
		{ (char*)"set_pciDomainID_", (char*)"(JI)V", (void*)device_features_set_pciDomainID },
		{ (char*)"get_pciDomainID_", (char*)"(J)I", (void*)device_features_get_pciDomainID },
		{ (char*)"set_pciDeviceID_", (char*)"(JI)V", (void*)device_features_set_pciDeviceID },
		{ (char*)"get_pciDeviceID_", (char*)"(J)I", (void*)device_features_get_pciDeviceID },
	};
	// Tellusim::Device
	static jlong device_new(TS_JNI_ARGS) {
		return newDevice();
	}
	static jlong device_new_1(TS_JNI_ARGS, jlong context) {
		return newDevice(toContext(context));
	}
	static jlong device_new_2(TS_JNI_ARGS, jlong surface) {
		return newDevice(toSurface(surface));
	}
	static jlong device_new_3(TS_JNI_ARGS, jlong window) {
		return newDevice(toWindow(window));
	}
	static void device_delete(TS_JNI_ARGS, jlong self) {
		delete (Device*)self;
	}
	static jboolean device_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDevice(self) == toDevice(ptr));
	}
	static jlong device_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDevice(toDevice(self).clonePtr());
	}
	static void device_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDevice(self).clearPtr();
	}
	static void device_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDevice(self).destroyPtr();
	}
	static void device_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDevice(self).acquirePtr();
	}
	static void device_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDevice(self).unacquirePtr();
	}
	static jboolean device_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDevice(self).isValidPtr();
	}
	static jboolean device_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDevice(self).isOwnerPtr();
	}
	static jboolean device_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDevice(self).isConstPtr();
	}
	static jint device_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDevice(self).getCountPtr();
	}
	static jlong device_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDevice(self).getInternalPtr();
	}
	static jint device_get_platform(TS_JNI_ARGS, jlong self) {
		return toDevice(self).getPlatform();
	}
	static jstring device_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDevice(self).getPlatformName());
	}
	static jint device_get_index(TS_JNI_ARGS, jlong self) {
		return toDevice(self).getIndex();
	}
	static jstring device_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDevice(self).getName().get());
	}
	static jstring device_get_vendor(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDevice(self).getVendor().get());
	}
	static jstring device_get_version(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDevice(self).getVersion().get());
	}
	static jlong device_get_features(TS_JNI_ARGS, jlong self) {
		return newDeviceFeatures(toDevice(self).getFeatures());
	}
	static jboolean device_has_query(TS_JNI_ARGS, jlong self, jint type) {
		return toDevice(self).hasQuery((Query::Type)type);
	}
	static jboolean device_has_shader(TS_JNI_ARGS, jlong self, jint type) {
		return toDevice(self).hasShader((Shader::Type)type);
	}
	static jboolean device_has_target(TS_JNI_ARGS, jlong self, jint format) {
		return toDevice(self).hasTarget((Format)format);
	}
	static jboolean device_has_texture(TS_JNI_ARGS, jlong self, jint format) {
		return toDevice(self).hasTexture((Format)format);
	}
	static jboolean device_has_surface(TS_JNI_ARGS, jlong self, jint format) {
		return toDevice(self).hasSurface((Format)format);
	}
	static jlong device_create_device(TS_JNI_ARGS, jlong self, jint index, jint frames) {
		return newDevice(toDevice(self).createDevice((uint32_t)index, (uint32_t)frames));
	}
	static jlong device_create_command_device(TS_JNI_ARGS, jlong self, jint frames) {
		return newDevice(toDevice(self).createCommandDevice((uint32_t)frames));
	}
	static jlong device_create_compute_device(TS_JNI_ARGS, jlong self, jint frames) {
		return newDevice(toDevice(self).createComputeDevice((uint32_t)frames));
	}
	static jlong device_create_copy_device(TS_JNI_ARGS, jlong self, jint frames) {
		return newDevice(toDevice(self).createCopyDevice((uint32_t)frames));
	}
	static jlong device_create_query(TS_JNI_ARGS, jlong self) {
		return newQuery(toDevice(self).createQuery());
	}
	static jlong device_create_query_1(TS_JNI_ARGS, jlong self, jint type) {
		return newQuery(toDevice(self).createQuery((Query::Type)type));
	}
	static jlong device_create_fence(TS_JNI_ARGS, jlong self) {
		return newFence(toDevice(self).createFence());
	}
	static jlong device_create_fence_1(TS_JNI_ARGS, jlong self, jlong shared) {
		return newFence(toDevice(self).createFence(toFence(shared)));
	}
	static jlong device_create_fence_2(TS_JNI_ARGS, jlong self, jint flags) {
		return newFence(toDevice(self).createFence((Fence::Flags)flags));
	}
	static jlong device_create_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toDevice(self).createBuffer());
	}
	static jlong device_create_buffer_1(TS_JNI_ARGS, jlong self, jlong shared) {
		return newBuffer(toDevice(self).createBuffer(toBuffer(shared)));
	}
	static jlong device_create_buffer_2(TS_JNI_ARGS, jlong self, jint flags, jlong size, jint format) {
		return newBuffer(toDevice(self).createBuffer((Buffer::Flags)flags, (size_t)size, (Format)format));
	}
	static jlong device_create_buffer_3(TS_JNI_ARGS, jlong self, jint flags, jbyteArray src, jint format) {
		return newBuffer(toDevice(self).createBuffer((Buffer::Flags)flags, ByteArray(env, src).get(), env->GetArrayLength(src), (Format)format));
	}
	static jlong device_create_sampler(TS_JNI_ARGS, jlong self) {
		return newSampler(toDevice(self).createSampler());
	}
	static jlong device_create_sampler_1(TS_JNI_ARGS, jlong self, jlong sampler) {
		return newSampler(toDevice(self).createSampler(toSampler(sampler)));
	}
	static jlong device_create_sampler_2(TS_JNI_ARGS, jlong self, jint filter, jint mode, jint anisotropy) {
		return newSampler(toDevice(self).createSampler((Sampler::Filter)filter, (Sampler::WrapMode)mode, (uint32_t)anisotropy));
	}
	static jlong device_create_texture(TS_JNI_ARGS, jlong self) {
		return newTexture(toDevice(self).createTexture());
	}
	static jlong device_create_texture_1(TS_JNI_ARGS, jlong self, jlong shared) {
		return newTexture(toDevice(self).createTexture(toTexture(shared)));
	}
	static jlong device_create_texture_2(TS_JNI_ARGS, jlong self, jint type, jint format, jlong size, jint layers, jint flags) {
		return newTexture(toDevice(self).createTexture((Texture::Type)type, (Format)format, toSize(size), (uint32_t)layers, (Texture::Flags)flags));
	}
	static jlong device_create_texture_3(TS_JNI_ARGS, jlong self, jint type, jint format, jlong size, jint flags) {
		return newTexture(toDevice(self).createTexture((Texture::Type)type, (Format)format, toSize(size), (Texture::Flags)flags));
	}
	static jlong device_create_texture_4(TS_JNI_ARGS, jlong self, jlong image, jint flags, jlong async) {
		return newTexture(toDevice(self).createTexture(toImage(image), (Texture::Flags)flags, (Async*)async));
	}
	static jlong device_create_texture2d(TS_JNI_ARGS, jlong self, jint format, jint size, jint flags) {
		return newTexture(toDevice(self).createTexture2D((Format)format, (uint32_t)size, (Texture::Flags)flags));
	}
	static jlong device_create_texture3d(TS_JNI_ARGS, jlong self, jint format, jint size, jint flags) {
		return newTexture(toDevice(self).createTexture3D((Format)format, (uint32_t)size, (Texture::Flags)flags));
	}
	static jlong device_create_texture_cube(TS_JNI_ARGS, jlong self, jint format, jint size, jint flags) {
		return newTexture(toDevice(self).createTextureCube((Format)format, (uint32_t)size, (Texture::Flags)flags));
	}
	static jlong device_create_texture2d_1(TS_JNI_ARGS, jlong self, jint format, jint width, jint height, jint flags) {
		return newTexture(toDevice(self).createTexture2D((Format)format, (uint32_t)width, (uint32_t)height, (Texture::Flags)flags));
	}
	static jlong device_create_texture3d_1(TS_JNI_ARGS, jlong self, jint format, jint width, jint height, jint depth, jint flags) {
		return newTexture(toDevice(self).createTexture3D((Format)format, (uint32_t)width, (uint32_t)height, (uint32_t)depth, (Texture::Flags)flags));
	}
	static jlong device_create_texture2d_2(TS_JNI_ARGS, jlong self, jint format, jint width, jint height, jint layers, jint flags) {
		return newTexture(toDevice(self).createTexture2D((Format)format, (uint32_t)width, (uint32_t)height, (uint32_t)layers, (Texture::Flags)flags));
	}
	static jlong device_create_texture_cube_1(TS_JNI_ARGS, jlong self, jint format, jint size, jint layers, jint flags) {
		return newTexture(toDevice(self).createTextureCube((Format)format, (uint32_t)size, (uint32_t)layers, (Texture::Flags)flags));
	}
	static jlong device_load_texture(TS_JNI_ARGS, jlong self, jstring name, jint flags, jint image_flags, jint offset, jlong async) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Texture ret_ = toDevice(self).loadTexture(name_, (Texture::Flags)flags, (Image::Flags)image_flags, (uint32_t)offset, (Async*)async);
		env->ReleaseStringUTFChars(name, name_);
		return newTexture(ret_);
	}
	static jlong device_load_texture_1(TS_JNI_ARGS, jlong self, jlong name, jint flags, jint image_flags, jint offset, jlong async) {
		return newTexture(toDevice(self).loadTexture(toString(name), (Texture::Flags)flags, (Image::Flags)image_flags, (uint32_t)offset, (Async*)async));
	}
	static jlong device_load_texture_2(TS_JNI_ARGS, jlong self, jlong stream, jint flags, jint image_flags, jint offset, jlong async) {
		return newTexture(toDevice(self).loadTexture(toStream(stream), (Texture::Flags)flags, (Image::Flags)image_flags, (uint32_t)offset, (Async*)async));
	}
	static jlong device_create_tracing(TS_JNI_ARGS, jlong self) {
		return newTracing(toDevice(self).createTracing());
	}
	static jlong device_create_tracing_1(TS_JNI_ARGS, jlong self, jlong tracing) {
		return newTracing(toDevice(self).createTracing(toTracing(tracing)));
	}
	static jlong device_create_tracing_2(TS_JNI_ARGS, jlong self, jint num_instances, jlong instance_buffer, jlong instance_offset, jint flags) {
		return newTracing(toDevice(self).createTracing((uint32_t)num_instances, toBuffer(instance_buffer), (size_t)instance_offset, (Tracing::Flags)flags));
	}
	static jlong device_create_tracing_3(TS_JNI_ARGS, jlong self, jint num_vertices, jint vertex_format, jlong vertex_stride, jint num_indices, jint index_format, jint flags) {
		return newTracing(toDevice(self).createTracing((uint32_t)num_vertices, (Format)vertex_format, (size_t)vertex_stride, (uint32_t)num_indices, (Format)index_format, (Tracing::Flags)flags));
	}
	static jlong device_create_tracing_4(TS_JNI_ARGS, jlong self, jint num_bounds, jlong bound_stride, jlong bound_buffer, jlong bound_offset, jint flags) {
		return newTracing(toDevice(self).createTracing((uint32_t)num_bounds, (size_t)bound_stride, toBuffer(bound_buffer), (size_t)bound_offset, (Tracing::Flags)flags));
	}
	static jlong device_create_buffer_table(TS_JNI_ARGS, jlong self) {
		return newBufferTable(toDevice(self).createBufferTable());
	}
	static jlong device_create_buffer_table_1(TS_JNI_ARGS, jlong self, jint size) {
		return newBufferTable(toDevice(self).createBufferTable((uint32_t)size));
	}
	static jlong device_create_buffer_table_2(TS_JNI_ARGS, jlong self, jlongArray buffers, jboolean owner) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		BufferTable ret_ = toDevice(self).createBufferTable(buffers_, (bool)owner);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
		return newBufferTable(ret_);
	}
	static jlong device_create_texture_table(TS_JNI_ARGS, jlong self) {
		return newTextureTable(toDevice(self).createTextureTable());
	}
	static jlong device_create_texture_table_1(TS_JNI_ARGS, jlong self, jint type, jint size) {
		return newTextureTable(toDevice(self).createTextureTable((Texture::Type)type, (uint32_t)size));
	}
	static jlong device_create_texture_table_2(TS_JNI_ARGS, jlong self, jlongArray textures, jboolean owner) {
		Array<Texture> textures_((uint32_t)env->GetArrayLength(textures));
		jlong *textures__ = env->GetLongArrayElements(textures, nullptr);
		for(uint32_t i = 0; i < textures_.size(); i++) textures_[i] = toTexture(textures__[i]);
		TextureTable ret_ = toDevice(self).createTextureTable(textures_, (bool)owner);
		if(textures__) env->ReleaseLongArrayElements(textures, textures__, 0);
		return newTextureTable(ret_);
	}
	static jlong device_create_shader(TS_JNI_ARGS, jlong self) {
		return newShader(toDevice(self).createShader());
	}
	static jlong device_load_shader(TS_JNI_ARGS, jlong self, jint type, jstring name, jstring format) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		Shader ret_ = toDevice(self).loadShader((Shader::Type)type, name_, "%s", format_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(format, format_);
		return newShader(ret_);
	}
	static jlong device_load_shader_glsl(TS_JNI_ARGS, jlong self, jint type, jstring name, jstring format) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		Shader ret_ = toDevice(self).loadShaderGLSL((Shader::Type)type, name_, "%s", format_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(format, format_);
		return newShader(ret_);
	}
	static jlong device_load_shader_1(TS_JNI_ARGS, jlong self, jint type, jstring name, jlong macros) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Shader ret_ = toDevice(self).loadShader((Shader::Type)type, name_, toString(macros));
		env->ReleaseStringUTFChars(name, name_);
		return newShader(ret_);
	}
	static jlong device_load_shader_glsl_1(TS_JNI_ARGS, jlong self, jint type, jstring name, jlong macros) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Shader ret_ = toDevice(self).loadShaderGLSL((Shader::Type)type, name_, toString(macros));
		env->ReleaseStringUTFChars(name, name_);
		return newShader(ret_);
	}
	static jlong device_load_shader_spirv(TS_JNI_ARGS, jlong self, jint type, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Shader ret_ = toDevice(self).loadShaderSPIRV((Shader::Type)type, name_);
		env->ReleaseStringUTFChars(name, name_);
		return newShader(ret_);
	}
	static jlong device_create_shader_1(TS_JNI_ARGS, jlong self, jint type, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		Shader ret_ = toDevice(self).createShader((Shader::Type)type, src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return newShader(ret_);
	}
	static jlong device_create_shader_glsl(TS_JNI_ARGS, jlong self, jint type, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		Shader ret_ = toDevice(self).createShaderGLSL((Shader::Type)type, src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return newShader(ret_);
	}
	static jlong device_create_shader_2(TS_JNI_ARGS, jlong self, jint type, jstring src, jlong macros) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Shader ret_ = toDevice(self).createShader((Shader::Type)type, src_, toString(macros));
		env->ReleaseStringUTFChars(src, src_);
		return newShader(ret_);
	}
	static jlong device_create_shader_glsl_1(TS_JNI_ARGS, jlong self, jint type, jstring src, jlong macros) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Shader ret_ = toDevice(self).createShaderGLSL((Shader::Type)type, src_, toString(macros));
		env->ReleaseStringUTFChars(src, src_);
		return newShader(ret_);
	}
	static jlong device_create_shader_spirv(TS_JNI_ARGS, jlong self, jint type, jintArray data) {
		uint32_t *data__ = (uint32_t*)env->GetIntArrayElements(data, nullptr);
		Array<uint32_t> data_((uint32_t)env->GetArrayLength(data), data__);
		Shader ret_ = toDevice(self).createShaderSPIRV((Shader::Type)type, data_);
		if(data_) env->ReleaseIntArrayElements(data, (jint*)data__, 0);
		return newShader(ret_);
	}
	static jlong device_create_kernel(TS_JNI_ARGS, jlong self) {
		return newKernel(toDevice(self).createKernel());
	}
	static jlong device_create_kernel_1(TS_JNI_ARGS, jlong self, jlong kernel) {
		return newKernel(toDevice(self).createKernel(toKernel(kernel)));
	}
	static void device_release_kernel(TS_JNI_ARGS, jlong self, jlong kernel) {
		toDevice(self).releaseKernel(toKernel(kernel));
	}
	static jlong device_create_pipeline(TS_JNI_ARGS, jlong self) {
		return newPipeline(toDevice(self).createPipeline());
	}
	static jlong device_create_pipeline_1(TS_JNI_ARGS, jlong self, jlong pipeline) {
		return newPipeline(toDevice(self).createPipeline(toPipeline(pipeline)));
	}
	static void device_release_pipeline(TS_JNI_ARGS, jlong self, jlong pipeline) {
		toDevice(self).releasePipeline(toPipeline(pipeline));
	}
	static jlong device_create_traversal(TS_JNI_ARGS, jlong self) {
		return newTraversal(toDevice(self).createTraversal());
	}
	static jlong device_create_traversal_1(TS_JNI_ARGS, jlong self, jlong traversal) {
		return newTraversal(toDevice(self).createTraversal(toTraversal(traversal)));
	}
	static void device_release_traversal(TS_JNI_ARGS, jlong self, jlong traversal) {
		toDevice(self).releaseTraversal(toTraversal(traversal));
	}
	static jlong device_create_target(TS_JNI_ARGS, jlong self) {
		return newTarget(toDevice(self).createTarget());
	}
	static jlong device_create_target_1(TS_JNI_ARGS, jlong self, jlong surface) {
		return newTarget(toDevice(self).createTarget(toSurface(surface)));
	}
	static jlong device_create_target_2(TS_JNI_ARGS, jlong self, jlong window) {
		return newTarget(toDevice(self).createTarget(toWindow(window)));
	}
	static jlong device_create_compute(TS_JNI_ARGS, jlong self) {
		return newCompute(toDevice(self).createCompute());
	}
	static jlong device_create_command(TS_JNI_ARGS, jlong self) {
		return newCommand(toDevice(self).createCommand());
	}
	static jlong device_create_command_1(TS_JNI_ARGS, jlong self, jlong target) {
		return newCommand(toDevice(self).createCommand(toTarget(target)));
	}
	static jboolean device_set_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset, jbyteArray src) {
		return toDevice(self).setBuffer(toBuffer(buffer), (size_t)offset, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jboolean device_set_buffer_1(TS_JNI_ARGS, jlong self, jlong buffer, jbyteArray src) {
		return toDevice(self).setBuffer(toBuffer(buffer), ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jboolean device_set_buffer_2(TS_JNI_ARGS, jlong self, jlong buffer, jlong src) {
		return toDevice(self).setBuffer(toBuffer(buffer), (const void*)src);
	}
	static jboolean device_get_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset, jbyteArray dest) {
		return toDevice(self).getBuffer(toBuffer(buffer), (size_t)offset, ByteArray(env, dest).get(), env->GetArrayLength(dest));
	}
	static jboolean device_get_buffer_1(TS_JNI_ARGS, jlong self, jlong buffer, jbyteArray dest) {
		return toDevice(self).getBuffer(toBuffer(buffer), ByteArray(env, dest).get(), env->GetArrayLength(dest));
	}
	static jboolean device_get_buffer_2(TS_JNI_ARGS, jlong self, jlong buffer, jlong dest) {
		return toDevice(self).getBuffer(toBuffer(buffer), (void*)dest);
	}
	static jlong device_map_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jlong offset, jlong size) {
		return (jlong)toDevice(self).mapBuffer(toBuffer(buffer), (size_t)offset, (size_t)size);
	}
	static jlong device_map_buffer_1(TS_JNI_ARGS, jlong self, jlong buffer, jlong size) {
		return (jlong)toDevice(self).mapBuffer(toBuffer(buffer), (size_t)size);
	}
	static jlong device_map_buffer_2(TS_JNI_ARGS, jlong self, jlong buffer) {
		return (jlong)toDevice(self).mapBuffer(toBuffer(buffer));
	}
	static jboolean device_unmap_buffer(TS_JNI_ARGS, jlong self, jlong buffer) {
		return toDevice(self).unmapBuffer(toBuffer(buffer));
	}
	static jboolean device_copy_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jlong dest_offset, jlong src, jlong src_offset, jlong size) {
		return toDevice(self).copyBuffer(toBuffer(buffer), (size_t)dest_offset, toBuffer(src), (size_t)src_offset, (size_t)size);
	}
	static jboolean device_copy_buffer_1(TS_JNI_ARGS, jlong self, jlong buffer, jlong dest_offset, jlong src, jlong size) {
		return toDevice(self).copyBuffer(toBuffer(buffer), (size_t)dest_offset, toBuffer(src), (size_t)size);
	}
	static jboolean device_copy_buffer_2(TS_JNI_ARGS, jlong self, jlong buffer, jlong src, jlong size) {
		return toDevice(self).copyBuffer(toBuffer(buffer), toBuffer(src), (size_t)size);
	}
	static jboolean device_copy_buffer_3(TS_JNI_ARGS, jlong self, jlong buffer, jlong src) {
		return toDevice(self).copyBuffer(toBuffer(buffer), toBuffer(src));
	}
	static jboolean device_clear_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jint format, jlong offset, jbyteArray src) {
		return toDevice(self).clearBuffer(toBuffer(buffer), (Format)format, (size_t)offset, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jboolean device_clear_buffer_1(TS_JNI_ARGS, jlong self, jlong buffer, jint format, jbyteArray src) {
		return toDevice(self).clearBuffer(toBuffer(buffer), (Format)format, ByteArray(env, src).get(), env->GetArrayLength(src));
	}
	static jboolean device_clear_buffer_2(TS_JNI_ARGS, jlong self, jlong buffer, jint format, jlong src) {
		return toDevice(self).clearBuffer(toBuffer(buffer), (Format)format, (const void*)src);
	}
	static jboolean device_clear_buffer_3(TS_JNI_ARGS, jlong self, jlong buffer) {
		return toDevice(self).clearBuffer(toBuffer(buffer));
	}
	static jboolean device_flush_buffer(TS_JNI_ARGS, jlong self, jlong buffer, jint flags) {
		return toDevice(self).flushBuffer(toBuffer(buffer), (Buffer::Flags)flags);
	}
	static jboolean device_flush_buffers(TS_JNI_ARGS, jlong self, jlongArray buffers, jint flags) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		bool ret_ = toDevice(self).flushBuffers(buffers_, (Buffer::Flags)flags);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
		return ret_;
	}
	static void device_release_buffer(TS_JNI_ARGS, jlong self, jlong buffer) {
		toDevice(self).releaseBuffer(toBuffer(buffer));
	}
	static void device_release_sampler(TS_JNI_ARGS, jlong self, jlong sampler) {
		toDevice(self).releaseSampler(toSampler(sampler));
	}
	static jboolean device_set_texture(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_origin, jlong dest_slice, jlong image, jlong src_slice) {
		return toDevice(self).setTexture(toTexture(texture), toOrigin(dest_origin), toSlice(dest_slice), toImage(image), toSlice(src_slice));
	}
	static jboolean device_set_texture_1(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_origin, jlong image) {
		return toDevice(self).setTexture(toTexture(texture), toOrigin(dest_origin), toImage(image));
	}
	static jboolean device_set_texture_2(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_slice, jlong image) {
		return toDevice(self).setTexture(toTexture(texture), toSlice(dest_slice), toImage(image));
	}
	static jboolean device_set_texture_3(TS_JNI_ARGS, jlong self, jlong texture, jlong image) {
		return toDevice(self).setTexture(toTexture(texture), toImage(image));
	}
	static jboolean device_get_texture(TS_JNI_ARGS, jlong self, jlong texture, jlong src_slice, jlong image, jlong dest_slice) {
		return toDevice(self).getTexture(toTexture(texture), toSlice(src_slice), toImage(image), toSlice(dest_slice));
	}
	static jboolean device_get_texture_1(TS_JNI_ARGS, jlong self, jlong texture, jlong image, jlong dest_slice) {
		return toDevice(self).getTexture(toTexture(texture), toImage(image), toSlice(dest_slice));
	}
	static jboolean device_get_texture_2(TS_JNI_ARGS, jlong self, jlong texture, jlong image) {
		return toDevice(self).getTexture(toTexture(texture), toImage(image));
	}
	static jboolean device_copy_texture(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_origin, jlong dest_slice, jlong src, jlong src_region, jlong src_slice) {
		return toDevice(self).copyTexture(toTexture(texture), toOrigin(dest_origin), toSlice(dest_slice), toTexture(src), toRegion(src_region), toSlice(src_slice));
	}
	static jboolean device_copy_texture_1(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_origin, jlong src, jlong src_region) {
		return toDevice(self).copyTexture(toTexture(texture), toOrigin(dest_origin), toTexture(src), toRegion(src_region));
	}
	static jboolean device_copy_texture_2(TS_JNI_ARGS, jlong self, jlong texture, jlong dest_slice, jlong src, jlong src_slice) {
		return toDevice(self).copyTexture(toTexture(texture), toSlice(dest_slice), toTexture(src), toSlice(src_slice));
	}
	static jboolean device_copy_texture_3(TS_JNI_ARGS, jlong self, jlong texture, jlong src) {
		return toDevice(self).copyTexture(toTexture(texture), toTexture(src));
	}
	static jboolean device_clear_texture(TS_JNI_ARGS, jlong self, jlong texture, jlong region, jlong slice, jlong src) {
		return toDevice(self).clearTexture(toTexture(texture), toRegion(region), toSlice(slice), (const void*)src);
	}
	static jboolean device_clear_texture_1(TS_JNI_ARGS, jlong self, jlong texture, jlong region, jlong src) {
		return toDevice(self).clearTexture(toTexture(texture), toRegion(region), (const void*)src);
	}
	static jboolean device_clear_texture_2(TS_JNI_ARGS, jlong self, jlong texture, jlong slice, jlong src) {
		return toDevice(self).clearTexture(toTexture(texture), toSlice(slice), (const void*)src);
	}
	static jboolean device_clear_texture_3(TS_JNI_ARGS, jlong self, jlong texture, jlong src) {
		return toDevice(self).clearTexture(toTexture(texture), (const void*)src);
	}
	static jboolean device_bind_texture(TS_JNI_ARGS, jlong self, jlong texture, jlongArray regions, jlongArray slices, jboolean commit, jlong fence) {
		Array<Region> regions_((uint32_t)env->GetArrayLength(regions));
		jlong *regions__ = env->GetLongArrayElements(regions, nullptr);
		for(uint32_t i = 0; i < regions_.size(); i++) regions_[i] = toRegion(regions__[i]);
		Array<Slice> slices_((uint32_t)env->GetArrayLength(slices));
		jlong *slices__ = env->GetLongArrayElements(slices, nullptr);
		for(uint32_t i = 0; i < slices_.size(); i++) slices_[i] = toSlice(slices__[i]);
		bool ret_ = toDevice(self).bindTexture(toTexture(texture), regions_.get(), regions_.size(), slices_.get(), slices_.size(), (bool)commit, toFence(fence));
		if(regions__) env->ReleaseLongArrayElements(regions, regions__, 0);
		if(slices__) env->ReleaseLongArrayElements(slices, slices__, 0);
		return ret_;
	}
	static jboolean device_bind_texture_1(TS_JNI_ARGS, jlong self, jlong texture, jlongArray regions, jlongArray slices, jboolean commit) {
		Array<Region> regions_((uint32_t)env->GetArrayLength(regions));
		jlong *regions__ = env->GetLongArrayElements(regions, nullptr);
		for(uint32_t i = 0; i < regions_.size(); i++) regions_[i] = toRegion(regions__[i]);
		Array<Slice> slices_((uint32_t)env->GetArrayLength(slices));
		jlong *slices__ = env->GetLongArrayElements(slices, nullptr);
		for(uint32_t i = 0; i < slices_.size(); i++) slices_[i] = toSlice(slices__[i]);
		bool ret_ = toDevice(self).bindTexture(toTexture(texture), regions_.get(), regions_.size(), slices_.get(), slices_.size(), (bool)commit);
		if(regions__) env->ReleaseLongArrayElements(regions, regions__, 0);
		if(slices__) env->ReleaseLongArrayElements(slices, slices__, 0);
		return ret_;
	}
	static jboolean device_bind_texture_2(TS_JNI_ARGS, jlong self, jlong texture, jlong region, jlong slice, jboolean commit, jlong fence) {
		return toDevice(self).bindTexture(toTexture(texture), toRegion(region), toSlice(slice), (bool)commit, toFence(fence));
	}
	static jboolean device_bind_texture_3(TS_JNI_ARGS, jlong self, jlong texture, jlong region, jlong slice, jboolean commit) {
		return toDevice(self).bindTexture(toTexture(texture), toRegion(region), toSlice(slice), (bool)commit);
	}
	static jboolean device_create_mipmaps(TS_JNI_ARGS, jlong self, jlong texture, jlong slice) {
		return toDevice(self).createMipmaps(toTexture(texture), toSlice(slice));
	}
	static jboolean device_create_mipmaps_1(TS_JNI_ARGS, jlong self, jlong texture) {
		return toDevice(self).createMipmaps(toTexture(texture));
	}
	static jboolean device_flush_texture(TS_JNI_ARGS, jlong self, jlong texture, jint flags) {
		return toDevice(self).flushTexture(toTexture(texture), (Texture::Flags)flags);
	}
	static jboolean device_flush_texture_1(TS_JNI_ARGS, jlong self, jlong texture, jlong slice, jint flags) {
		return toDevice(self).flushTexture(toTexture(texture), toSlice(slice), (Texture::Flags)flags);
	}
	static jboolean device_flush_textures(TS_JNI_ARGS, jlong self, jlongArray textures, jint flags) {
		Array<Texture> textures_((uint32_t)env->GetArrayLength(textures));
		jlong *textures__ = env->GetLongArrayElements(textures, nullptr);
		for(uint32_t i = 0; i < textures_.size(); i++) textures_[i] = toTexture(textures__[i]);
		bool ret_ = toDevice(self).flushTextures(textures_, (Texture::Flags)flags);
		if(textures__) env->ReleaseLongArrayElements(textures, textures__, 0);
		return ret_;
	}
	static void device_release_texture(TS_JNI_ARGS, jlong self, jlong texture) {
		toDevice(self).releaseTexture(toTexture(texture));
	}
	static jboolean device_set_tracing(TS_JNI_ARGS, jlong self, jlong tracing, jlongArray instances) {
		Array<Tracing::Instance> instances_((uint32_t)env->GetArrayLength(instances));
		jlong *instances__ = env->GetLongArrayElements(instances, nullptr);
		for(uint32_t i = 0; i < instances_.size(); i++) instances_[i] = toTracingInstance(instances__[i]);
		bool ret_ = toDevice(self).setTracing(toTracing(tracing), instances_.get(), instances_.size());
		if(instances__) env->ReleaseLongArrayElements(instances, instances__, 0);
		return ret_;
	}
	static jboolean device_build_tracing(TS_JNI_ARGS, jlong self, jlong tracing, jlong buffer, jint flags) {
		return toDevice(self).buildTracing(toTracing(tracing), toBuffer(buffer), (Tracing::Flags)flags);
	}
	static jboolean device_build_tracing_1(TS_JNI_ARGS, jlong self, jlong tracing, jlong buffer, jlong offset, jint flags) {
		return toDevice(self).buildTracing(toTracing(tracing), toBuffer(buffer), (size_t)offset, (Tracing::Flags)flags);
	}
	static jboolean device_build_tracings(TS_JNI_ARGS, jlong self, jlongArray tracings, jlong buffer, jint flags) {
		Array<Tracing> tracings_((uint32_t)env->GetArrayLength(tracings));
		jlong *tracings__ = env->GetLongArrayElements(tracings, nullptr);
		for(uint32_t i = 0; i < tracings_.size(); i++) tracings_[i] = toTracing(tracings__[i]);
		bool ret_ = toDevice(self).buildTracings(tracings_, toBuffer(buffer), (Tracing::Flags)flags);
		if(tracings__) env->ReleaseLongArrayElements(tracings, tracings__, 0);
		return ret_;
	}
	static jboolean device_build_tracings_1(TS_JNI_ARGS, jlong self, jlongArray tracings, jlong buffer, jlong offset, jint flags) {
		Array<Tracing> tracings_((uint32_t)env->GetArrayLength(tracings));
		jlong *tracings__ = env->GetLongArrayElements(tracings, nullptr);
		for(uint32_t i = 0; i < tracings_.size(); i++) tracings_[i] = toTracing(tracings__[i]);
		bool ret_ = toDevice(self).buildTracings(tracings_, toBuffer(buffer), (size_t)offset, (Tracing::Flags)flags);
		if(tracings__) env->ReleaseLongArrayElements(tracings, tracings__, 0);
		return ret_;
	}
	static jboolean device_copy_tracing(TS_JNI_ARGS, jlong self, jlong tracing, jlong buffer, jlong offset) {
		return toDevice(self).copyTracing(toTracing(tracing), toBuffer(buffer), (size_t)offset);
	}
	static jboolean device_copy_tracings(TS_JNI_ARGS, jlong self, jlongArray tracings, jlong buffer, jlong offset, jlong stride) {
		Array<Tracing> tracings_((uint32_t)env->GetArrayLength(tracings));
		jlong *tracings__ = env->GetLongArrayElements(tracings, nullptr);
		for(uint32_t i = 0; i < tracings_.size(); i++) tracings_[i] = toTracing(tracings__[i]);
		bool ret_ = toDevice(self).copyTracings(tracings_, toBuffer(buffer), (size_t)offset, (size_t)stride);
		if(tracings__) env->ReleaseLongArrayElements(tracings, tracings__, 0);
		return ret_;
	}
	static jboolean device_flush_tracing(TS_JNI_ARGS, jlong self, jlong tracing) {
		return toDevice(self).flushTracing(toTracing(tracing));
	}
	static jboolean device_flush_tracings(TS_JNI_ARGS, jlong self, jlongArray tracings) {
		Array<Tracing> tracings_((uint32_t)env->GetArrayLength(tracings));
		jlong *tracings__ = env->GetLongArrayElements(tracings, nullptr);
		for(uint32_t i = 0; i < tracings_.size(); i++) tracings_[i] = toTracing(tracings__[i]);
		bool ret_ = toDevice(self).flushTracings(tracings_);
		if(tracings__) env->ReleaseLongArrayElements(tracings, tracings__, 0);
		return ret_;
	}
	static void device_release_tracing(TS_JNI_ARGS, jlong self, jlong tracing) {
		toDevice(self).releaseTracing(toTracing(tracing));
	}
	static jboolean device_set_buffer_table(TS_JNI_ARGS, jlong self, jlong table, jint index, jlong buffer, jboolean owner) {
		return toDevice(self).setBufferTable(toBufferTable(table), (uint32_t)index, toBuffer(buffer), (bool)owner);
	}
	static jboolean device_set_buffer_table_1(TS_JNI_ARGS, jlong self, jlong table, jint index, jlongArray buffers, jboolean owner) {
		Array<Buffer> buffers_((uint32_t)env->GetArrayLength(buffers));
		jlong *buffers__ = env->GetLongArrayElements(buffers, nullptr);
		for(uint32_t i = 0; i < buffers_.size(); i++) buffers_[i] = toBuffer(buffers__[i]);
		bool ret_ = toDevice(self).setBufferTable(toBufferTable(table), (uint32_t)index, buffers_, (bool)owner);
		if(buffers__) env->ReleaseLongArrayElements(buffers, buffers__, 0);
		return ret_;
	}
	static void device_release_buffer_table(TS_JNI_ARGS, jlong self, jlong table) {
		toDevice(self).releaseBufferTable(toBufferTable(table));
	}
	static jboolean device_set_texture_table(TS_JNI_ARGS, jlong self, jlong table, jint index, jlong texture, jboolean owner) {
		return toDevice(self).setTextureTable(toTextureTable(table), (uint32_t)index, toTexture(texture), (bool)owner);
	}
	static jboolean device_set_texture_table_1(TS_JNI_ARGS, jlong self, jlong table, jint index, jlongArray textures, jboolean owner) {
		Array<Texture> textures_((uint32_t)env->GetArrayLength(textures));
		jlong *textures__ = env->GetLongArrayElements(textures, nullptr);
		for(uint32_t i = 0; i < textures_.size(); i++) textures_[i] = toTexture(textures__[i]);
		bool ret_ = toDevice(self).setTextureTable(toTextureTable(table), (uint32_t)index, textures_, (bool)owner);
		if(textures__) env->ReleaseLongArrayElements(textures, textures__, 0);
		return ret_;
	}
	static void device_release_texture_table(TS_JNI_ARGS, jlong self, jlong table) {
		toDevice(self).releaseTextureTable(toTextureTable(table));
	}
	static jboolean device_begin_query(TS_JNI_ARGS, jlong self, jlong query) {
		return toDevice(self).beginQuery(toQuery(query));
	}
	static void device_end_query(TS_JNI_ARGS, jlong self, jlong query) {
		toDevice(self).endQuery(toQuery(query));
	}
	static jboolean device_copy_query(TS_JNI_ARGS, jlong self, jlong query, jlong buffer, jlong offset) {
		return toDevice(self).copyQuery(toQuery(query), toBuffer(buffer), (size_t)offset);
	}
	static jboolean device_copy_queries(TS_JNI_ARGS, jlong self, jlongArray queries, jlong buffer, jlong offset, jlong stride) {
		Array<Query> queries_((uint32_t)env->GetArrayLength(queries));
		jlong *queries__ = env->GetLongArrayElements(queries, nullptr);
		for(uint32_t i = 0; i < queries_.size(); i++) queries_[i] = toQuery(queries__[i]);
		bool ret_ = toDevice(self).copyQueries(queries_, toBuffer(buffer), (size_t)offset, (size_t)stride);
		if(queries__) env->ReleaseLongArrayElements(queries, queries__, 0);
		return ret_;
	}
	static jboolean device_wait_fence(TS_JNI_ARGS, jlong self, jlong fence) {
		return toDevice(self).waitFence(toFence(fence));
	}
	static jboolean device_signal_fence(TS_JNI_ARGS, jlong self, jlong fence) {
		return toDevice(self).signalFence(toFence(fence));
	}
	static jboolean device_execute(TS_JNI_ARGS, jlong self, jlong device) {
		return toDevice(self).execute(toDevice(device));
	}
	static jboolean device_flip(TS_JNI_ARGS, jlong self, jlong fence) {
		return toDevice(self).flip(toFence(fence));
	}
	static jboolean device_flip_1(TS_JNI_ARGS, jlong self) {
		return toDevice(self).flip();
	}
	static jboolean device_flush(TS_JNI_ARGS, jlong self) {
		return toDevice(self).flush();
	}
	static jboolean device_finish(TS_JNI_ARGS, jlong self) {
		return toDevice(self).finish();
	}
	static jboolean device_check(TS_JNI_ARGS, jlong self) {
		return toDevice(self).check();
	}
	static const JNINativeMethod device_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)device_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)device_new_1 },
		{ (char*)"new_2", (char*)"(J)J", (void*)device_new_2 },
		{ (char*)"new_3", (char*)"(J)J", (void*)device_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)device_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)device_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)device_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)device_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)device_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)device_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)device_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)device_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)device_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)device_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)device_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)device_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)device_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)device_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)device_get_index },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)device_get_name },
		{ (char*)"get_vendor", (char*)"(J)Ljava/lang/String;", (void*)device_get_vendor },
		{ (char*)"get_version", (char*)"(J)Ljava/lang/String;", (void*)device_get_version },
		{ (char*)"get_features", (char*)"(J)J", (void*)device_get_features },
		{ (char*)"has_query", (char*)"(JI)Z", (void*)device_has_query },
		{ (char*)"has_shader", (char*)"(JI)Z", (void*)device_has_shader },
		{ (char*)"has_target", (char*)"(JI)Z", (void*)device_has_target },
		{ (char*)"has_texture", (char*)"(JI)Z", (void*)device_has_texture },
		{ (char*)"has_surface", (char*)"(JI)Z", (void*)device_has_surface },
		{ (char*)"create_device", (char*)"(JII)J", (void*)device_create_device },
		{ (char*)"create_command_device", (char*)"(JI)J", (void*)device_create_command_device },
		{ (char*)"create_compute_device", (char*)"(JI)J", (void*)device_create_compute_device },
		{ (char*)"create_copy_device", (char*)"(JI)J", (void*)device_create_copy_device },
		{ (char*)"create_query", (char*)"(J)J", (void*)device_create_query },
		{ (char*)"create_query_1", (char*)"(JI)J", (void*)device_create_query_1 },
		{ (char*)"create_fence", (char*)"(J)J", (void*)device_create_fence },
		{ (char*)"create_fence_1", (char*)"(JJ)J", (void*)device_create_fence_1 },
		{ (char*)"create_fence_2", (char*)"(JI)J", (void*)device_create_fence_2 },
		{ (char*)"create_buffer", (char*)"(J)J", (void*)device_create_buffer },
		{ (char*)"create_buffer_1", (char*)"(JJ)J", (void*)device_create_buffer_1 },
		{ (char*)"create_buffer_2", (char*)"(JIJI)J", (void*)device_create_buffer_2 },
		{ (char*)"create_buffer_3", (char*)"(JI[BI)J", (void*)device_create_buffer_3 },
		{ (char*)"create_sampler", (char*)"(J)J", (void*)device_create_sampler },
		{ (char*)"create_sampler_1", (char*)"(JJ)J", (void*)device_create_sampler_1 },
		{ (char*)"create_sampler_2", (char*)"(JIII)J", (void*)device_create_sampler_2 },
		{ (char*)"create_texture", (char*)"(J)J", (void*)device_create_texture },
		{ (char*)"create_texture_1", (char*)"(JJ)J", (void*)device_create_texture_1 },
		{ (char*)"create_texture_2", (char*)"(JIIJII)J", (void*)device_create_texture_2 },
		{ (char*)"create_texture_3", (char*)"(JIIJI)J", (void*)device_create_texture_3 },
		{ (char*)"create_texture_4", (char*)"(JJIJ)J", (void*)device_create_texture_4 },
		{ (char*)"create_texture2d", (char*)"(JIII)J", (void*)device_create_texture2d },
		{ (char*)"create_texture3d", (char*)"(JIII)J", (void*)device_create_texture3d },
		{ (char*)"create_texture_cube", (char*)"(JIII)J", (void*)device_create_texture_cube },
		{ (char*)"create_texture2d_1", (char*)"(JIIII)J", (void*)device_create_texture2d_1 },
		{ (char*)"create_texture3d_1", (char*)"(JIIIII)J", (void*)device_create_texture3d_1 },
		{ (char*)"create_texture2d_2", (char*)"(JIIIII)J", (void*)device_create_texture2d_2 },
		{ (char*)"create_texture_cube_1", (char*)"(JIIII)J", (void*)device_create_texture_cube_1 },
		{ (char*)"load_texture", (char*)"(JLjava/lang/String;IIIJ)J", (void*)device_load_texture },
		{ (char*)"load_texture_1", (char*)"(JJIIIJ)J", (void*)device_load_texture_1 },
		{ (char*)"load_texture_2", (char*)"(JJIIIJ)J", (void*)device_load_texture_2 },
		{ (char*)"create_tracing", (char*)"(J)J", (void*)device_create_tracing },
		{ (char*)"create_tracing_1", (char*)"(JJ)J", (void*)device_create_tracing_1 },
		{ (char*)"create_tracing_2", (char*)"(JIJJI)J", (void*)device_create_tracing_2 },
		{ (char*)"create_tracing_3", (char*)"(JIIJIII)J", (void*)device_create_tracing_3 },
		{ (char*)"create_tracing_4", (char*)"(JIJJJI)J", (void*)device_create_tracing_4 },
		{ (char*)"create_buffer_table", (char*)"(J)J", (void*)device_create_buffer_table },
		{ (char*)"create_buffer_table_1", (char*)"(JI)J", (void*)device_create_buffer_table_1 },
		{ (char*)"create_buffer_table_2", (char*)"(J[JZ)J", (void*)device_create_buffer_table_2 },
		{ (char*)"create_texture_table", (char*)"(J)J", (void*)device_create_texture_table },
		{ (char*)"create_texture_table_1", (char*)"(JII)J", (void*)device_create_texture_table_1 },
		{ (char*)"create_texture_table_2", (char*)"(J[JZ)J", (void*)device_create_texture_table_2 },
		{ (char*)"create_shader", (char*)"(J)J", (void*)device_create_shader },
		{ (char*)"load_shader", (char*)"(JILjava/lang/String;Ljava/lang/String;)J", (void*)device_load_shader },
		{ (char*)"load_shader_glsl", (char*)"(JILjava/lang/String;Ljava/lang/String;)J", (void*)device_load_shader_glsl },
		{ (char*)"load_shader_1", (char*)"(JILjava/lang/String;J)J", (void*)device_load_shader_1 },
		{ (char*)"load_shader_glsl_1", (char*)"(JILjava/lang/String;J)J", (void*)device_load_shader_glsl_1 },
		{ (char*)"load_shader_spirv", (char*)"(JILjava/lang/String;)J", (void*)device_load_shader_spirv },
		{ (char*)"create_shader_1", (char*)"(JILjava/lang/String;Ljava/lang/String;)J", (void*)device_create_shader_1 },
		{ (char*)"create_shader_glsl", (char*)"(JILjava/lang/String;Ljava/lang/String;)J", (void*)device_create_shader_glsl },
		{ (char*)"create_shader_2", (char*)"(JILjava/lang/String;J)J", (void*)device_create_shader_2 },
		{ (char*)"create_shader_glsl_1", (char*)"(JILjava/lang/String;J)J", (void*)device_create_shader_glsl_1 },
		{ (char*)"create_shader_spirv", (char*)"(JI[I)J", (void*)device_create_shader_spirv },
		{ (char*)"create_kernel", (char*)"(J)J", (void*)device_create_kernel },
		{ (char*)"create_kernel_1", (char*)"(JJ)J", (void*)device_create_kernel_1 },
		{ (char*)"release_kernel", (char*)"(JJ)V", (void*)device_release_kernel },
		{ (char*)"create_pipeline", (char*)"(J)J", (void*)device_create_pipeline },
		{ (char*)"create_pipeline_1", (char*)"(JJ)J", (void*)device_create_pipeline_1 },
		{ (char*)"release_pipeline", (char*)"(JJ)V", (void*)device_release_pipeline },
		{ (char*)"create_traversal", (char*)"(J)J", (void*)device_create_traversal },
		{ (char*)"create_traversal_1", (char*)"(JJ)J", (void*)device_create_traversal_1 },
		{ (char*)"release_traversal", (char*)"(JJ)V", (void*)device_release_traversal },
		{ (char*)"create_target", (char*)"(J)J", (void*)device_create_target },
		{ (char*)"create_target_1", (char*)"(JJ)J", (void*)device_create_target_1 },
		{ (char*)"create_target_2", (char*)"(JJ)J", (void*)device_create_target_2 },
		{ (char*)"create_compute", (char*)"(J)J", (void*)device_create_compute },
		{ (char*)"create_command", (char*)"(J)J", (void*)device_create_command },
		{ (char*)"create_command_1", (char*)"(JJ)J", (void*)device_create_command_1 },
		{ (char*)"set_buffer", (char*)"(JJJ[B)Z", (void*)device_set_buffer },
		{ (char*)"set_buffer_1", (char*)"(JJ[B)Z", (void*)device_set_buffer_1 },
		{ (char*)"set_buffer_2", (char*)"(JJJ)Z", (void*)device_set_buffer_2 },
		{ (char*)"get_buffer", (char*)"(JJJ[B)Z", (void*)device_get_buffer },
		{ (char*)"get_buffer_1", (char*)"(JJ[B)Z", (void*)device_get_buffer_1 },
		{ (char*)"get_buffer_2", (char*)"(JJJ)Z", (void*)device_get_buffer_2 },
		{ (char*)"map_buffer", (char*)"(JJJJ)J", (void*)device_map_buffer },
		{ (char*)"map_buffer_1", (char*)"(JJJ)J", (void*)device_map_buffer_1 },
		{ (char*)"map_buffer_2", (char*)"(JJ)J", (void*)device_map_buffer_2 },
		{ (char*)"unmap_buffer", (char*)"(JJ)Z", (void*)device_unmap_buffer },
		{ (char*)"copy_buffer", (char*)"(JJJJJJ)Z", (void*)device_copy_buffer },
		{ (char*)"copy_buffer_1", (char*)"(JJJJJ)Z", (void*)device_copy_buffer_1 },
		{ (char*)"copy_buffer_2", (char*)"(JJJJ)Z", (void*)device_copy_buffer_2 },
		{ (char*)"copy_buffer_3", (char*)"(JJJ)Z", (void*)device_copy_buffer_3 },
		{ (char*)"clear_buffer", (char*)"(JJIJ[B)Z", (void*)device_clear_buffer },
		{ (char*)"clear_buffer_1", (char*)"(JJI[B)Z", (void*)device_clear_buffer_1 },
		{ (char*)"clear_buffer_2", (char*)"(JJIJ)Z", (void*)device_clear_buffer_2 },
		{ (char*)"clear_buffer_3", (char*)"(JJ)Z", (void*)device_clear_buffer_3 },
		{ (char*)"flush_buffer", (char*)"(JJI)Z", (void*)device_flush_buffer },
		{ (char*)"flush_buffers", (char*)"(J[JI)Z", (void*)device_flush_buffers },
		{ (char*)"release_buffer", (char*)"(JJ)V", (void*)device_release_buffer },
		{ (char*)"release_sampler", (char*)"(JJ)V", (void*)device_release_sampler },
		{ (char*)"set_texture", (char*)"(JJJJJJ)Z", (void*)device_set_texture },
		{ (char*)"set_texture_1", (char*)"(JJJJ)Z", (void*)device_set_texture_1 },
		{ (char*)"set_texture_2", (char*)"(JJJJ)Z", (void*)device_set_texture_2 },
		{ (char*)"set_texture_3", (char*)"(JJJ)Z", (void*)device_set_texture_3 },
		{ (char*)"get_texture", (char*)"(JJJJJ)Z", (void*)device_get_texture },
		{ (char*)"get_texture_1", (char*)"(JJJJ)Z", (void*)device_get_texture_1 },
		{ (char*)"get_texture_2", (char*)"(JJJ)Z", (void*)device_get_texture_2 },
		{ (char*)"copy_texture", (char*)"(JJJJJJJ)Z", (void*)device_copy_texture },
		{ (char*)"copy_texture_1", (char*)"(JJJJJ)Z", (void*)device_copy_texture_1 },
		{ (char*)"copy_texture_2", (char*)"(JJJJJ)Z", (void*)device_copy_texture_2 },
		{ (char*)"copy_texture_3", (char*)"(JJJ)Z", (void*)device_copy_texture_3 },
		{ (char*)"clear_texture", (char*)"(JJJJJ)Z", (void*)device_clear_texture },
		{ (char*)"clear_texture_1", (char*)"(JJJJ)Z", (void*)device_clear_texture_1 },
		{ (char*)"clear_texture_2", (char*)"(JJJJ)Z", (void*)device_clear_texture_2 },
		{ (char*)"clear_texture_3", (char*)"(JJJ)Z", (void*)device_clear_texture_3 },
		{ (char*)"bind_texture", (char*)"(JJ[J[JZJ)Z", (void*)device_bind_texture },
		{ (char*)"bind_texture_1", (char*)"(JJ[J[JZ)Z", (void*)device_bind_texture_1 },
		{ (char*)"bind_texture_2", (char*)"(JJJJZJ)Z", (void*)device_bind_texture_2 },
		{ (char*)"bind_texture_3", (char*)"(JJJJZ)Z", (void*)device_bind_texture_3 },
		{ (char*)"create_mipmaps", (char*)"(JJJ)Z", (void*)device_create_mipmaps },
		{ (char*)"create_mipmaps_1", (char*)"(JJ)Z", (void*)device_create_mipmaps_1 },
		{ (char*)"flush_texture", (char*)"(JJI)Z", (void*)device_flush_texture },
		{ (char*)"flush_texture_1", (char*)"(JJJI)Z", (void*)device_flush_texture_1 },
		{ (char*)"flush_textures", (char*)"(J[JI)Z", (void*)device_flush_textures },
		{ (char*)"release_texture", (char*)"(JJ)V", (void*)device_release_texture },
		{ (char*)"set_tracing", (char*)"(JJ[J)Z", (void*)device_set_tracing },
		{ (char*)"build_tracing", (char*)"(JJJI)Z", (void*)device_build_tracing },
		{ (char*)"build_tracing_1", (char*)"(JJJJI)Z", (void*)device_build_tracing_1 },
		{ (char*)"build_tracings", (char*)"(J[JJI)Z", (void*)device_build_tracings },
		{ (char*)"build_tracings_1", (char*)"(J[JJJI)Z", (void*)device_build_tracings_1 },
		{ (char*)"copy_tracing", (char*)"(JJJJ)Z", (void*)device_copy_tracing },
		{ (char*)"copy_tracings", (char*)"(J[JJJJ)Z", (void*)device_copy_tracings },
		{ (char*)"flush_tracing", (char*)"(JJ)Z", (void*)device_flush_tracing },
		{ (char*)"flush_tracings", (char*)"(J[J)Z", (void*)device_flush_tracings },
		{ (char*)"release_tracing", (char*)"(JJ)V", (void*)device_release_tracing },
		{ (char*)"set_buffer_table", (char*)"(JJIJZ)Z", (void*)device_set_buffer_table },
		{ (char*)"set_buffer_table_1", (char*)"(JJI[JZ)Z", (void*)device_set_buffer_table_1 },
		{ (char*)"release_buffer_table", (char*)"(JJ)V", (void*)device_release_buffer_table },
		{ (char*)"set_texture_table", (char*)"(JJIJZ)Z", (void*)device_set_texture_table },
		{ (char*)"set_texture_table_1", (char*)"(JJI[JZ)Z", (void*)device_set_texture_table_1 },
		{ (char*)"release_texture_table", (char*)"(JJ)V", (void*)device_release_texture_table },
		{ (char*)"begin_query", (char*)"(JJ)Z", (void*)device_begin_query },
		{ (char*)"end_query", (char*)"(JJ)V", (void*)device_end_query },
		{ (char*)"copy_query", (char*)"(JJJJ)Z", (void*)device_copy_query },
		{ (char*)"copy_queries", (char*)"(J[JJJJ)Z", (void*)device_copy_queries },
		{ (char*)"wait_fence", (char*)"(JJ)Z", (void*)device_wait_fence },
		{ (char*)"signal_fence", (char*)"(JJ)Z", (void*)device_signal_fence },
		{ (char*)"execute_", (char*)"(JJ)Z", (void*)device_execute },
		{ (char*)"flip_", (char*)"(JJ)Z", (void*)device_flip },
		{ (char*)"flip_1", (char*)"(J)Z", (void*)device_flip_1 },
		{ (char*)"flush_", (char*)"(J)Z", (void*)device_flush },
		{ (char*)"finish_", (char*)"(J)Z", (void*)device_finish },
		{ (char*)"check_", (char*)"(J)Z", (void*)device_check },
	};
	
	// Tellusim::D3D12Device
	static jlong d3d12_device_new(TS_JNI_ARGS) {
		return newD3D12Device();
	}
	static jlong d3d12_device_new_1(TS_JNI_ARGS, jlong context) {
		return newD3D12Device(toContext(context));
	}
	static jlong d3d12_device_new_2(TS_JNI_ARGS, jlong surface) {
		return newD3D12Device(toSurface(surface));
	}
	static jlong d3d12_device_new_3(TS_JNI_ARGS, jlong window) {
		return newD3D12Device(toWindow(window));
	}
	static void d3d12_device_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Device*)self;
	}
	static jboolean d3d12_device_equal_device_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Device(self).operator==(toDevice(base));
	}
	static jlong d3d12_device_cast_device_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Device(toDevice(self));
	}
	static jlong d3d12_device_base_device_ptr(TS_JNI_ARGS, jlong self) {
		return newDevice(toD3D12Device(self).getDevice());
	}
	static void d3d12_device_set_buffer_state(TS_JNI_ARGS, jlong self, jlong buffer, jint state) {
		toD3D12Device(self).setBufferState(toBuffer(buffer), (uint32_t)state);
	}
	static void d3d12_device_set_texture_state(TS_JNI_ARGS, jlong self, jlong texture, jint state) {
		toD3D12Device(self).setTextureState(toTexture(texture), (uint32_t)state);
	}
	static jlong d3d12_device_get_d3d12_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Device(self).getD3D12Device();
	}
	static jlong d3d12_device_get_queue(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Device(self).getQueue();
	}
	static jlong d3d12_device_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Device(self).getCommand();
	}
	static const JNINativeMethod d3d12_device_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_device_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)d3d12_device_new_1 },
		{ (char*)"new_2", (char*)"(J)J", (void*)d3d12_device_new_2 },
		{ (char*)"new_3", (char*)"(J)J", (void*)d3d12_device_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_device_delete },
		{ (char*)"equal_device_ptr", (char*)"(JJ)Z", (void*)d3d12_device_equal_device_ptr },
		{ (char*)"cast_device_ptr", (char*)"(J)J", (void*)d3d12_device_cast_device_ptr },
		{ (char*)"base_device_ptr", (char*)"(J)J", (void*)d3d12_device_base_device_ptr },
		{ (char*)"set_buffer_state", (char*)"(JJI)V", (void*)d3d12_device_set_buffer_state },
		{ (char*)"set_texture_state", (char*)"(JJI)V", (void*)d3d12_device_set_texture_state },
		{ (char*)"get_d3d12_device", (char*)"(J)J", (void*)d3d12_device_get_d3d12_device },
		{ (char*)"get_queue", (char*)"(J)J", (void*)d3d12_device_get_queue },
		{ (char*)"get_command", (char*)"(J)J", (void*)d3d12_device_get_command },
	};
	
	// Tellusim::D3D11Device
	static jlong d3d11_device_new(TS_JNI_ARGS) {
		return newD3D11Device();
	}
	static jlong d3d11_device_new_1(TS_JNI_ARGS, jlong context) {
		return newD3D11Device(toContext(context));
	}
	static jlong d3d11_device_new_2(TS_JNI_ARGS, jlong surface) {
		return newD3D11Device(toSurface(surface));
	}
	static jlong d3d11_device_new_3(TS_JNI_ARGS, jlong window) {
		return newD3D11Device(toWindow(window));
	}
	static void d3d11_device_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D11Device*)self;
	}
	static jboolean d3d11_device_equal_device_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D11Device(self).operator==(toDevice(base));
	}
	static jlong d3d11_device_cast_device_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D11Device(toDevice(self));
	}
	static jlong d3d11_device_base_device_ptr(TS_JNI_ARGS, jlong self) {
		return newDevice(toD3D11Device(self).getDevice());
	}
	static jlong d3d11_device_get_d3d11_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Device(self).getD3D11Device();
	}
	static jlong d3d11_device_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Device(self).getCommand();
	}
	static const JNINativeMethod d3d11_device_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d11_device_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)d3d11_device_new_1 },
		{ (char*)"new_2", (char*)"(J)J", (void*)d3d11_device_new_2 },
		{ (char*)"new_3", (char*)"(J)J", (void*)d3d11_device_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d11_device_delete },
		{ (char*)"equal_device_ptr", (char*)"(JJ)Z", (void*)d3d11_device_equal_device_ptr },
		{ (char*)"cast_device_ptr", (char*)"(J)J", (void*)d3d11_device_cast_device_ptr },
		{ (char*)"base_device_ptr", (char*)"(J)J", (void*)d3d11_device_base_device_ptr },
		{ (char*)"get_d3d11_device", (char*)"(J)J", (void*)d3d11_device_get_d3d11_device },
		{ (char*)"get_command", (char*)"(J)J", (void*)d3d11_device_get_command },
	};
	
	// Tellusim::MTLDevice
	static jlong mtl_device_new(TS_JNI_ARGS) {
		return newMTLDevice();
	}
	static jlong mtl_device_new_1(TS_JNI_ARGS, jlong context) {
		return newMTLDevice(toContext(context));
	}
	static jlong mtl_device_new_2(TS_JNI_ARGS, jlong surface) {
		return newMTLDevice(toSurface(surface));
	}
	static jlong mtl_device_new_3(TS_JNI_ARGS, jlong window) {
		return newMTLDevice(toWindow(window));
	}
	static void mtl_device_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLDevice*)self;
	}
	static jboolean mtl_device_equal_device_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLDevice(self).operator==(toDevice(base));
	}
	static jlong mtl_device_cast_device_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLDevice(toDevice(self));
	}
	static jlong mtl_device_base_device_ptr(TS_JNI_ARGS, jlong self) {
		return newDevice(toMTLDevice(self).getDevice());
	}
	static jlong mtl_device_get_mtl_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLDevice(self).getMTLDevice();
	}
	static jlong mtl_device_get_queue(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLDevice(self).getQueue();
	}
	static jlong mtl_device_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLDevice(self).getCommand();
	}
	static jlong mtl_device_get_encoder(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLDevice(self).getEncoder();
	}
	static jlong mtl_device_get_render_encoder(TS_JNI_ARGS, jlong self, jlong descriptor) {
		return (jlong)toMTLDevice(self).getRenderEncoder((void*)descriptor);
	}
	static jlong mtl_device_get_compute_encoder(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLDevice(self).getComputeEncoder();
	}
	static jlong mtl_device_get_tracing_encoder(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLDevice(self).getTracingEncoder();
	}
	static jlong mtl_device_get_blit_encoder(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLDevice(self).getBlitEncoder();
	}
	static void mtl_device_end_encoder(TS_JNI_ARGS, jlong self) {
		toMTLDevice(self).endEncoder();
	}
	static const JNINativeMethod mtl_device_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_device_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)mtl_device_new_1 },
		{ (char*)"new_2", (char*)"(J)J", (void*)mtl_device_new_2 },
		{ (char*)"new_3", (char*)"(J)J", (void*)mtl_device_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_device_delete },
		{ (char*)"equal_device_ptr", (char*)"(JJ)Z", (void*)mtl_device_equal_device_ptr },
		{ (char*)"cast_device_ptr", (char*)"(J)J", (void*)mtl_device_cast_device_ptr },
		{ (char*)"base_device_ptr", (char*)"(J)J", (void*)mtl_device_base_device_ptr },
		{ (char*)"get_mtl_device", (char*)"(J)J", (void*)mtl_device_get_mtl_device },
		{ (char*)"get_queue", (char*)"(J)J", (void*)mtl_device_get_queue },
		{ (char*)"get_command", (char*)"(J)J", (void*)mtl_device_get_command },
		{ (char*)"get_encoder", (char*)"(J)J", (void*)mtl_device_get_encoder },
		{ (char*)"get_render_encoder", (char*)"(JJ)J", (void*)mtl_device_get_render_encoder },
		{ (char*)"get_compute_encoder", (char*)"(J)J", (void*)mtl_device_get_compute_encoder },
		{ (char*)"get_tracing_encoder", (char*)"(J)J", (void*)mtl_device_get_tracing_encoder },
		{ (char*)"get_blit_encoder", (char*)"(J)J", (void*)mtl_device_get_blit_encoder },
		{ (char*)"end_encoder", (char*)"(J)V", (void*)mtl_device_end_encoder },
	};
	
	// Tellusim::VKDevice
	static jlong vk_device_new(TS_JNI_ARGS) {
		return newVKDevice();
	}
	static jlong vk_device_new_1(TS_JNI_ARGS, jlong context) {
		return newVKDevice(toContext(context));
	}
	static jlong vk_device_new_2(TS_JNI_ARGS, jlong surface) {
		return newVKDevice(toSurface(surface));
	}
	static jlong vk_device_new_3(TS_JNI_ARGS, jlong window) {
		return newVKDevice(toWindow(window));
	}
	static void vk_device_delete(TS_JNI_ARGS, jlong self) {
		delete (VKDevice*)self;
	}
	static jboolean vk_device_equal_device_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKDevice(self).operator==(toDevice(base));
	}
	static jlong vk_device_cast_device_ptr(TS_JNI_ARGS, jlong self) {
		return newVKDevice(toDevice(self));
	}
	static jlong vk_device_base_device_ptr(TS_JNI_ARGS, jlong self) {
		return newDevice(toVKDevice(self).getDevice());
	}
	static void vk_device_set_buffer_access(TS_JNI_ARGS, jlong self, jlong buffer, jint access) {
		toVKDevice(self).setBufferAccess(toBuffer(buffer), (uint32_t)access);
	}
	static void vk_device_set_texture_layout(TS_JNI_ARGS, jlong self, jlong texture, jint layout) {
		toVKDevice(self).setTextureLayout(toTexture(texture), (uint32_t)layout);
	}
	static jboolean vk_device_wait_vk_fence(TS_JNI_ARGS, jlong self, jlong fence, jlong timeout, jboolean reset) {
		return toVKDevice(self).waitVKFence((void*)fence, (uint64_t)timeout, (bool)reset);
	}
	static jboolean vk_device_signal_vk_fence(TS_JNI_ARGS, jlong self, jlong fence) {
		return toVKDevice(self).signalVKFence((void*)fence);
	}
	static void vk_device_wait_semaphore(TS_JNI_ARGS, jlong self, jlong semaphore, jint mask) {
		toVKDevice(self).waitSemaphore((void*)semaphore, (uint32_t)mask);
	}
	static void vk_device_signal_semaphore(TS_JNI_ARGS, jlong self, jlong semaphore) {
		toVKDevice(self).signalSemaphore((void*)semaphore);
	}
	static jboolean vk_device_has_memory_type(TS_JNI_ARGS, jlong self, jint flags) {
		return toVKDevice(self).hasMemoryType((uint32_t)flags);
	}
	static jint vk_device_get_memory_index(TS_JNI_ARGS, jlong self, jint types, jint flags) {
		return toVKDevice(self).getMemoryIndex((uint32_t)types, (uint32_t)flags);
	}
	static jlong vk_device_get_instance(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKDevice(self).getInstance();
	}
	static jlong vk_device_get_adapter(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKDevice(self).getAdapter();
	}
	static jlong vk_device_get_vk_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKDevice(self).getVKDevice();
	}
	static jlong vk_device_get_queue(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKDevice(self).getQueue();
	}
	static jlong vk_device_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKDevice(self).getCommand();
	}
	static jint vk_device_get_family(TS_JNI_ARGS, jlong self) {
		return toVKDevice(self).getFamily();
	}
	static const JNINativeMethod vk_device_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_device_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)vk_device_new_1 },
		{ (char*)"new_2", (char*)"(J)J", (void*)vk_device_new_2 },
		{ (char*)"new_3", (char*)"(J)J", (void*)vk_device_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_device_delete },
		{ (char*)"equal_device_ptr", (char*)"(JJ)Z", (void*)vk_device_equal_device_ptr },
		{ (char*)"cast_device_ptr", (char*)"(J)J", (void*)vk_device_cast_device_ptr },
		{ (char*)"base_device_ptr", (char*)"(J)J", (void*)vk_device_base_device_ptr },
		{ (char*)"set_buffer_access", (char*)"(JJI)V", (void*)vk_device_set_buffer_access },
		{ (char*)"set_texture_layout", (char*)"(JJI)V", (void*)vk_device_set_texture_layout },
		{ (char*)"wait_vk_fence", (char*)"(JJJZ)Z", (void*)vk_device_wait_vk_fence },
		{ (char*)"signal_vk_fence", (char*)"(JJ)Z", (void*)vk_device_signal_vk_fence },
		{ (char*)"wait_semaphore", (char*)"(JJI)V", (void*)vk_device_wait_semaphore },
		{ (char*)"signal_semaphore", (char*)"(JJ)V", (void*)vk_device_signal_semaphore },
		{ (char*)"has_memory_type", (char*)"(JI)Z", (void*)vk_device_has_memory_type },
		{ (char*)"get_memory_index", (char*)"(JII)I", (void*)vk_device_get_memory_index },
		{ (char*)"get_instance", (char*)"(J)J", (void*)vk_device_get_instance },
		{ (char*)"get_adapter", (char*)"(J)J", (void*)vk_device_get_adapter },
		{ (char*)"get_vk_device", (char*)"(J)J", (void*)vk_device_get_vk_device },
		{ (char*)"get_queue", (char*)"(J)J", (void*)vk_device_get_queue },
		{ (char*)"get_command", (char*)"(J)J", (void*)vk_device_get_command },
		{ (char*)"get_family", (char*)"(J)I", (void*)vk_device_get_family },
	};
	
	// Tellusim::FUDevice
	static jlong fu_device_new(TS_JNI_ARGS) {
		return newFUDevice();
	}
	static jlong fu_device_new_1(TS_JNI_ARGS, jlongArray devices, jboolean owner) {
		Array<Device> devices_((uint32_t)env->GetArrayLength(devices));
		jlong *devices__ = env->GetLongArrayElements(devices, nullptr);
		for(uint32_t i = 0; i < devices_.size(); i++) devices_[i] = toDevice(devices__[i]);
		jlong ret_ = newFUDevice(devices_, (bool)owner);
		if(devices__) env->ReleaseLongArrayElements(devices, devices__, 0);
		return ret_;
	}
	static void fu_device_delete(TS_JNI_ARGS, jlong self) {
		delete (FUDevice*)self;
	}
	static jboolean fu_device_equal_device_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUDevice(self).operator==(toDevice(base));
	}
	static jlong fu_device_cast_device_ptr(TS_JNI_ARGS, jlong self) {
		return newFUDevice(toDevice(self));
	}
	static jlong fu_device_base_device_ptr(TS_JNI_ARGS, jlong self) {
		return newDevice(toFUDevice(self).getDevice());
	}
	static void fu_device_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUDevice(self).setMask((uint32_t)mask);
	}
	static jint fu_device_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUDevice(self).getMask();
	}
	static jint fu_device_get_num_devices(TS_JNI_ARGS, jlong self) {
		return toFUDevice(self).getNumDevices();
	}
	static jlong fu_device_get_device(TS_JNI_ARGS, jlong self, jint index) {
		return newDevice(toFUDevice(self).getDevice((uint32_t)index));
	}
	static jlong fu_device_get_device_1(TS_JNI_ARGS, jlong self, jint index) {
		return newDevice(toFUDevice(self).getDevice((uint32_t)index));
	}
	static const JNINativeMethod fu_device_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_device_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_device_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_device_delete },
		{ (char*)"equal_device_ptr", (char*)"(JJ)Z", (void*)fu_device_equal_device_ptr },
		{ (char*)"cast_device_ptr", (char*)"(J)J", (void*)fu_device_cast_device_ptr },
		{ (char*)"base_device_ptr", (char*)"(J)J", (void*)fu_device_base_device_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_device_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_device_get_mask },
		{ (char*)"get_num_devices", (char*)"(J)I", (void*)fu_device_get_num_devices },
		{ (char*)"get_device", (char*)"(JI)J", (void*)fu_device_get_device },
		{ (char*)"get_device_1", (char*)"(JI)J", (void*)fu_device_get_device_1 },
	};
	
	// Tellusim::Kernel
	static jlong kernel_new(TS_JNI_ARGS) {
		return newKernel();
	}
	static void kernel_delete(TS_JNI_ARGS, jlong self) {
		delete (Kernel*)self;
	}
	static jboolean kernel_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toKernel(self) == toKernel(ptr));
	}
	static jlong kernel_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newKernel(toKernel(self).clonePtr());
	}
	static void kernel_clear_ptr(TS_JNI_ARGS, jlong self) {
		toKernel(self).clearPtr();
	}
	static void kernel_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toKernel(self).destroyPtr();
	}
	static void kernel_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toKernel(self).acquirePtr();
	}
	static void kernel_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toKernel(self).unacquirePtr();
	}
	static jboolean kernel_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toKernel(self).isValidPtr();
	}
	static jboolean kernel_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toKernel(self).isOwnerPtr();
	}
	static jboolean kernel_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toKernel(self).isConstPtr();
	}
	static jint kernel_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getCountPtr();
	}
	static jlong kernel_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toKernel(self).getInternalPtr();
	}
	static jint kernel_get_platform(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getPlatform();
	}
	static jstring kernel_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toKernel(self).getPlatformName());
	}
	static jint kernel_get_index(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getIndex();
	}
	static void kernel_clear(TS_JNI_ARGS, jlong self) {
		toKernel(self).clear();
	}
	static jboolean kernel_is_created(TS_JNI_ARGS, jlong self) {
		return toKernel(self).isCreated();
	}
	static void kernel_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toKernel(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring kernel_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toKernel(self).getName().get());
	}
	static jboolean kernel_create(TS_JNI_ARGS, jlong self) {
		return toKernel(self).create();
	}
	static void kernel_set_parameters(TS_JNI_ARGS, jlong self, jlong kernel) {
		toKernel(self).setParameters(toKernel(kernel));
	}
	static jboolean kernel_save_state(TS_JNI_ARGS, jlong self, jlong stream) {
		return toKernel(self).saveState(toStream(stream));
	}
	static void kernel_set_shader(TS_JNI_ARGS, jlong self, jlong shader, jboolean owner) {
		toKernel(self).setShader(toShader(shader), (bool)owner);
	}
	static jlong kernel_get_compute_shader(TS_JNI_ARGS, jlong self) {
		return newShader(toKernel(self).getComputeShader());
	}
	static jboolean kernel_load_shader(TS_JNI_ARGS, jlong self, jstring name, jstring format) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toKernel(self).loadShader(name_, "%s", format_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean kernel_load_shader_glsl(TS_JNI_ARGS, jlong self, jstring name, jstring format) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toKernel(self).loadShaderGLSL(name_, "%s", format_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean kernel_load_shader_1(TS_JNI_ARGS, jlong self, jstring name, jlong macros, jstringArray includes, jint size) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toKernel(self).loadShader(name_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(name, name_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean kernel_load_shader_glsl_1(TS_JNI_ARGS, jlong self, jstring name, jlong macros, jstringArray includes, jint size) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toKernel(self).loadShaderGLSL(name_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(name, name_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean kernel_load_shader_spirv(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toKernel(self).loadShaderSPIRV(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean kernel_create_shader(TS_JNI_ARGS, jlong self, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toKernel(self).createShader(src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean kernel_create_shader_glsl(TS_JNI_ARGS, jlong self, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toKernel(self).createShaderGLSL(src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean kernel_create_shader_1(TS_JNI_ARGS, jlong self, jstring src, jlong macros, jstringArray includes, jint size) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toKernel(self).createShader(src_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(src, src_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean kernel_create_shader_glsl_1(TS_JNI_ARGS, jlong self, jstring src, jlong macros, jstringArray includes, jint size) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toKernel(self).createShaderGLSL(src_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(src, src_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean kernel_create_shader_spirv(TS_JNI_ARGS, jlong self, jintArray data) {
		uint32_t *data__ = (uint32_t*)env->GetIntArrayElements(data, nullptr);
		Array<uint32_t> data_((uint32_t)env->GetArrayLength(data), data__);
		bool ret_ = toKernel(self).createShaderSPIRV(data_);
		if(data_) env->ReleaseIntArrayElements(data, (jint*)data__, 0);
		return ret_;
	}
	static jint kernel_add_sampler(TS_JNI_ARGS, jlong self) {
		return toKernel(self).addSampler();
	}
	static jlong kernel_set_samplers(TS_JNI_ARGS, jlong self, jint num) {
		return newKernel(toKernel(self).setSamplers((uint32_t)num));
	}
	static jint kernel_get_num_samplers(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getNumSamplers();
	}
	static jlong kernel_set_sampler_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newKernel(toKernel(self).setSamplerOffset((uint32_t)offset));
	}
	static jint kernel_get_sampler_offset(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getSamplerOffset();
	}
	static jlong kernel_set_sampler_array(TS_JNI_ARGS, jlong self, jint index, jint num, jboolean array) {
		return newKernel(toKernel(self).setSamplerArray((uint32_t)index, (uint32_t)num, (bool)array));
	}
	static jint kernel_get_sampler_array(TS_JNI_ARGS, jlong self, jint index) {
		return toKernel(self).getSamplerArray((uint32_t)index);
	}
	static jint kernel_add_texture(TS_JNI_ARGS, jlong self) {
		return toKernel(self).addTexture();
	}
	static jlong kernel_set_textures(TS_JNI_ARGS, jlong self, jint num) {
		return newKernel(toKernel(self).setTextures((uint32_t)num));
	}
	static jint kernel_get_num_textures(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getNumTextures();
	}
	static jlong kernel_set_texture_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newKernel(toKernel(self).setTextureOffset((uint32_t)offset));
	}
	static jint kernel_get_texture_offset(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getTextureOffset();
	}
	static jlong kernel_set_texture_array(TS_JNI_ARGS, jlong self, jint index, jint num, jboolean array) {
		return newKernel(toKernel(self).setTextureArray((uint32_t)index, (uint32_t)num, (bool)array));
	}
	static jint kernel_get_texture_array(TS_JNI_ARGS, jlong self, jint index) {
		return toKernel(self).getTextureArray((uint32_t)index);
	}
	static jint kernel_add_surface(TS_JNI_ARGS, jlong self) {
		return toKernel(self).addSurface();
	}
	static jlong kernel_set_surfaces(TS_JNI_ARGS, jlong self, jint num) {
		return newKernel(toKernel(self).setSurfaces((uint32_t)num));
	}
	static jint kernel_get_num_surfaces(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getNumSurfaces();
	}
	static jlong kernel_set_surface_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newKernel(toKernel(self).setSurfaceOffset((uint32_t)offset));
	}
	static jint kernel_get_surface_offset(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getSurfaceOffset();
	}
	static jlong kernel_set_surface_array(TS_JNI_ARGS, jlong self, jint index, jint num, jboolean array) {
		return newKernel(toKernel(self).setSurfaceArray((uint32_t)index, (uint32_t)num, (bool)array));
	}
	static jint kernel_get_surface_array(TS_JNI_ARGS, jlong self, jint index) {
		return toKernel(self).getSurfaceArray((uint32_t)index);
	}
	static jint kernel_add_uniform(TS_JNI_ARGS, jlong self, jint flags) {
		return toKernel(self).addUniform((BindFlags)flags);
	}
	static jlong kernel_set_uniforms(TS_JNI_ARGS, jlong self, jint num, jint flags) {
		return newKernel(toKernel(self).setUniforms((uint32_t)num, (BindFlags)flags));
	}
	static jint kernel_get_num_uniforms(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getNumUniforms();
	}
	static jlong kernel_set_uniform_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newKernel(toKernel(self).setUniformOffset((uint32_t)offset));
	}
	static jint kernel_get_uniform_offset(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getUniformOffset();
	}
	static jlong kernel_set_uniform_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return newKernel(toKernel(self).setUniformFlags((uint32_t)index, (BindFlags)flags));
	}
	static jint kernel_get_uniform_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toKernel(self).getUniformFlags((uint32_t)index);
	}
	static jint kernel_add_storage(TS_JNI_ARGS, jlong self, jint flags) {
		return toKernel(self).addStorage((BindFlags)flags);
	}
	static jlong kernel_set_storages(TS_JNI_ARGS, jlong self, jint num, jint flags) {
		return newKernel(toKernel(self).setStorages((uint32_t)num, (BindFlags)flags));
	}
	static jint kernel_get_num_storages(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getNumStorages();
	}
	static jlong kernel_set_storage_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newKernel(toKernel(self).setStorageOffset((uint32_t)offset));
	}
	static jint kernel_get_storage_offset(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getStorageOffset();
	}
	static jlong kernel_set_storage_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return newKernel(toKernel(self).setStorageFlags((uint32_t)index, (BindFlags)flags));
	}
	static jint kernel_get_storage_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toKernel(self).getStorageFlags((uint32_t)index);
	}
	static jint kernel_add_tracing(TS_JNI_ARGS, jlong self) {
		return toKernel(self).addTracing();
	}
	static jlong kernel_set_tracings(TS_JNI_ARGS, jlong self, jint num) {
		return newKernel(toKernel(self).setTracings((uint32_t)num));
	}
	static jint kernel_get_num_tracings(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getNumTracings();
	}
	static jlong kernel_set_tracing_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newKernel(toKernel(self).setTracingOffset((uint32_t)offset));
	}
	static jint kernel_get_tracing_offset(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getTracingOffset();
	}
	static jint kernel_add_texel(TS_JNI_ARGS, jlong self) {
		return toKernel(self).addTexel();
	}
	static jlong kernel_set_texels(TS_JNI_ARGS, jlong self, jint num) {
		return newKernel(toKernel(self).setTexels((uint32_t)num));
	}
	static jint kernel_get_num_texels(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getNumTexels();
	}
	static jlong kernel_set_texel_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newKernel(toKernel(self).setTexelOffset((uint32_t)offset));
	}
	static jint kernel_get_texel_offset(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getTexelOffset();
	}
	static jint kernel_add_table(TS_JNI_ARGS, jlong self, jint type, jint size) {
		return toKernel(self).addTable((TableType)type, (uint32_t)size);
	}
	static jint kernel_get_num_tables(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getNumTables();
	}
	static jlong kernel_set_table_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newKernel(toKernel(self).setTableOffset((uint32_t)offset));
	}
	static jint kernel_get_table_offset(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getTableOffset();
	}
	static jlong kernel_set_table_type(TS_JNI_ARGS, jlong self, jint index, jint type, jint size, jint flags) {
		return newKernel(toKernel(self).setTableType((uint32_t)index, (TableType)type, (uint32_t)size, (BindFlags)flags));
	}
	static jint kernel_get_table_type(TS_JNI_ARGS, jlong self, jint index) {
		return toKernel(self).getTableType((uint32_t)index);
	}
	static jint kernel_get_table_size(TS_JNI_ARGS, jlong self, jint index) {
		return toKernel(self).getTableSize((uint32_t)index);
	}
	static jlong kernel_set_table_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return newKernel(toKernel(self).setTableFlags((uint32_t)index, (BindFlags)flags));
	}
	static jint kernel_get_table_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toKernel(self).getTableFlags((uint32_t)index);
	}
	static void kernel_set_group_size(TS_JNI_ARGS, jlong self, jint width, jint height, jint depth) {
		toKernel(self).setGroupSize((uint32_t)width, (uint32_t)height, (uint32_t)depth);
	}
	static jint kernel_get_group_size_x(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getGroupSizeX();
	}
	static jint kernel_get_group_size_y(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getGroupSizeY();
	}
	static jint kernel_get_group_size_z(TS_JNI_ARGS, jlong self) {
		return toKernel(self).getGroupSizeZ();
	}
	static const JNINativeMethod kernel_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)kernel_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)kernel_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)kernel_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)kernel_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)kernel_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)kernel_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)kernel_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)kernel_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)kernel_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)kernel_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)kernel_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)kernel_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)kernel_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)kernel_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)kernel_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)kernel_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)kernel_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)kernel_is_created },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)kernel_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)kernel_get_name },
		{ (char*)"create_", (char*)"(J)Z", (void*)kernel_create },
		{ (char*)"set_parameters", (char*)"(JJ)V", (void*)kernel_set_parameters },
		{ (char*)"save_state", (char*)"(JJ)Z", (void*)kernel_save_state },
		{ (char*)"set_shader", (char*)"(JJZ)V", (void*)kernel_set_shader },
		{ (char*)"get_compute_shader", (char*)"(J)J", (void*)kernel_get_compute_shader },
		{ (char*)"load_shader", (char*)"(JLjava/lang/String;Ljava/lang/String;)Z", (void*)kernel_load_shader },
		{ (char*)"load_shader_glsl", (char*)"(JLjava/lang/String;Ljava/lang/String;)Z", (void*)kernel_load_shader_glsl },
		{ (char*)"load_shader_1", (char*)"(JLjava/lang/String;J[Ljava/lang/String;I)Z", (void*)kernel_load_shader_1 },
		{ (char*)"load_shader_glsl_1", (char*)"(JLjava/lang/String;J[Ljava/lang/String;I)Z", (void*)kernel_load_shader_glsl_1 },
		{ (char*)"load_shader_spirv", (char*)"(JLjava/lang/String;)Z", (void*)kernel_load_shader_spirv },
		{ (char*)"create_shader", (char*)"(JLjava/lang/String;Ljava/lang/String;)Z", (void*)kernel_create_shader },
		{ (char*)"create_shader_glsl", (char*)"(JLjava/lang/String;Ljava/lang/String;)Z", (void*)kernel_create_shader_glsl },
		{ (char*)"create_shader_1", (char*)"(JLjava/lang/String;J[Ljava/lang/String;I)Z", (void*)kernel_create_shader_1 },
		{ (char*)"create_shader_glsl_1", (char*)"(JLjava/lang/String;J[Ljava/lang/String;I)Z", (void*)kernel_create_shader_glsl_1 },
		{ (char*)"create_shader_spirv", (char*)"(J[I)Z", (void*)kernel_create_shader_spirv },
		{ (char*)"add_sampler", (char*)"(J)I", (void*)kernel_add_sampler },
		{ (char*)"set_samplers", (char*)"(JI)J", (void*)kernel_set_samplers },
		{ (char*)"get_num_samplers", (char*)"(J)I", (void*)kernel_get_num_samplers },
		{ (char*)"set_sampler_offset", (char*)"(JI)J", (void*)kernel_set_sampler_offset },
		{ (char*)"get_sampler_offset", (char*)"(J)I", (void*)kernel_get_sampler_offset },
		{ (char*)"set_sampler_array", (char*)"(JIIZ)J", (void*)kernel_set_sampler_array },
		{ (char*)"get_sampler_array", (char*)"(JI)I", (void*)kernel_get_sampler_array },
		{ (char*)"add_texture", (char*)"(J)I", (void*)kernel_add_texture },
		{ (char*)"set_textures", (char*)"(JI)J", (void*)kernel_set_textures },
		{ (char*)"get_num_textures", (char*)"(J)I", (void*)kernel_get_num_textures },
		{ (char*)"set_texture_offset", (char*)"(JI)J", (void*)kernel_set_texture_offset },
		{ (char*)"get_texture_offset", (char*)"(J)I", (void*)kernel_get_texture_offset },
		{ (char*)"set_texture_array", (char*)"(JIIZ)J", (void*)kernel_set_texture_array },
		{ (char*)"get_texture_array", (char*)"(JI)I", (void*)kernel_get_texture_array },
		{ (char*)"add_surface", (char*)"(J)I", (void*)kernel_add_surface },
		{ (char*)"set_surfaces", (char*)"(JI)J", (void*)kernel_set_surfaces },
		{ (char*)"get_num_surfaces", (char*)"(J)I", (void*)kernel_get_num_surfaces },
		{ (char*)"set_surface_offset", (char*)"(JI)J", (void*)kernel_set_surface_offset },
		{ (char*)"get_surface_offset", (char*)"(J)I", (void*)kernel_get_surface_offset },
		{ (char*)"set_surface_array", (char*)"(JIIZ)J", (void*)kernel_set_surface_array },
		{ (char*)"get_surface_array", (char*)"(JI)I", (void*)kernel_get_surface_array },
		{ (char*)"add_uniform", (char*)"(JI)I", (void*)kernel_add_uniform },
		{ (char*)"set_uniforms", (char*)"(JII)J", (void*)kernel_set_uniforms },
		{ (char*)"get_num_uniforms", (char*)"(J)I", (void*)kernel_get_num_uniforms },
		{ (char*)"set_uniform_offset", (char*)"(JI)J", (void*)kernel_set_uniform_offset },
		{ (char*)"get_uniform_offset", (char*)"(J)I", (void*)kernel_get_uniform_offset },
		{ (char*)"set_uniform_flags", (char*)"(JII)J", (void*)kernel_set_uniform_flags },
		{ (char*)"get_uniform_flags", (char*)"(JI)I", (void*)kernel_get_uniform_flags },
		{ (char*)"add_storage", (char*)"(JI)I", (void*)kernel_add_storage },
		{ (char*)"set_storages", (char*)"(JII)J", (void*)kernel_set_storages },
		{ (char*)"get_num_storages", (char*)"(J)I", (void*)kernel_get_num_storages },
		{ (char*)"set_storage_offset", (char*)"(JI)J", (void*)kernel_set_storage_offset },
		{ (char*)"get_storage_offset", (char*)"(J)I", (void*)kernel_get_storage_offset },
		{ (char*)"set_storage_flags", (char*)"(JII)J", (void*)kernel_set_storage_flags },
		{ (char*)"get_storage_flags", (char*)"(JI)I", (void*)kernel_get_storage_flags },
		{ (char*)"add_tracing", (char*)"(J)I", (void*)kernel_add_tracing },
		{ (char*)"set_tracings", (char*)"(JI)J", (void*)kernel_set_tracings },
		{ (char*)"get_num_tracings", (char*)"(J)I", (void*)kernel_get_num_tracings },
		{ (char*)"set_tracing_offset", (char*)"(JI)J", (void*)kernel_set_tracing_offset },
		{ (char*)"get_tracing_offset", (char*)"(J)I", (void*)kernel_get_tracing_offset },
		{ (char*)"add_texel", (char*)"(J)I", (void*)kernel_add_texel },
		{ (char*)"set_texels", (char*)"(JI)J", (void*)kernel_set_texels },
		{ (char*)"get_num_texels", (char*)"(J)I", (void*)kernel_get_num_texels },
		{ (char*)"set_texel_offset", (char*)"(JI)J", (void*)kernel_set_texel_offset },
		{ (char*)"get_texel_offset", (char*)"(J)I", (void*)kernel_get_texel_offset },
		{ (char*)"add_table", (char*)"(JII)I", (void*)kernel_add_table },
		{ (char*)"get_num_tables", (char*)"(J)I", (void*)kernel_get_num_tables },
		{ (char*)"set_table_offset", (char*)"(JI)J", (void*)kernel_set_table_offset },
		{ (char*)"get_table_offset", (char*)"(J)I", (void*)kernel_get_table_offset },
		{ (char*)"set_table_type", (char*)"(JIIII)J", (void*)kernel_set_table_type },
		{ (char*)"get_table_type", (char*)"(JI)I", (void*)kernel_get_table_type },
		{ (char*)"get_table_size", (char*)"(JI)I", (void*)kernel_get_table_size },
		{ (char*)"set_table_flags", (char*)"(JII)J", (void*)kernel_set_table_flags },
		{ (char*)"get_table_flags", (char*)"(JI)I", (void*)kernel_get_table_flags },
		{ (char*)"set_group_size", (char*)"(JIII)V", (void*)kernel_set_group_size },
		{ (char*)"get_group_size_x", (char*)"(J)I", (void*)kernel_get_group_size_x },
		{ (char*)"get_group_size_y", (char*)"(J)I", (void*)kernel_get_group_size_y },
		{ (char*)"get_group_size_z", (char*)"(J)I", (void*)kernel_get_group_size_z },
	};
	
	// Tellusim::D3D12Kernel
	static jlong d3d12_kernel_new(TS_JNI_ARGS) {
		return newD3D12Kernel();
	}
	static void d3d12_kernel_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Kernel*)self;
	}
	static jboolean d3d12_kernel_equal_kernel_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Kernel(self).operator==(toKernel(base));
	}
	static jlong d3d12_kernel_cast_kernel_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Kernel(toKernel(self));
	}
	static jlong d3d12_kernel_base_kernel_ptr(TS_JNI_ARGS, jlong self) {
		return newKernel(toD3D12Kernel(self).getKernel());
	}
	static jlong d3d12_kernel_get_root_signature(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Kernel(self).getRootSignature();
	}
	static const JNINativeMethod d3d12_kernel_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_kernel_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_kernel_delete },
		{ (char*)"equal_kernel_ptr", (char*)"(JJ)Z", (void*)d3d12_kernel_equal_kernel_ptr },
		{ (char*)"cast_kernel_ptr", (char*)"(J)J", (void*)d3d12_kernel_cast_kernel_ptr },
		{ (char*)"base_kernel_ptr", (char*)"(J)J", (void*)d3d12_kernel_base_kernel_ptr },
		{ (char*)"get_root_signature", (char*)"(J)J", (void*)d3d12_kernel_get_root_signature },
	};
	
	// Tellusim::MTLKernel
	static jlong mtl_kernel_new(TS_JNI_ARGS) {
		return newMTLKernel();
	}
	static void mtl_kernel_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLKernel*)self;
	}
	static jboolean mtl_kernel_equal_kernel_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLKernel(self).operator==(toKernel(base));
	}
	static jlong mtl_kernel_cast_kernel_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLKernel(toKernel(self));
	}
	static jlong mtl_kernel_base_kernel_ptr(TS_JNI_ARGS, jlong self) {
		return newKernel(toMTLKernel(self).getKernel());
	}
	static void mtl_kernel_set_indirect(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toMTLKernel(self).setIndirect((bool)enabled);
	}
	static jboolean mtl_kernel_is_indirect(TS_JNI_ARGS, jlong self) {
		return toMTLKernel(self).isIndirect();
	}
	static jlong mtl_kernel_get_compute_function(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLKernel(self).getComputeFunction();
	}
	static const JNINativeMethod mtl_kernel_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_kernel_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_kernel_delete },
		{ (char*)"equal_kernel_ptr", (char*)"(JJ)Z", (void*)mtl_kernel_equal_kernel_ptr },
		{ (char*)"cast_kernel_ptr", (char*)"(J)J", (void*)mtl_kernel_cast_kernel_ptr },
		{ (char*)"base_kernel_ptr", (char*)"(J)J", (void*)mtl_kernel_base_kernel_ptr },
		{ (char*)"set_indirect", (char*)"(JZ)V", (void*)mtl_kernel_set_indirect },
		{ (char*)"is_indirect", (char*)"(J)Z", (void*)mtl_kernel_is_indirect },
		{ (char*)"get_compute_function", (char*)"(J)J", (void*)mtl_kernel_get_compute_function },
	};
	
	// Tellusim::FUKernel
	static jlong fu_kernel_new(TS_JNI_ARGS) {
		return newFUKernel();
	}
	static jlong fu_kernel_new_1(TS_JNI_ARGS, jlongArray kernels, jboolean owner) {
		Array<Kernel> kernels_((uint32_t)env->GetArrayLength(kernels));
		jlong *kernels__ = env->GetLongArrayElements(kernels, nullptr);
		for(uint32_t i = 0; i < kernels_.size(); i++) kernels_[i] = toKernel(kernels__[i]);
		jlong ret_ = newFUKernel(kernels_, (bool)owner);
		if(kernels__) env->ReleaseLongArrayElements(kernels, kernels__, 0);
		return ret_;
	}
	static void fu_kernel_delete(TS_JNI_ARGS, jlong self) {
		delete (FUKernel*)self;
	}
	static jboolean fu_kernel_equal_kernel_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUKernel(self).operator==(toKernel(base));
	}
	static jlong fu_kernel_cast_kernel_ptr(TS_JNI_ARGS, jlong self) {
		return newFUKernel(toKernel(self));
	}
	static jlong fu_kernel_base_kernel_ptr(TS_JNI_ARGS, jlong self) {
		return newKernel(toFUKernel(self).getKernel());
	}
	static void fu_kernel_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUKernel(self).setMask((uint32_t)mask);
	}
	static jint fu_kernel_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUKernel(self).getMask();
	}
	static jint fu_kernel_get_num_kernels(TS_JNI_ARGS, jlong self) {
		return toFUKernel(self).getNumKernels();
	}
	static jlong fu_kernel_get_kernel(TS_JNI_ARGS, jlong self, jint index) {
		return newKernel(toFUKernel(self).getKernel((uint32_t)index));
	}
	static jlong fu_kernel_get_kernel_1(TS_JNI_ARGS, jlong self, jint index) {
		return newKernel(toFUKernel(self).getKernel((uint32_t)index));
	}
	static const JNINativeMethod fu_kernel_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_kernel_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_kernel_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_kernel_delete },
		{ (char*)"equal_kernel_ptr", (char*)"(JJ)Z", (void*)fu_kernel_equal_kernel_ptr },
		{ (char*)"cast_kernel_ptr", (char*)"(J)J", (void*)fu_kernel_cast_kernel_ptr },
		{ (char*)"base_kernel_ptr", (char*)"(J)J", (void*)fu_kernel_base_kernel_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_kernel_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_kernel_get_mask },
		{ (char*)"get_num_kernels", (char*)"(J)I", (void*)fu_kernel_get_num_kernels },
		{ (char*)"get_kernel", (char*)"(JI)J", (void*)fu_kernel_get_kernel },
		{ (char*)"get_kernel_1", (char*)"(JI)J", (void*)fu_kernel_get_kernel_1 },
	};
	
	// Tellusim::Pipeline
	static jlong pipeline_new(TS_JNI_ARGS) {
		return newPipeline();
	}
	static void pipeline_delete(TS_JNI_ARGS, jlong self) {
		delete (Pipeline*)self;
	}
	static jboolean pipeline_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toPipeline(self) == toPipeline(ptr));
	}
	static jlong pipeline_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newPipeline(toPipeline(self).clonePtr());
	}
	static void pipeline_clear_ptr(TS_JNI_ARGS, jlong self) {
		toPipeline(self).clearPtr();
	}
	static void pipeline_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toPipeline(self).destroyPtr();
	}
	static void pipeline_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toPipeline(self).acquirePtr();
	}
	static void pipeline_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toPipeline(self).unacquirePtr();
	}
	static jboolean pipeline_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).isValidPtr();
	}
	static jboolean pipeline_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).isOwnerPtr();
	}
	static jboolean pipeline_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).isConstPtr();
	}
	static jint pipeline_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getCountPtr();
	}
	static jlong pipeline_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toPipeline(self).getInternalPtr();
	}
	static jint pipeline_get_platform(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getPlatform();
	}
	static jstring pipeline_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toPipeline(self).getPlatformName());
	}
	static jint pipeline_get_index(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getIndex();
	}
	static void pipeline_clear(TS_JNI_ARGS, jlong self) {
		toPipeline(self).clear();
	}
	static jboolean pipeline_is_created(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).isCreated();
	}
	static void pipeline_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toPipeline(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring pipeline_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toPipeline(self).getName().get());
	}
	static jboolean pipeline_create(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).create();
	}
	static void pipeline_set_parameters(TS_JNI_ARGS, jlong self, jlong pipeline) {
		toPipeline(self).setParameters(toPipeline(pipeline));
	}
	static jboolean pipeline_save_state(TS_JNI_ARGS, jlong self, jlong stream) {
		return toPipeline(self).saveState(toStream(stream));
	}
	static void pipeline_add_shader(TS_JNI_ARGS, jlong self, jlong shader, jboolean owner) {
		toPipeline(self).addShader(toShader(shader), (bool)owner);
	}
	static jlong pipeline_get_vertex_shader(TS_JNI_ARGS, jlong self) {
		return newShader(toPipeline(self).getVertexShader());
	}
	static jlong pipeline_get_control_shader(TS_JNI_ARGS, jlong self) {
		return newShader(toPipeline(self).getControlShader());
	}
	static jlong pipeline_get_evaluate_shader(TS_JNI_ARGS, jlong self) {
		return newShader(toPipeline(self).getEvaluateShader());
	}
	static jlong pipeline_get_geometry_shader(TS_JNI_ARGS, jlong self) {
		return newShader(toPipeline(self).getGeometryShader());
	}
	static jlong pipeline_get_fragment_shader(TS_JNI_ARGS, jlong self) {
		return newShader(toPipeline(self).getFragmentShader());
	}
	static jlong pipeline_get_task_shader(TS_JNI_ARGS, jlong self) {
		return newShader(toPipeline(self).getTaskShader());
	}
	static jlong pipeline_get_mesh_shader(TS_JNI_ARGS, jlong self) {
		return newShader(toPipeline(self).getMeshShader());
	}
	static jboolean pipeline_load_shader(TS_JNI_ARGS, jlong self, jint type, jstring name, jstring format) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toPipeline(self).loadShader((Shader::Type)type, name_, "%s", format_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean pipeline_load_shader_glsl(TS_JNI_ARGS, jlong self, jint type, jstring name, jstring format) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toPipeline(self).loadShaderGLSL((Shader::Type)type, name_, "%s", format_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean pipeline_load_shader_1(TS_JNI_ARGS, jlong self, jint type, jstring name, jlong macros, jstringArray includes, jint size) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toPipeline(self).loadShader((Shader::Type)type, name_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(name, name_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean pipeline_load_shader_glsl_1(TS_JNI_ARGS, jlong self, jint type, jstring name, jlong macros, jstringArray includes, jint size) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toPipeline(self).loadShaderGLSL((Shader::Type)type, name_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(name, name_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean pipeline_load_shader_spirv(TS_JNI_ARGS, jlong self, jint type, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toPipeline(self).loadShaderSPIRV((Shader::Type)type, name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean pipeline_create_shader(TS_JNI_ARGS, jlong self, jint type, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toPipeline(self).createShader((Shader::Type)type, src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean pipeline_create_shader_glsl(TS_JNI_ARGS, jlong self, jint type, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toPipeline(self).createShaderGLSL((Shader::Type)type, src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean pipeline_create_shader_1(TS_JNI_ARGS, jlong self, jint type, jstring src, jlong macros, jstringArray includes, jint size) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toPipeline(self).createShader((Shader::Type)type, src_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(src, src_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean pipeline_create_shader_glsl_1(TS_JNI_ARGS, jlong self, jint type, jstring src, jlong macros, jstringArray includes, jint size) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toPipeline(self).createShaderGLSL((Shader::Type)type, src_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(src, src_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean pipeline_create_shader_spirv(TS_JNI_ARGS, jlong self, jint type, jintArray data) {
		uint32_t *data__ = (uint32_t*)env->GetIntArrayElements(data, nullptr);
		Array<uint32_t> data_((uint32_t)env->GetArrayLength(data), data__);
		bool ret_ = toPipeline(self).createShaderSPIRV((Shader::Type)type, data_);
		if(data_) env->ReleaseIntArrayElements(data, (jint*)data__, 0);
		return ret_;
	}
	static jint pipeline_add_sampler(TS_JNI_ARGS, jlong self, jint mask) {
		return toPipeline(self).addSampler((Shader::Mask)mask);
	}
	static jint pipeline_get_num_samplers(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumSamplers();
	}
	static jlong pipeline_set_sampler_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newPipeline(toPipeline(self).setSamplerOffset((uint32_t)offset));
	}
	static jint pipeline_get_sampler_offset(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getSamplerOffset();
	}
	static jlong pipeline_set_sampler_mask(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		return newPipeline(toPipeline(self).setSamplerMask((uint32_t)index, (Shader::Mask)mask));
	}
	static jint pipeline_get_sampler_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getSamplerMask((uint32_t)index);
	}
	static jlong pipeline_set_sampler_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask, jboolean array) {
		return newPipeline(toPipeline(self).setSamplerMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask, (bool)array));
	}
	static jint pipeline_get_sampler_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toPipeline(self).getSamplerMasks((uint32_t)index, (uint32_t)num);
	}
	static jlong pipeline_set_sampler_array(TS_JNI_ARGS, jlong self, jint index, jint num, jboolean array) {
		return newPipeline(toPipeline(self).setSamplerArray((uint32_t)index, (uint32_t)num, (bool)array));
	}
	static jint pipeline_get_sampler_array(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getSamplerArray((uint32_t)index);
	}
	static jint pipeline_add_texture(TS_JNI_ARGS, jlong self, jint mask) {
		return toPipeline(self).addTexture((Shader::Mask)mask);
	}
	static jint pipeline_get_num_textures(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumTextures();
	}
	static jlong pipeline_set_texture_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newPipeline(toPipeline(self).setTextureOffset((uint32_t)offset));
	}
	static jint pipeline_get_texture_offset(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getTextureOffset();
	}
	static jlong pipeline_set_texture_mask(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		return newPipeline(toPipeline(self).setTextureMask((uint32_t)index, (Shader::Mask)mask));
	}
	static jint pipeline_get_texture_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getTextureMask((uint32_t)index);
	}
	static jlong pipeline_set_texture_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask, jboolean array) {
		return newPipeline(toPipeline(self).setTextureMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask, (bool)array));
	}
	static jint pipeline_get_texture_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toPipeline(self).getTextureMasks((uint32_t)index, (uint32_t)num);
	}
	static jlong pipeline_set_texture_array(TS_JNI_ARGS, jlong self, jint index, jint num, jboolean array) {
		return newPipeline(toPipeline(self).setTextureArray((uint32_t)index, (uint32_t)num, (bool)array));
	}
	static jint pipeline_get_texture_array(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getTextureArray((uint32_t)index);
	}
	static jint pipeline_add_surface(TS_JNI_ARGS, jlong self, jint mask) {
		return toPipeline(self).addSurface((Shader::Mask)mask);
	}
	static jint pipeline_get_num_surfaces(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumSurfaces();
	}
	static jlong pipeline_set_surface_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newPipeline(toPipeline(self).setSurfaceOffset((uint32_t)offset));
	}
	static jint pipeline_get_surface_offset(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getSurfaceOffset();
	}
	static jlong pipeline_set_surface_mask(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		return newPipeline(toPipeline(self).setSurfaceMask((uint32_t)index, (Shader::Mask)mask));
	}
	static jint pipeline_get_surface_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getSurfaceMask((uint32_t)index);
	}
	static jlong pipeline_set_surface_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask, jboolean array) {
		return newPipeline(toPipeline(self).setSurfaceMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask, (bool)array));
	}
	static jint pipeline_get_surface_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toPipeline(self).getSurfaceMasks((uint32_t)index, (uint32_t)num);
	}
	static jlong pipeline_set_surface_array(TS_JNI_ARGS, jlong self, jint index, jint num, jboolean array) {
		return newPipeline(toPipeline(self).setSurfaceArray((uint32_t)index, (uint32_t)num, (bool)array));
	}
	static jint pipeline_get_surface_array(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getSurfaceArray((uint32_t)index);
	}
	static jint pipeline_add_uniform(TS_JNI_ARGS, jlong self, jint mask, jint flags) {
		return toPipeline(self).addUniform((Shader::Mask)mask, (BindFlags)flags);
	}
	static jint pipeline_get_num_uniforms(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumUniforms();
	}
	static jlong pipeline_set_uniform_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newPipeline(toPipeline(self).setUniformOffset((uint32_t)offset));
	}
	static jint pipeline_get_uniform_offset(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getUniformOffset();
	}
	static jlong pipeline_set_uniform_mask(TS_JNI_ARGS, jlong self, jint index, jint mask, jint flags) {
		return newPipeline(toPipeline(self).setUniformMask((uint32_t)index, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint pipeline_get_uniform_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getUniformMask((uint32_t)index);
	}
	static jlong pipeline_set_uniform_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask, jint flags) {
		return newPipeline(toPipeline(self).setUniformMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint pipeline_get_uniform_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toPipeline(self).getUniformMasks((uint32_t)index, (uint32_t)num);
	}
	static jlong pipeline_set_uniform_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return newPipeline(toPipeline(self).setUniformFlags((uint32_t)index, (BindFlags)flags));
	}
	static jint pipeline_get_uniform_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getUniformFlags((uint32_t)index);
	}
	static jint pipeline_add_storage(TS_JNI_ARGS, jlong self, jint mask, jint flags) {
		return toPipeline(self).addStorage((Shader::Mask)mask, (BindFlags)flags);
	}
	static jint pipeline_get_num_storages(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumStorages();
	}
	static jlong pipeline_set_storage_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newPipeline(toPipeline(self).setStorageOffset((uint32_t)offset));
	}
	static jint pipeline_get_storage_offset(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStorageOffset();
	}
	static jlong pipeline_set_storage_mask(TS_JNI_ARGS, jlong self, jint index, jint mask, jint flags) {
		return newPipeline(toPipeline(self).setStorageMask((uint32_t)index, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint pipeline_get_storage_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getStorageMask((uint32_t)index);
	}
	static jlong pipeline_set_storage_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask, jint flags) {
		return newPipeline(toPipeline(self).setStorageMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint pipeline_get_storage_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toPipeline(self).getStorageMasks((uint32_t)index, (uint32_t)num);
	}
	static jlong pipeline_set_storage_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return newPipeline(toPipeline(self).setStorageFlags((uint32_t)index, (BindFlags)flags));
	}
	static jint pipeline_get_storage_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getStorageFlags((uint32_t)index);
	}
	static jint pipeline_add_tracing(TS_JNI_ARGS, jlong self, jint mask) {
		return toPipeline(self).addTracing((Shader::Mask)mask);
	}
	static jint pipeline_get_num_tracings(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumTracings();
	}
	static jlong pipeline_set_tracing_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newPipeline(toPipeline(self).setTracingOffset((uint32_t)offset));
	}
	static jint pipeline_get_tracing_offset(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getTracingOffset();
	}
	static jlong pipeline_set_tracing_mask(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		return newPipeline(toPipeline(self).setTracingMask((uint32_t)index, (Shader::Mask)mask));
	}
	static jint pipeline_get_tracing_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getTracingMask((uint32_t)index);
	}
	static jlong pipeline_set_tracing_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask) {
		return newPipeline(toPipeline(self).setTracingMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask));
	}
	static jint pipeline_get_tracing_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toPipeline(self).getTracingMasks((uint32_t)index, (uint32_t)num);
	}
	static jint pipeline_add_texel(TS_JNI_ARGS, jlong self, jint mask) {
		return toPipeline(self).addTexel((Shader::Mask)mask);
	}
	static jint pipeline_get_num_texels(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumTexels();
	}
	static jlong pipeline_set_texel_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newPipeline(toPipeline(self).setTexelOffset((uint32_t)offset));
	}
	static jint pipeline_get_texel_offset(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getTexelOffset();
	}
	static jlong pipeline_set_texel_mask(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		return newPipeline(toPipeline(self).setTexelMask((uint32_t)index, (Shader::Mask)mask));
	}
	static jint pipeline_get_texel_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getTexelMask((uint32_t)index);
	}
	static jlong pipeline_set_texel_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask) {
		return newPipeline(toPipeline(self).setTexelMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask));
	}
	static jint pipeline_get_texel_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toPipeline(self).getTexelMasks((uint32_t)index, (uint32_t)num);
	}
	static jint pipeline_add_table(TS_JNI_ARGS, jlong self, jint type, jint size, jint mask, jint flags) {
		return toPipeline(self).addTable((TableType)type, (uint32_t)size, (Shader::Mask)mask, (BindFlags)flags);
	}
	static jint pipeline_get_num_tables(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumTables();
	}
	static jlong pipeline_set_table_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newPipeline(toPipeline(self).setTableOffset((uint32_t)offset));
	}
	static jint pipeline_get_table_offset(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getTableOffset();
	}
	static jlong pipeline_set_table_type(TS_JNI_ARGS, jlong self, jint index, jint type, jint size, jint mask, jint flags) {
		return newPipeline(toPipeline(self).setTableType((uint32_t)index, (TableType)type, (uint32_t)size, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint pipeline_get_table_type(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getTableType((uint32_t)index);
	}
	static jint pipeline_get_table_size(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getTableSize((uint32_t)index);
	}
	static jlong pipeline_set_table_mask(TS_JNI_ARGS, jlong self, jint index, jint mask, jint flags) {
		return newPipeline(toPipeline(self).setTableMask((uint32_t)index, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint pipeline_get_table_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getTableMask((uint32_t)index);
	}
	static jlong pipeline_set_table_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return newPipeline(toPipeline(self).setTableFlags((uint32_t)index, (BindFlags)flags));
	}
	static jint pipeline_get_table_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getTableFlags((uint32_t)index);
	}
	static jint pipeline_get_num_vertices(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumVertices();
	}
	static jint pipeline_get_vertex_stride(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getVertexStride((uint32_t)index);
	}
	static jint pipeline_get_vertex_rate(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getVertexRate((uint32_t)index);
	}
	static jint pipeline_add_attribute(TS_JNI_ARGS, jlong self, jint attribute, jint format, jint vertex, jlong offset, jlong stride, jint rate) {
		return toPipeline(self).addAttribute((Pipeline::Attribute)attribute, (Format)format, (uint32_t)vertex, (size_t)offset, (size_t)stride, (uint32_t)rate);
	}
	static jlong pipeline_set_attribute(TS_JNI_ARGS, jlong self, jint index, jint attribute, jint format, jint vertex, jlong offset, jlong stride, jint rate) {
		return newPipeline(toPipeline(self).setAttribute((uint32_t)index, (Pipeline::Attribute)attribute, (Format)format, (uint32_t)vertex, (size_t)offset, (size_t)stride, (uint32_t)rate));
	}
	static jlong pipeline_set_attribute_type(TS_JNI_ARGS, jlong self, jint index, jint attribute) {
		return newPipeline(toPipeline(self).setAttributeType((uint32_t)index, (Pipeline::Attribute)attribute));
	}
	static jlong pipeline_set_attribute_format(TS_JNI_ARGS, jlong self, jint index, jint format) {
		return newPipeline(toPipeline(self).setAttributeFormat((uint32_t)index, (Format)format));
	}
	static jlong pipeline_set_attribute_vertex(TS_JNI_ARGS, jlong self, jint index, jint vertex) {
		return newPipeline(toPipeline(self).setAttributeVertex((uint32_t)index, (uint32_t)vertex));
	}
	static jlong pipeline_set_attribute_offset(TS_JNI_ARGS, jlong self, jint index, jlong offset) {
		return newPipeline(toPipeline(self).setAttributeOffset((uint32_t)index, (size_t)offset));
	}
	static jlong pipeline_set_attribute_stride(TS_JNI_ARGS, jlong self, jint index, jlong stride) {
		return newPipeline(toPipeline(self).setAttributeStride((uint32_t)index, (size_t)stride));
	}
	static jlong pipeline_set_attribute_rate(TS_JNI_ARGS, jlong self, jint index, jint rate) {
		return newPipeline(toPipeline(self).setAttributeRate((uint32_t)index, (uint32_t)rate));
	}
	static jint pipeline_get_num_attributes(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumAttributes();
	}
	static jint pipeline_get_attribute_type(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getAttributeType((uint32_t)index);
	}
	static jint pipeline_get_attribute_format(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getAttributeFormat((uint32_t)index);
	}
	static jint pipeline_get_attribute_vertex(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getAttributeVertex((uint32_t)index);
	}
	static jint pipeline_get_attribute_offset(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getAttributeOffset((uint32_t)index);
	}
	static jint pipeline_get_attribute_stride(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getAttributeStride((uint32_t)index);
	}
	static jint pipeline_get_attribute_rate(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getAttributeRate((uint32_t)index);
	}
	static void pipeline_set_primitive(TS_JNI_ARGS, jlong self, jint primitive) {
		toPipeline(self).setPrimitive((Pipeline::Primitive)primitive);
	}
	static jint pipeline_get_primitive(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getPrimitive();
	}
	static void pipeline_set_fill_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toPipeline(self).setFillMode((Pipeline::FillMode)mode);
	}
	static jint pipeline_get_fill_mode(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getFillMode();
	}
	static void pipeline_set_cull_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toPipeline(self).setCullMode((Pipeline::CullMode)mode);
	}
	static jint pipeline_get_cull_mode(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getCullMode();
	}
	static void pipeline_set_front_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toPipeline(self).setFrontMode((Pipeline::FrontMode)mode);
	}
	static jint pipeline_get_front_mode(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getFrontMode();
	}
	static void pipeline_set_depth_bias(TS_JNI_ARGS, jlong self, jfloat bias, jfloat slope, jfloat clamp) {
		toPipeline(self).setDepthBias(bias, slope, clamp);
	}
	static jfloat pipeline_get_depth_bias(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getDepthBias();
	}
	static jfloat pipeline_get_depth_slope(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getDepthSlope();
	}
	static jfloat pipeline_get_depth_clamp(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getDepthClamp();
	}
	static void pipeline_set_multisample(TS_JNI_ARGS, jlong self, jint multisample) {
		toPipeline(self).setMultisample((uint32_t)multisample);
	}
	static jint pipeline_get_multisample(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getMultisample();
	}
	static void pipeline_set_sample_mask(TS_JNI_ARGS, jlong self, jint sample_mask) {
		toPipeline(self).setSampleMask((uint32_t)sample_mask);
	}
	static jint pipeline_get_sample_mask(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getSampleMask();
	}
	static void pipeline_set_depth_clip(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toPipeline(self).setDepthClip((bool)enabled);
	}
	static jboolean pipeline_get_depth_clip(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getDepthClip();
	}
	static void pipeline_set_depth_replace(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toPipeline(self).setDepthReplace((bool)enabled);
	}
	static jboolean pipeline_get_depth_replace(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getDepthReplace();
	}
	static void pipeline_set_scissor_test(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toPipeline(self).setScissorTest((bool)enabled);
	}
	static jboolean pipeline_get_scissor_test(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getScissorTest();
	}
	static void pipeline_set_raster_discard(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toPipeline(self).setRasterDiscard((bool)enabled);
	}
	static jboolean pipeline_get_raster_discard(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getRasterDiscard();
	}
	static void pipeline_set_sample_shading(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toPipeline(self).setSampleShading((bool)enabled);
	}
	static jboolean pipeline_get_sample_shading(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getSampleShading();
	}
	static void pipeline_set_alpha_to_coverage(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toPipeline(self).setAlphaToCoverage((bool)enabled);
	}
	static jboolean pipeline_get_alpha_to_coverage(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getAlphaToCoverage();
	}
	static void pipeline_set_multisample_raster(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toPipeline(self).setMultisampleRaster((bool)enabled);
	}
	static jboolean pipeline_get_multisample_raster(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getMultisampleRaster();
	}
	static void pipeline_set_conservative_raster(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toPipeline(self).setConservativeRaster((bool)enabled);
	}
	static jboolean pipeline_get_conservative_raster(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getConservativeRaster();
	}
	static void pipeline_set_num_viewports(TS_JNI_ARGS, jlong self, jint num_viewports) {
		toPipeline(self).setNumViewports((uint32_t)num_viewports);
	}
	static jint pipeline_get_num_targets(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumTargets();
	}
	static jint pipeline_get_num_viewports(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumViewports();
	}
	static void pipeline_set_num_clip_distances(TS_JNI_ARGS, jlong self, jint num_distances) {
		toPipeline(self).setNumClipDistances((uint32_t)num_distances);
	}
	static jint pipeline_get_num_clip_distances(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getNumClipDistances();
	}
	static void pipeline_set_blend(TS_JNI_ARGS, jlong self, jint op, jint src, jint dest) {
		toPipeline(self).setBlend((Pipeline::BlendOp)op, (Pipeline::BlendFunc)src, (Pipeline::BlendFunc)dest);
	}
	static void pipeline_set_blend_color(TS_JNI_ARGS, jlong self, jint op, jint src, jint dest) {
		toPipeline(self).setBlendColor((Pipeline::BlendOp)op, (Pipeline::BlendFunc)src, (Pipeline::BlendFunc)dest);
	}
	static void pipeline_set_blend_alpha(TS_JNI_ARGS, jlong self, jint op, jint src, jint dest) {
		toPipeline(self).setBlendAlpha((Pipeline::BlendOp)op, (Pipeline::BlendFunc)src, (Pipeline::BlendFunc)dest);
	}
	static void pipeline_set_blend_1(TS_JNI_ARGS, jlong self, jint index, jint op, jint src, jint dest) {
		toPipeline(self).setBlend((uint32_t)index, (Pipeline::BlendOp)op, (Pipeline::BlendFunc)src, (Pipeline::BlendFunc)dest);
	}
	static void pipeline_set_blend_color_1(TS_JNI_ARGS, jlong self, jint index, jint op, jint src, jint dest) {
		toPipeline(self).setBlendColor((uint32_t)index, (Pipeline::BlendOp)op, (Pipeline::BlendFunc)src, (Pipeline::BlendFunc)dest);
	}
	static void pipeline_set_blend_alpha_1(TS_JNI_ARGS, jlong self, jint index, jint op, jint src, jint dest) {
		toPipeline(self).setBlendAlpha((uint32_t)index, (Pipeline::BlendOp)op, (Pipeline::BlendFunc)src, (Pipeline::BlendFunc)dest);
	}
	static jint pipeline_get_blend_color_op(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getBlendColorOp((uint32_t)index);
	}
	static jint pipeline_get_blend_alpha_op(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getBlendAlphaOp((uint32_t)index);
	}
	static jint pipeline_get_blend_src_color_func(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getBlendSrcColorFunc((uint32_t)index);
	}
	static jint pipeline_get_blend_src_alpha_func(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getBlendSrcAlphaFunc((uint32_t)index);
	}
	static jint pipeline_get_blend_dest_color_func(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getBlendDestColorFunc((uint32_t)index);
	}
	static jint pipeline_get_blend_dest_alpha_func(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getBlendDestAlphaFunc((uint32_t)index);
	}
	static void pipeline_set_color_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toPipeline(self).setColorMask((Pipeline::ColorMask)mask);
	}
	static void pipeline_set_color_mask_1(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		toPipeline(self).setColorMask((uint32_t)index, (Pipeline::ColorMask)mask);
	}
	static void pipeline_set_color_format(TS_JNI_ARGS, jlong self, jint index, jint format) {
		toPipeline(self).setColorFormat((uint32_t)index, (Format)format);
	}
	static void pipeline_set_color_format_1(TS_JNI_ARGS, jlong self, jint format, jint num) {
		toPipeline(self).setColorFormat((Format)format, (uint32_t)num);
	}
	static jint pipeline_get_color_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getColorMask((uint32_t)index);
	}
	static jint pipeline_get_color_format(TS_JNI_ARGS, jlong self, jint index) {
		return toPipeline(self).getColorFormat((uint32_t)index);
	}
	static void pipeline_set_depth_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toPipeline(self).setDepthMask((Pipeline::DepthMask)mask);
	}
	static void pipeline_set_depth_func(TS_JNI_ARGS, jlong self, jint func) {
		toPipeline(self).setDepthFunc((Pipeline::DepthFunc)func);
	}
	static void pipeline_set_depth_format(TS_JNI_ARGS, jlong self, jint format) {
		toPipeline(self).setDepthFormat((Format)format);
	}
	static jint pipeline_get_depth_mask(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getDepthMask();
	}
	static jint pipeline_get_depth_func(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getDepthFunc();
	}
	static jint pipeline_get_depth_format(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getDepthFormat();
	}
	static void pipeline_set_stencil_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toPipeline(self).setStencilMask((uint32_t)mask);
	}
	static void pipeline_set_stencil_back_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toPipeline(self).setStencilBackMask((uint32_t)mask);
	}
	static void pipeline_set_stencil_front_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toPipeline(self).setStencilFrontMask((uint32_t)mask);
	}
	static void pipeline_set_stencil_func(TS_JNI_ARGS, jlong self, jint func, jint dpass_op) {
		toPipeline(self).setStencilFunc((Pipeline::StencilFunc)func, (Pipeline::StencilOp)dpass_op);
	}
	static void pipeline_set_stencil_back_func(TS_JNI_ARGS, jlong self, jint func, jint dpass_op) {
		toPipeline(self).setStencilBackFunc((Pipeline::StencilFunc)func, (Pipeline::StencilOp)dpass_op);
	}
	static void pipeline_set_stencil_front_func(TS_JNI_ARGS, jlong self, jint func, jint dpass_op) {
		toPipeline(self).setStencilFrontFunc((Pipeline::StencilFunc)func, (Pipeline::StencilOp)dpass_op);
	}
	static void pipeline_set_stencil_func_1(TS_JNI_ARGS, jlong self, jint func, jint fail_op, jint dfail_op, jint dpass_op) {
		toPipeline(self).setStencilFunc((Pipeline::StencilFunc)func, (Pipeline::StencilOp)fail_op, (Pipeline::StencilOp)dfail_op, (Pipeline::StencilOp)dpass_op);
	}
	static void pipeline_set_stencil_back_func_1(TS_JNI_ARGS, jlong self, jint func, jint fail_op, jint dfail_op, jint dpass_op) {
		toPipeline(self).setStencilBackFunc((Pipeline::StencilFunc)func, (Pipeline::StencilOp)fail_op, (Pipeline::StencilOp)dfail_op, (Pipeline::StencilOp)dpass_op);
	}
	static void pipeline_set_stencil_front_func_1(TS_JNI_ARGS, jlong self, jint func, jint fail_op, jint dfail_op, jint dpass_op) {
		toPipeline(self).setStencilFrontFunc((Pipeline::StencilFunc)func, (Pipeline::StencilOp)fail_op, (Pipeline::StencilOp)dfail_op, (Pipeline::StencilOp)dpass_op);
	}
	static jint pipeline_get_stencil_back_mask(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStencilBackMask();
	}
	static jint pipeline_get_stencil_back_func(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStencilBackFunc();
	}
	static jint pipeline_get_stencil_back_fail_op(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStencilBackFailOp();
	}
	static jint pipeline_get_stencil_back_depth_fail_op(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStencilBackDepthFailOp();
	}
	static jint pipeline_get_stencil_back_depth_pass_op(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStencilBackDepthPassOp();
	}
	static jint pipeline_get_stencil_front_mask(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStencilFrontMask();
	}
	static jint pipeline_get_stencil_front_func(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStencilFrontFunc();
	}
	static jint pipeline_get_stencil_front_fail_op(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStencilFrontFailOp();
	}
	static jint pipeline_get_stencil_front_depth_fail_op(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStencilFrontDepthFailOp();
	}
	static jint pipeline_get_stencil_front_depth_pass_op(TS_JNI_ARGS, jlong self) {
		return toPipeline(self).getStencilFrontDepthPassOp();
	}
	static const JNINativeMethod pipeline_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)pipeline_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)pipeline_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)pipeline_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)pipeline_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)pipeline_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)pipeline_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)pipeline_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)pipeline_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)pipeline_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)pipeline_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)pipeline_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)pipeline_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)pipeline_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)pipeline_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)pipeline_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)pipeline_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)pipeline_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)pipeline_is_created },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)pipeline_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)pipeline_get_name },
		{ (char*)"create_", (char*)"(J)Z", (void*)pipeline_create },
		{ (char*)"set_parameters", (char*)"(JJ)V", (void*)pipeline_set_parameters },
		{ (char*)"save_state", (char*)"(JJ)Z", (void*)pipeline_save_state },
		{ (char*)"add_shader", (char*)"(JJZ)V", (void*)pipeline_add_shader },
		{ (char*)"get_vertex_shader", (char*)"(J)J", (void*)pipeline_get_vertex_shader },
		{ (char*)"get_control_shader", (char*)"(J)J", (void*)pipeline_get_control_shader },
		{ (char*)"get_evaluate_shader", (char*)"(J)J", (void*)pipeline_get_evaluate_shader },
		{ (char*)"get_geometry_shader", (char*)"(J)J", (void*)pipeline_get_geometry_shader },
		{ (char*)"get_fragment_shader", (char*)"(J)J", (void*)pipeline_get_fragment_shader },
		{ (char*)"get_task_shader", (char*)"(J)J", (void*)pipeline_get_task_shader },
		{ (char*)"get_mesh_shader", (char*)"(J)J", (void*)pipeline_get_mesh_shader },
		{ (char*)"load_shader", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)pipeline_load_shader },
		{ (char*)"load_shader_glsl", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)pipeline_load_shader_glsl },
		{ (char*)"load_shader_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)pipeline_load_shader_1 },
		{ (char*)"load_shader_glsl_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)pipeline_load_shader_glsl_1 },
		{ (char*)"load_shader_spirv", (char*)"(JILjava/lang/String;)Z", (void*)pipeline_load_shader_spirv },
		{ (char*)"create_shader", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)pipeline_create_shader },
		{ (char*)"create_shader_glsl", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)pipeline_create_shader_glsl },
		{ (char*)"create_shader_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)pipeline_create_shader_1 },
		{ (char*)"create_shader_glsl_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)pipeline_create_shader_glsl_1 },
		{ (char*)"create_shader_spirv", (char*)"(JI[I)Z", (void*)pipeline_create_shader_spirv },
		{ (char*)"add_sampler", (char*)"(JI)I", (void*)pipeline_add_sampler },
		{ (char*)"get_num_samplers", (char*)"(J)I", (void*)pipeline_get_num_samplers },
		{ (char*)"set_sampler_offset", (char*)"(JI)J", (void*)pipeline_set_sampler_offset },
		{ (char*)"get_sampler_offset", (char*)"(J)I", (void*)pipeline_get_sampler_offset },
		{ (char*)"set_sampler_mask", (char*)"(JII)J", (void*)pipeline_set_sampler_mask },
		{ (char*)"get_sampler_mask", (char*)"(JI)I", (void*)pipeline_get_sampler_mask },
		{ (char*)"set_sampler_masks", (char*)"(JIIIZ)J", (void*)pipeline_set_sampler_masks },
		{ (char*)"get_sampler_masks", (char*)"(JII)I", (void*)pipeline_get_sampler_masks },
		{ (char*)"set_sampler_array", (char*)"(JIIZ)J", (void*)pipeline_set_sampler_array },
		{ (char*)"get_sampler_array", (char*)"(JI)I", (void*)pipeline_get_sampler_array },
		{ (char*)"add_texture", (char*)"(JI)I", (void*)pipeline_add_texture },
		{ (char*)"get_num_textures", (char*)"(J)I", (void*)pipeline_get_num_textures },
		{ (char*)"set_texture_offset", (char*)"(JI)J", (void*)pipeline_set_texture_offset },
		{ (char*)"get_texture_offset", (char*)"(J)I", (void*)pipeline_get_texture_offset },
		{ (char*)"set_texture_mask", (char*)"(JII)J", (void*)pipeline_set_texture_mask },
		{ (char*)"get_texture_mask", (char*)"(JI)I", (void*)pipeline_get_texture_mask },
		{ (char*)"set_texture_masks", (char*)"(JIIIZ)J", (void*)pipeline_set_texture_masks },
		{ (char*)"get_texture_masks", (char*)"(JII)I", (void*)pipeline_get_texture_masks },
		{ (char*)"set_texture_array", (char*)"(JIIZ)J", (void*)pipeline_set_texture_array },
		{ (char*)"get_texture_array", (char*)"(JI)I", (void*)pipeline_get_texture_array },
		{ (char*)"add_surface", (char*)"(JI)I", (void*)pipeline_add_surface },
		{ (char*)"get_num_surfaces", (char*)"(J)I", (void*)pipeline_get_num_surfaces },
		{ (char*)"set_surface_offset", (char*)"(JI)J", (void*)pipeline_set_surface_offset },
		{ (char*)"get_surface_offset", (char*)"(J)I", (void*)pipeline_get_surface_offset },
		{ (char*)"set_surface_mask", (char*)"(JII)J", (void*)pipeline_set_surface_mask },
		{ (char*)"get_surface_mask", (char*)"(JI)I", (void*)pipeline_get_surface_mask },
		{ (char*)"set_surface_masks", (char*)"(JIIIZ)J", (void*)pipeline_set_surface_masks },
		{ (char*)"get_surface_masks", (char*)"(JII)I", (void*)pipeline_get_surface_masks },
		{ (char*)"set_surface_array", (char*)"(JIIZ)J", (void*)pipeline_set_surface_array },
		{ (char*)"get_surface_array", (char*)"(JI)I", (void*)pipeline_get_surface_array },
		{ (char*)"add_uniform", (char*)"(JII)I", (void*)pipeline_add_uniform },
		{ (char*)"get_num_uniforms", (char*)"(J)I", (void*)pipeline_get_num_uniforms },
		{ (char*)"set_uniform_offset", (char*)"(JI)J", (void*)pipeline_set_uniform_offset },
		{ (char*)"get_uniform_offset", (char*)"(J)I", (void*)pipeline_get_uniform_offset },
		{ (char*)"set_uniform_mask", (char*)"(JIII)J", (void*)pipeline_set_uniform_mask },
		{ (char*)"get_uniform_mask", (char*)"(JI)I", (void*)pipeline_get_uniform_mask },
		{ (char*)"set_uniform_masks", (char*)"(JIIII)J", (void*)pipeline_set_uniform_masks },
		{ (char*)"get_uniform_masks", (char*)"(JII)I", (void*)pipeline_get_uniform_masks },
		{ (char*)"set_uniform_flags", (char*)"(JII)J", (void*)pipeline_set_uniform_flags },
		{ (char*)"get_uniform_flags", (char*)"(JI)I", (void*)pipeline_get_uniform_flags },
		{ (char*)"add_storage", (char*)"(JII)I", (void*)pipeline_add_storage },
		{ (char*)"get_num_storages", (char*)"(J)I", (void*)pipeline_get_num_storages },
		{ (char*)"set_storage_offset", (char*)"(JI)J", (void*)pipeline_set_storage_offset },
		{ (char*)"get_storage_offset", (char*)"(J)I", (void*)pipeline_get_storage_offset },
		{ (char*)"set_storage_mask", (char*)"(JIII)J", (void*)pipeline_set_storage_mask },
		{ (char*)"get_storage_mask", (char*)"(JI)I", (void*)pipeline_get_storage_mask },
		{ (char*)"set_storage_masks", (char*)"(JIIII)J", (void*)pipeline_set_storage_masks },
		{ (char*)"get_storage_masks", (char*)"(JII)I", (void*)pipeline_get_storage_masks },
		{ (char*)"set_storage_flags", (char*)"(JII)J", (void*)pipeline_set_storage_flags },
		{ (char*)"get_storage_flags", (char*)"(JI)I", (void*)pipeline_get_storage_flags },
		{ (char*)"add_tracing", (char*)"(JI)I", (void*)pipeline_add_tracing },
		{ (char*)"get_num_tracings", (char*)"(J)I", (void*)pipeline_get_num_tracings },
		{ (char*)"set_tracing_offset", (char*)"(JI)J", (void*)pipeline_set_tracing_offset },
		{ (char*)"get_tracing_offset", (char*)"(J)I", (void*)pipeline_get_tracing_offset },
		{ (char*)"set_tracing_mask", (char*)"(JII)J", (void*)pipeline_set_tracing_mask },
		{ (char*)"get_tracing_mask", (char*)"(JI)I", (void*)pipeline_get_tracing_mask },
		{ (char*)"set_tracing_masks", (char*)"(JIII)J", (void*)pipeline_set_tracing_masks },
		{ (char*)"get_tracing_masks", (char*)"(JII)I", (void*)pipeline_get_tracing_masks },
		{ (char*)"add_texel", (char*)"(JI)I", (void*)pipeline_add_texel },
		{ (char*)"get_num_texels", (char*)"(J)I", (void*)pipeline_get_num_texels },
		{ (char*)"set_texel_offset", (char*)"(JI)J", (void*)pipeline_set_texel_offset },
		{ (char*)"get_texel_offset", (char*)"(J)I", (void*)pipeline_get_texel_offset },
		{ (char*)"set_texel_mask", (char*)"(JII)J", (void*)pipeline_set_texel_mask },
		{ (char*)"get_texel_mask", (char*)"(JI)I", (void*)pipeline_get_texel_mask },
		{ (char*)"set_texel_masks", (char*)"(JIII)J", (void*)pipeline_set_texel_masks },
		{ (char*)"get_texel_masks", (char*)"(JII)I", (void*)pipeline_get_texel_masks },
		{ (char*)"add_table", (char*)"(JIIII)I", (void*)pipeline_add_table },
		{ (char*)"get_num_tables", (char*)"(J)I", (void*)pipeline_get_num_tables },
		{ (char*)"set_table_offset", (char*)"(JI)J", (void*)pipeline_set_table_offset },
		{ (char*)"get_table_offset", (char*)"(J)I", (void*)pipeline_get_table_offset },
		{ (char*)"set_table_type", (char*)"(JIIIII)J", (void*)pipeline_set_table_type },
		{ (char*)"get_table_type", (char*)"(JI)I", (void*)pipeline_get_table_type },
		{ (char*)"get_table_size", (char*)"(JI)I", (void*)pipeline_get_table_size },
		{ (char*)"set_table_mask", (char*)"(JIII)J", (void*)pipeline_set_table_mask },
		{ (char*)"get_table_mask", (char*)"(JI)I", (void*)pipeline_get_table_mask },
		{ (char*)"set_table_flags", (char*)"(JII)J", (void*)pipeline_set_table_flags },
		{ (char*)"get_table_flags", (char*)"(JI)I", (void*)pipeline_get_table_flags },
		{ (char*)"get_num_vertices", (char*)"(J)I", (void*)pipeline_get_num_vertices },
		{ (char*)"get_vertex_stride", (char*)"(JI)I", (void*)pipeline_get_vertex_stride },
		{ (char*)"get_vertex_rate", (char*)"(JI)I", (void*)pipeline_get_vertex_rate },
		{ (char*)"add_attribute", (char*)"(JIIIJJI)I", (void*)pipeline_add_attribute },
		{ (char*)"set_attribute", (char*)"(JIIIIJJI)J", (void*)pipeline_set_attribute },
		{ (char*)"set_attribute_type", (char*)"(JII)J", (void*)pipeline_set_attribute_type },
		{ (char*)"set_attribute_format", (char*)"(JII)J", (void*)pipeline_set_attribute_format },
		{ (char*)"set_attribute_vertex", (char*)"(JII)J", (void*)pipeline_set_attribute_vertex },
		{ (char*)"set_attribute_offset", (char*)"(JIJ)J", (void*)pipeline_set_attribute_offset },
		{ (char*)"set_attribute_stride", (char*)"(JIJ)J", (void*)pipeline_set_attribute_stride },
		{ (char*)"set_attribute_rate", (char*)"(JII)J", (void*)pipeline_set_attribute_rate },
		{ (char*)"get_num_attributes", (char*)"(J)I", (void*)pipeline_get_num_attributes },
		{ (char*)"get_attribute_type", (char*)"(JI)I", (void*)pipeline_get_attribute_type },
		{ (char*)"get_attribute_format", (char*)"(JI)I", (void*)pipeline_get_attribute_format },
		{ (char*)"get_attribute_vertex", (char*)"(JI)I", (void*)pipeline_get_attribute_vertex },
		{ (char*)"get_attribute_offset", (char*)"(JI)I", (void*)pipeline_get_attribute_offset },
		{ (char*)"get_attribute_stride", (char*)"(JI)I", (void*)pipeline_get_attribute_stride },
		{ (char*)"get_attribute_rate", (char*)"(JI)I", (void*)pipeline_get_attribute_rate },
		{ (char*)"set_primitive", (char*)"(JI)V", (void*)pipeline_set_primitive },
		{ (char*)"get_primitive", (char*)"(J)I", (void*)pipeline_get_primitive },
		{ (char*)"set_fill_mode", (char*)"(JI)V", (void*)pipeline_set_fill_mode },
		{ (char*)"get_fill_mode", (char*)"(J)I", (void*)pipeline_get_fill_mode },
		{ (char*)"set_cull_mode", (char*)"(JI)V", (void*)pipeline_set_cull_mode },
		{ (char*)"get_cull_mode", (char*)"(J)I", (void*)pipeline_get_cull_mode },
		{ (char*)"set_front_mode", (char*)"(JI)V", (void*)pipeline_set_front_mode },
		{ (char*)"get_front_mode", (char*)"(J)I", (void*)pipeline_get_front_mode },
		{ (char*)"set_depth_bias", (char*)"(JFFF)V", (void*)pipeline_set_depth_bias },
		{ (char*)"get_depth_bias", (char*)"(J)F", (void*)pipeline_get_depth_bias },
		{ (char*)"get_depth_slope", (char*)"(J)F", (void*)pipeline_get_depth_slope },
		{ (char*)"get_depth_clamp", (char*)"(J)F", (void*)pipeline_get_depth_clamp },
		{ (char*)"set_multisample", (char*)"(JI)V", (void*)pipeline_set_multisample },
		{ (char*)"get_multisample", (char*)"(J)I", (void*)pipeline_get_multisample },
		{ (char*)"set_sample_mask", (char*)"(JI)V", (void*)pipeline_set_sample_mask },
		{ (char*)"get_sample_mask", (char*)"(J)I", (void*)pipeline_get_sample_mask },
		{ (char*)"set_depth_clip", (char*)"(JZ)V", (void*)pipeline_set_depth_clip },
		{ (char*)"get_depth_clip", (char*)"(J)Z", (void*)pipeline_get_depth_clip },
		{ (char*)"set_depth_replace", (char*)"(JZ)V", (void*)pipeline_set_depth_replace },
		{ (char*)"get_depth_replace", (char*)"(J)Z", (void*)pipeline_get_depth_replace },
		{ (char*)"set_scissor_test", (char*)"(JZ)V", (void*)pipeline_set_scissor_test },
		{ (char*)"get_scissor_test", (char*)"(J)Z", (void*)pipeline_get_scissor_test },
		{ (char*)"set_raster_discard", (char*)"(JZ)V", (void*)pipeline_set_raster_discard },
		{ (char*)"get_raster_discard", (char*)"(J)Z", (void*)pipeline_get_raster_discard },
		{ (char*)"set_sample_shading", (char*)"(JZ)V", (void*)pipeline_set_sample_shading },
		{ (char*)"get_sample_shading", (char*)"(J)Z", (void*)pipeline_get_sample_shading },
		{ (char*)"set_alpha_to_coverage", (char*)"(JZ)V", (void*)pipeline_set_alpha_to_coverage },
		{ (char*)"get_alpha_to_coverage", (char*)"(J)Z", (void*)pipeline_get_alpha_to_coverage },
		{ (char*)"set_multisample_raster", (char*)"(JZ)V", (void*)pipeline_set_multisample_raster },
		{ (char*)"get_multisample_raster", (char*)"(J)Z", (void*)pipeline_get_multisample_raster },
		{ (char*)"set_conservative_raster", (char*)"(JZ)V", (void*)pipeline_set_conservative_raster },
		{ (char*)"get_conservative_raster", (char*)"(J)Z", (void*)pipeline_get_conservative_raster },
		{ (char*)"set_num_viewports", (char*)"(JI)V", (void*)pipeline_set_num_viewports },
		{ (char*)"get_num_targets", (char*)"(J)I", (void*)pipeline_get_num_targets },
		{ (char*)"get_num_viewports", (char*)"(J)I", (void*)pipeline_get_num_viewports },
		{ (char*)"set_num_clip_distances", (char*)"(JI)V", (void*)pipeline_set_num_clip_distances },
		{ (char*)"get_num_clip_distances", (char*)"(J)I", (void*)pipeline_get_num_clip_distances },
		{ (char*)"set_blend", (char*)"(JIII)V", (void*)pipeline_set_blend },
		{ (char*)"set_blend_color", (char*)"(JIII)V", (void*)pipeline_set_blend_color },
		{ (char*)"set_blend_alpha", (char*)"(JIII)V", (void*)pipeline_set_blend_alpha },
		{ (char*)"set_blend_1", (char*)"(JIIII)V", (void*)pipeline_set_blend_1 },
		{ (char*)"set_blend_color_1", (char*)"(JIIII)V", (void*)pipeline_set_blend_color_1 },
		{ (char*)"set_blend_alpha_1", (char*)"(JIIII)V", (void*)pipeline_set_blend_alpha_1 },
		{ (char*)"get_blend_color_op", (char*)"(JI)I", (void*)pipeline_get_blend_color_op },
		{ (char*)"get_blend_alpha_op", (char*)"(JI)I", (void*)pipeline_get_blend_alpha_op },
		{ (char*)"get_blend_src_color_func", (char*)"(JI)I", (void*)pipeline_get_blend_src_color_func },
		{ (char*)"get_blend_src_alpha_func", (char*)"(JI)I", (void*)pipeline_get_blend_src_alpha_func },
		{ (char*)"get_blend_dest_color_func", (char*)"(JI)I", (void*)pipeline_get_blend_dest_color_func },
		{ (char*)"get_blend_dest_alpha_func", (char*)"(JI)I", (void*)pipeline_get_blend_dest_alpha_func },
		{ (char*)"set_color_mask", (char*)"(JI)V", (void*)pipeline_set_color_mask },
		{ (char*)"set_color_mask_1", (char*)"(JII)V", (void*)pipeline_set_color_mask_1 },
		{ (char*)"set_color_format", (char*)"(JII)V", (void*)pipeline_set_color_format },
		{ (char*)"set_color_format_1", (char*)"(JII)V", (void*)pipeline_set_color_format_1 },
		{ (char*)"get_color_mask", (char*)"(JI)I", (void*)pipeline_get_color_mask },
		{ (char*)"get_color_format", (char*)"(JI)I", (void*)pipeline_get_color_format },
		{ (char*)"set_depth_mask", (char*)"(JI)V", (void*)pipeline_set_depth_mask },
		{ (char*)"set_depth_func", (char*)"(JI)V", (void*)pipeline_set_depth_func },
		{ (char*)"set_depth_format", (char*)"(JI)V", (void*)pipeline_set_depth_format },
		{ (char*)"get_depth_mask", (char*)"(J)I", (void*)pipeline_get_depth_mask },
		{ (char*)"get_depth_func", (char*)"(J)I", (void*)pipeline_get_depth_func },
		{ (char*)"get_depth_format", (char*)"(J)I", (void*)pipeline_get_depth_format },
		{ (char*)"set_stencil_mask", (char*)"(JI)V", (void*)pipeline_set_stencil_mask },
		{ (char*)"set_stencil_back_mask", (char*)"(JI)V", (void*)pipeline_set_stencil_back_mask },
		{ (char*)"set_stencil_front_mask", (char*)"(JI)V", (void*)pipeline_set_stencil_front_mask },
		{ (char*)"set_stencil_func", (char*)"(JII)V", (void*)pipeline_set_stencil_func },
		{ (char*)"set_stencil_back_func", (char*)"(JII)V", (void*)pipeline_set_stencil_back_func },
		{ (char*)"set_stencil_front_func", (char*)"(JII)V", (void*)pipeline_set_stencil_front_func },
		{ (char*)"set_stencil_func_1", (char*)"(JIIII)V", (void*)pipeline_set_stencil_func_1 },
		{ (char*)"set_stencil_back_func_1", (char*)"(JIIII)V", (void*)pipeline_set_stencil_back_func_1 },
		{ (char*)"set_stencil_front_func_1", (char*)"(JIIII)V", (void*)pipeline_set_stencil_front_func_1 },
		{ (char*)"get_stencil_back_mask", (char*)"(J)I", (void*)pipeline_get_stencil_back_mask },
		{ (char*)"get_stencil_back_func", (char*)"(J)I", (void*)pipeline_get_stencil_back_func },
		{ (char*)"get_stencil_back_fail_op", (char*)"(J)I", (void*)pipeline_get_stencil_back_fail_op },
		{ (char*)"get_stencil_back_depth_fail_op", (char*)"(J)I", (void*)pipeline_get_stencil_back_depth_fail_op },
		{ (char*)"get_stencil_back_depth_pass_op", (char*)"(J)I", (void*)pipeline_get_stencil_back_depth_pass_op },
		{ (char*)"get_stencil_front_mask", (char*)"(J)I", (void*)pipeline_get_stencil_front_mask },
		{ (char*)"get_stencil_front_func", (char*)"(J)I", (void*)pipeline_get_stencil_front_func },
		{ (char*)"get_stencil_front_fail_op", (char*)"(J)I", (void*)pipeline_get_stencil_front_fail_op },
		{ (char*)"get_stencil_front_depth_fail_op", (char*)"(J)I", (void*)pipeline_get_stencil_front_depth_fail_op },
		{ (char*)"get_stencil_front_depth_pass_op", (char*)"(J)I", (void*)pipeline_get_stencil_front_depth_pass_op },
	};
	
	// Tellusim::D3D12Pipeline
	static jlong d3d12_pipeline_new(TS_JNI_ARGS) {
		return newD3D12Pipeline();
	}
	static void d3d12_pipeline_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Pipeline*)self;
	}
	static jboolean d3d12_pipeline_equal_pipeline_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Pipeline(self).operator==(toPipeline(base));
	}
	static jlong d3d12_pipeline_cast_pipeline_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Pipeline(toPipeline(self));
	}
	static jlong d3d12_pipeline_base_pipeline_ptr(TS_JNI_ARGS, jlong self) {
		return newPipeline(toD3D12Pipeline(self).getPipeline());
	}
	static jlong d3d12_pipeline_get_root_signature(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Pipeline(self).getRootSignature();
	}
	static const JNINativeMethod d3d12_pipeline_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_pipeline_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_pipeline_delete },
		{ (char*)"equal_pipeline_ptr", (char*)"(JJ)Z", (void*)d3d12_pipeline_equal_pipeline_ptr },
		{ (char*)"cast_pipeline_ptr", (char*)"(J)J", (void*)d3d12_pipeline_cast_pipeline_ptr },
		{ (char*)"base_pipeline_ptr", (char*)"(J)J", (void*)d3d12_pipeline_base_pipeline_ptr },
		{ (char*)"get_root_signature", (char*)"(J)J", (void*)d3d12_pipeline_get_root_signature },
	};
	
	// Tellusim::MTLPipeline
	static jlong mtl_pipeline_new(TS_JNI_ARGS) {
		return newMTLPipeline();
	}
	static void mtl_pipeline_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLPipeline*)self;
	}
	static jboolean mtl_pipeline_equal_pipeline_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLPipeline(self).operator==(toPipeline(base));
	}
	static jlong mtl_pipeline_cast_pipeline_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLPipeline(toPipeline(self));
	}
	static jlong mtl_pipeline_base_pipeline_ptr(TS_JNI_ARGS, jlong self) {
		return newPipeline(toMTLPipeline(self).getPipeline());
	}
	static void mtl_pipeline_set_indirect(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toMTLPipeline(self).setIndirect((bool)enabled);
	}
	static jboolean mtl_pipeline_is_indirect(TS_JNI_ARGS, jlong self) {
		return toMTLPipeline(self).isIndirect();
	}
	static jlong mtl_pipeline_get_vertex_function(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLPipeline(self).getVertexFunction();
	}
	static jlong mtl_pipeline_get_fragment_function(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLPipeline(self).getFragmentFunction();
	}
	static const JNINativeMethod mtl_pipeline_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_pipeline_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_pipeline_delete },
		{ (char*)"equal_pipeline_ptr", (char*)"(JJ)Z", (void*)mtl_pipeline_equal_pipeline_ptr },
		{ (char*)"cast_pipeline_ptr", (char*)"(J)J", (void*)mtl_pipeline_cast_pipeline_ptr },
		{ (char*)"base_pipeline_ptr", (char*)"(J)J", (void*)mtl_pipeline_base_pipeline_ptr },
		{ (char*)"set_indirect", (char*)"(JZ)V", (void*)mtl_pipeline_set_indirect },
		{ (char*)"is_indirect", (char*)"(J)Z", (void*)mtl_pipeline_is_indirect },
		{ (char*)"get_vertex_function", (char*)"(J)J", (void*)mtl_pipeline_get_vertex_function },
		{ (char*)"get_fragment_function", (char*)"(J)J", (void*)mtl_pipeline_get_fragment_function },
	};
	
	// Tellusim::FUPipeline
	static jlong fu_pipeline_new(TS_JNI_ARGS) {
		return newFUPipeline();
	}
	static jlong fu_pipeline_new_1(TS_JNI_ARGS, jlongArray pipelines, jboolean owner) {
		Array<Pipeline> pipelines_((uint32_t)env->GetArrayLength(pipelines));
		jlong *pipelines__ = env->GetLongArrayElements(pipelines, nullptr);
		for(uint32_t i = 0; i < pipelines_.size(); i++) pipelines_[i] = toPipeline(pipelines__[i]);
		jlong ret_ = newFUPipeline(pipelines_, (bool)owner);
		if(pipelines__) env->ReleaseLongArrayElements(pipelines, pipelines__, 0);
		return ret_;
	}
	static void fu_pipeline_delete(TS_JNI_ARGS, jlong self) {
		delete (FUPipeline*)self;
	}
	static jboolean fu_pipeline_equal_pipeline_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUPipeline(self).operator==(toPipeline(base));
	}
	static jlong fu_pipeline_cast_pipeline_ptr(TS_JNI_ARGS, jlong self) {
		return newFUPipeline(toPipeline(self));
	}
	static jlong fu_pipeline_base_pipeline_ptr(TS_JNI_ARGS, jlong self) {
		return newPipeline(toFUPipeline(self).getPipeline());
	}
	static void fu_pipeline_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUPipeline(self).setMask((uint32_t)mask);
	}
	static jint fu_pipeline_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUPipeline(self).getMask();
	}
	static jint fu_pipeline_get_num_pipelines(TS_JNI_ARGS, jlong self) {
		return toFUPipeline(self).getNumPipelines();
	}
	static jlong fu_pipeline_get_pipeline(TS_JNI_ARGS, jlong self, jint index) {
		return newPipeline(toFUPipeline(self).getPipeline((uint32_t)index));
	}
	static jlong fu_pipeline_get_pipeline_1(TS_JNI_ARGS, jlong self, jint index) {
		return newPipeline(toFUPipeline(self).getPipeline((uint32_t)index));
	}
	static const JNINativeMethod fu_pipeline_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_pipeline_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_pipeline_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_pipeline_delete },
		{ (char*)"equal_pipeline_ptr", (char*)"(JJ)Z", (void*)fu_pipeline_equal_pipeline_ptr },
		{ (char*)"cast_pipeline_ptr", (char*)"(J)J", (void*)fu_pipeline_cast_pipeline_ptr },
		{ (char*)"base_pipeline_ptr", (char*)"(J)J", (void*)fu_pipeline_base_pipeline_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_pipeline_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_pipeline_get_mask },
		{ (char*)"get_num_pipelines", (char*)"(J)I", (void*)fu_pipeline_get_num_pipelines },
		{ (char*)"get_pipeline", (char*)"(JI)J", (void*)fu_pipeline_get_pipeline },
		{ (char*)"get_pipeline_1", (char*)"(JI)J", (void*)fu_pipeline_get_pipeline_1 },
	};
	
	// Tellusim::Traversal
	static jlong traversal_new(TS_JNI_ARGS) {
		return newTraversal();
	}
	static void traversal_delete(TS_JNI_ARGS, jlong self) {
		delete (Traversal*)self;
	}
	static jboolean traversal_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toTraversal(self) == toTraversal(ptr));
	}
	static jlong traversal_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newTraversal(toTraversal(self).clonePtr());
	}
	static void traversal_clear_ptr(TS_JNI_ARGS, jlong self) {
		toTraversal(self).clearPtr();
	}
	static void traversal_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toTraversal(self).destroyPtr();
	}
	static void traversal_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toTraversal(self).acquirePtr();
	}
	static void traversal_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toTraversal(self).unacquirePtr();
	}
	static jboolean traversal_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).isValidPtr();
	}
	static jboolean traversal_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).isOwnerPtr();
	}
	static jboolean traversal_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).isConstPtr();
	}
	static jint traversal_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getCountPtr();
	}
	static jlong traversal_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toTraversal(self).getInternalPtr();
	}
	static jint traversal_get_platform(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getPlatform();
	}
	static jstring traversal_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTraversal(self).getPlatformName());
	}
	static jint traversal_get_index(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getIndex();
	}
	static void traversal_clear(TS_JNI_ARGS, jlong self) {
		toTraversal(self).clear();
	}
	static jboolean traversal_is_created(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).isCreated();
	}
	static void traversal_set_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toTraversal(self).setName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jstring traversal_get_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toTraversal(self).getName().get());
	}
	static jboolean traversal_create(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).create();
	}
	static void traversal_set_parameters(TS_JNI_ARGS, jlong self, jlong traversal) {
		toTraversal(self).setParameters(toTraversal(traversal));
	}
	static jboolean traversal_save_state(TS_JNI_ARGS, jlong self, jlong stream) {
		return toTraversal(self).saveState(toStream(stream));
	}
	static void traversal_add_shader(TS_JNI_ARGS, jlong self, jlong shader, jboolean owner) {
		toTraversal(self).addShader(toShader(shader), (bool)owner);
	}
	static jlong traversal_get_ray_gen_shader(TS_JNI_ARGS, jlong self) {
		return newShader(toTraversal(self).getRayGenShader());
	}
	static jboolean traversal_load_shader(TS_JNI_ARGS, jlong self, jint type, jstring name, jstring format) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toTraversal(self).loadShader((Shader::Type)type, name_, "%s", format_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean traversal_load_shader_glsl(TS_JNI_ARGS, jlong self, jint type, jstring name, jstring format) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toTraversal(self).loadShaderGLSL((Shader::Type)type, name_, "%s", format_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean traversal_load_shader_1(TS_JNI_ARGS, jlong self, jint type, jstring name, jlong macros, jstringArray includes, jint size) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toTraversal(self).loadShader((Shader::Type)type, name_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(name, name_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean traversal_load_shader_glsl_1(TS_JNI_ARGS, jlong self, jint type, jstring name, jlong macros, jstringArray includes, jint size) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toTraversal(self).loadShaderGLSL((Shader::Type)type, name_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(name, name_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean traversal_load_shader_spirv(TS_JNI_ARGS, jlong self, jint type, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toTraversal(self).loadShaderSPIRV((Shader::Type)type, name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean traversal_create_shader(TS_JNI_ARGS, jlong self, jint type, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toTraversal(self).createShader((Shader::Type)type, src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean traversal_create_shader_glsl(TS_JNI_ARGS, jlong self, jint type, jstring src, jstring format) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		bool ret_ = toTraversal(self).createShaderGLSL((Shader::Type)type, src_, "%s", format_);
		env->ReleaseStringUTFChars(src, src_);
		env->ReleaseStringUTFChars(format, format_);
		return ret_;
	}
	static jboolean traversal_create_shader_1(TS_JNI_ARGS, jlong self, jint type, jstring src, jlong macros, jstringArray includes, jint size) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toTraversal(self).createShader((Shader::Type)type, src_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(src, src_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean traversal_create_shader_glsl_1(TS_JNI_ARGS, jlong self, jint type, jstring src, jlong macros, jstringArray includes, jint size) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		Array<const char*> includes_((includes) ? (uint32_t)env->GetArrayLength(includes) : 0);
		for(uint32_t i = 0; i < includes_.size(); i++) includes_[i] = (const char*)env->GetStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), nullptr);
		bool ret_ = toTraversal(self).createShaderGLSL((Shader::Type)type, src_, toString(macros), includes_.get(), (uint32_t)size);
		env->ReleaseStringUTFChars(src, src_);
		for(uint32_t i = 0; i < includes_.size(); i++) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(includes, i), includes_[i]);
		return ret_;
	}
	static jboolean traversal_create_shader_spirv(TS_JNI_ARGS, jlong self, jint type, jintArray data) {
		uint32_t *data__ = (uint32_t*)env->GetIntArrayElements(data, nullptr);
		Array<uint32_t> data_((uint32_t)env->GetArrayLength(data), data__);
		bool ret_ = toTraversal(self).createShaderSPIRV((Shader::Type)type, data_);
		if(data_) env->ReleaseIntArrayElements(data, (jint*)data__, 0);
		return ret_;
	}
	static jint traversal_add_sampler(TS_JNI_ARGS, jlong self, jint mask) {
		return toTraversal(self).addSampler((Shader::Mask)mask);
	}
	static jint traversal_get_num_samplers(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getNumSamplers();
	}
	static jlong traversal_set_sampler_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newTraversal(toTraversal(self).setSamplerOffset((uint32_t)offset));
	}
	static jint traversal_get_sampler_offset(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getSamplerOffset();
	}
	static jlong traversal_set_sampler_mask(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		return newTraversal(toTraversal(self).setSamplerMask((uint32_t)index, (Shader::Mask)mask));
	}
	static jint traversal_get_sampler_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getSamplerMask((uint32_t)index);
	}
	static jlong traversal_set_sampler_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask, jboolean array) {
		return newTraversal(toTraversal(self).setSamplerMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask, (bool)array));
	}
	static jint traversal_get_sampler_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toTraversal(self).getSamplerMasks((uint32_t)index, (uint32_t)num);
	}
	static jlong traversal_set_sampler_array(TS_JNI_ARGS, jlong self, jint index, jint num, jboolean array) {
		return newTraversal(toTraversal(self).setSamplerArray((uint32_t)index, (uint32_t)num, (bool)array));
	}
	static jint traversal_get_sampler_array(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getSamplerArray((uint32_t)index);
	}
	static jint traversal_add_texture(TS_JNI_ARGS, jlong self, jint mask) {
		return toTraversal(self).addTexture((Shader::Mask)mask);
	}
	static jint traversal_get_num_textures(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getNumTextures();
	}
	static jlong traversal_set_texture_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newTraversal(toTraversal(self).setTextureOffset((uint32_t)offset));
	}
	static jint traversal_get_texture_offset(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getTextureOffset();
	}
	static jlong traversal_set_texture_mask(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		return newTraversal(toTraversal(self).setTextureMask((uint32_t)index, (Shader::Mask)mask));
	}
	static jint traversal_get_texture_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getTextureMask((uint32_t)index);
	}
	static jlong traversal_set_texture_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask, jboolean array) {
		return newTraversal(toTraversal(self).setTextureMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask, (bool)array));
	}
	static jint traversal_get_texture_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toTraversal(self).getTextureMasks((uint32_t)index, (uint32_t)num);
	}
	static jlong traversal_set_texture_array(TS_JNI_ARGS, jlong self, jint index, jint num, jboolean array) {
		return newTraversal(toTraversal(self).setTextureArray((uint32_t)index, (uint32_t)num, (bool)array));
	}
	static jint traversal_get_texture_array(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getTextureArray((uint32_t)index);
	}
	static jint traversal_add_surface(TS_JNI_ARGS, jlong self, jint mask) {
		return toTraversal(self).addSurface((Shader::Mask)mask);
	}
	static jint traversal_get_num_surfaces(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getNumSurfaces();
	}
	static jlong traversal_set_surface_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newTraversal(toTraversal(self).setSurfaceOffset((uint32_t)offset));
	}
	static jint traversal_get_surface_offset(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getSurfaceOffset();
	}
	static jlong traversal_set_surface_mask(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		return newTraversal(toTraversal(self).setSurfaceMask((uint32_t)index, (Shader::Mask)mask));
	}
	static jint traversal_get_surface_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getSurfaceMask((uint32_t)index);
	}
	static jlong traversal_set_surface_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask, jboolean array) {
		return newTraversal(toTraversal(self).setSurfaceMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask, (bool)array));
	}
	static jint traversal_get_surface_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toTraversal(self).getSurfaceMasks((uint32_t)index, (uint32_t)num);
	}
	static jlong traversal_set_surface_array(TS_JNI_ARGS, jlong self, jint index, jint num, jboolean array) {
		return newTraversal(toTraversal(self).setSurfaceArray((uint32_t)index, (uint32_t)num, (bool)array));
	}
	static jint traversal_get_surface_array(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getSurfaceArray((uint32_t)index);
	}
	static jint traversal_add_uniform(TS_JNI_ARGS, jlong self, jint mask, jint flags) {
		return toTraversal(self).addUniform((Shader::Mask)mask, (BindFlags)flags);
	}
	static jint traversal_get_num_uniforms(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getNumUniforms();
	}
	static jlong traversal_set_uniform_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newTraversal(toTraversal(self).setUniformOffset((uint32_t)offset));
	}
	static jint traversal_get_uniform_offset(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getUniformOffset();
	}
	static jlong traversal_set_uniform_mask(TS_JNI_ARGS, jlong self, jint index, jint mask, jint flags) {
		return newTraversal(toTraversal(self).setUniformMask((uint32_t)index, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint traversal_get_uniform_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getUniformMask((uint32_t)index);
	}
	static jlong traversal_set_uniform_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask, jint flags) {
		return newTraversal(toTraversal(self).setUniformMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint traversal_get_uniform_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toTraversal(self).getUniformMasks((uint32_t)index, (uint32_t)num);
	}
	static jlong traversal_set_uniform_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return newTraversal(toTraversal(self).setUniformFlags((uint32_t)index, (BindFlags)flags));
	}
	static jint traversal_get_uniform_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getUniformFlags((uint32_t)index);
	}
	static jint traversal_add_storage(TS_JNI_ARGS, jlong self, jint mask, jint flags) {
		return toTraversal(self).addStorage((Shader::Mask)mask, (BindFlags)flags);
	}
	static jint traversal_get_num_storages(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getNumStorages();
	}
	static jlong traversal_set_storage_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newTraversal(toTraversal(self).setStorageOffset((uint32_t)offset));
	}
	static jint traversal_get_storage_offset(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getStorageOffset();
	}
	static jlong traversal_set_storage_mask(TS_JNI_ARGS, jlong self, jint index, jint mask, jint flags) {
		return newTraversal(toTraversal(self).setStorageMask((uint32_t)index, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint traversal_get_storage_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getStorageMask((uint32_t)index);
	}
	static jlong traversal_set_storage_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask, jint flags) {
		return newTraversal(toTraversal(self).setStorageMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint traversal_get_storage_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toTraversal(self).getStorageMasks((uint32_t)index, (uint32_t)num);
	}
	static jlong traversal_set_storage_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return newTraversal(toTraversal(self).setStorageFlags((uint32_t)index, (BindFlags)flags));
	}
	static jint traversal_get_storage_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getStorageFlags((uint32_t)index);
	}
	static jint traversal_add_tracing(TS_JNI_ARGS, jlong self, jint mask) {
		return toTraversal(self).addTracing((Shader::Mask)mask);
	}
	static jint traversal_get_num_tracings(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getNumTracings();
	}
	static jlong traversal_set_tracing_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newTraversal(toTraversal(self).setTracingOffset((uint32_t)offset));
	}
	static jint traversal_get_tracing_offset(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getTracingOffset();
	}
	static jlong traversal_set_tracing_mask(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		return newTraversal(toTraversal(self).setTracingMask((uint32_t)index, (Shader::Mask)mask));
	}
	static jint traversal_get_tracing_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getTracingMask((uint32_t)index);
	}
	static jlong traversal_set_tracing_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask) {
		return newTraversal(toTraversal(self).setTracingMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask));
	}
	static jint traversal_get_tracing_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toTraversal(self).getTracingMasks((uint32_t)index, (uint32_t)num);
	}
	static jint traversal_add_texel(TS_JNI_ARGS, jlong self, jint mask) {
		return toTraversal(self).addTexel((Shader::Mask)mask);
	}
	static jint traversal_get_num_texels(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getNumTexels();
	}
	static jlong traversal_set_texel_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newTraversal(toTraversal(self).setTexelOffset((uint32_t)offset));
	}
	static jint traversal_get_texel_offset(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getTexelOffset();
	}
	static jlong traversal_set_texel_mask(TS_JNI_ARGS, jlong self, jint index, jint mask) {
		return newTraversal(toTraversal(self).setTexelMask((uint32_t)index, (Shader::Mask)mask));
	}
	static jint traversal_get_texel_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getTexelMask((uint32_t)index);
	}
	static jlong traversal_set_texel_masks(TS_JNI_ARGS, jlong self, jint index, jint num, jint mask) {
		return newTraversal(toTraversal(self).setTexelMasks((uint32_t)index, (uint32_t)num, (Shader::Mask)mask));
	}
	static jint traversal_get_texel_masks(TS_JNI_ARGS, jlong self, jint index, jint num) {
		return toTraversal(self).getTexelMasks((uint32_t)index, (uint32_t)num);
	}
	static jint traversal_add_table(TS_JNI_ARGS, jlong self, jint type, jint size, jint mask, jint flags) {
		return toTraversal(self).addTable((TableType)type, (uint32_t)size, (Shader::Mask)mask, (BindFlags)flags);
	}
	static jint traversal_get_num_tables(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getNumTables();
	}
	static jlong traversal_set_table_offset(TS_JNI_ARGS, jlong self, jint offset) {
		return newTraversal(toTraversal(self).setTableOffset((uint32_t)offset));
	}
	static jint traversal_get_table_offset(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getTableOffset();
	}
	static jlong traversal_set_table_type(TS_JNI_ARGS, jlong self, jint index, jint type, jint size, jint mask, jint flags) {
		return newTraversal(toTraversal(self).setTableType((uint32_t)index, (TableType)type, (uint32_t)size, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint traversal_get_table_type(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getTableType((uint32_t)index);
	}
	static jint traversal_get_table_size(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getTableSize((uint32_t)index);
	}
	static jlong traversal_set_table_mask(TS_JNI_ARGS, jlong self, jint index, jint mask, jint flags) {
		return newTraversal(toTraversal(self).setTableMask((uint32_t)index, (Shader::Mask)mask, (BindFlags)flags));
	}
	static jint traversal_get_table_mask(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getTableMask((uint32_t)index);
	}
	static jlong traversal_set_table_flags(TS_JNI_ARGS, jlong self, jint index, jint flags) {
		return newTraversal(toTraversal(self).setTableFlags((uint32_t)index, (BindFlags)flags));
	}
	static jint traversal_get_table_flags(TS_JNI_ARGS, jlong self, jint index) {
		return toTraversal(self).getTableFlags((uint32_t)index);
	}
	static void traversal_set_recursion_depth(TS_JNI_ARGS, jlong self, jint depth) {
		toTraversal(self).setRecursionDepth((uint32_t)depth);
	}
	static jint traversal_get_recursion_depth(TS_JNI_ARGS, jlong self) {
		return toTraversal(self).getRecursionDepth();
	}
	static const JNINativeMethod traversal_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)traversal_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)traversal_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)traversal_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)traversal_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)traversal_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)traversal_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)traversal_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)traversal_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)traversal_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)traversal_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)traversal_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)traversal_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)traversal_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)traversal_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)traversal_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)traversal_get_index },
		{ (char*)"clear_", (char*)"(J)V", (void*)traversal_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)traversal_is_created },
		{ (char*)"set_name", (char*)"(JLjava/lang/String;)V", (void*)traversal_set_name },
		{ (char*)"get_name", (char*)"(J)Ljava/lang/String;", (void*)traversal_get_name },
		{ (char*)"create_", (char*)"(J)Z", (void*)traversal_create },
		{ (char*)"set_parameters", (char*)"(JJ)V", (void*)traversal_set_parameters },
		{ (char*)"save_state", (char*)"(JJ)Z", (void*)traversal_save_state },
		{ (char*)"add_shader", (char*)"(JJZ)V", (void*)traversal_add_shader },
		{ (char*)"get_ray_gen_shader", (char*)"(J)J", (void*)traversal_get_ray_gen_shader },
		{ (char*)"load_shader", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)traversal_load_shader },
		{ (char*)"load_shader_glsl", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)traversal_load_shader_glsl },
		{ (char*)"load_shader_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)traversal_load_shader_1 },
		{ (char*)"load_shader_glsl_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)traversal_load_shader_glsl_1 },
		{ (char*)"load_shader_spirv", (char*)"(JILjava/lang/String;)Z", (void*)traversal_load_shader_spirv },
		{ (char*)"create_shader", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)traversal_create_shader },
		{ (char*)"create_shader_glsl", (char*)"(JILjava/lang/String;Ljava/lang/String;)Z", (void*)traversal_create_shader_glsl },
		{ (char*)"create_shader_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)traversal_create_shader_1 },
		{ (char*)"create_shader_glsl_1", (char*)"(JILjava/lang/String;J[Ljava/lang/String;I)Z", (void*)traversal_create_shader_glsl_1 },
		{ (char*)"create_shader_spirv", (char*)"(JI[I)Z", (void*)traversal_create_shader_spirv },
		{ (char*)"add_sampler", (char*)"(JI)I", (void*)traversal_add_sampler },
		{ (char*)"get_num_samplers", (char*)"(J)I", (void*)traversal_get_num_samplers },
		{ (char*)"set_sampler_offset", (char*)"(JI)J", (void*)traversal_set_sampler_offset },
		{ (char*)"get_sampler_offset", (char*)"(J)I", (void*)traversal_get_sampler_offset },
		{ (char*)"set_sampler_mask", (char*)"(JII)J", (void*)traversal_set_sampler_mask },
		{ (char*)"get_sampler_mask", (char*)"(JI)I", (void*)traversal_get_sampler_mask },
		{ (char*)"set_sampler_masks", (char*)"(JIIIZ)J", (void*)traversal_set_sampler_masks },
		{ (char*)"get_sampler_masks", (char*)"(JII)I", (void*)traversal_get_sampler_masks },
		{ (char*)"set_sampler_array", (char*)"(JIIZ)J", (void*)traversal_set_sampler_array },
		{ (char*)"get_sampler_array", (char*)"(JI)I", (void*)traversal_get_sampler_array },
		{ (char*)"add_texture", (char*)"(JI)I", (void*)traversal_add_texture },
		{ (char*)"get_num_textures", (char*)"(J)I", (void*)traversal_get_num_textures },
		{ (char*)"set_texture_offset", (char*)"(JI)J", (void*)traversal_set_texture_offset },
		{ (char*)"get_texture_offset", (char*)"(J)I", (void*)traversal_get_texture_offset },
		{ (char*)"set_texture_mask", (char*)"(JII)J", (void*)traversal_set_texture_mask },
		{ (char*)"get_texture_mask", (char*)"(JI)I", (void*)traversal_get_texture_mask },
		{ (char*)"set_texture_masks", (char*)"(JIIIZ)J", (void*)traversal_set_texture_masks },
		{ (char*)"get_texture_masks", (char*)"(JII)I", (void*)traversal_get_texture_masks },
		{ (char*)"set_texture_array", (char*)"(JIIZ)J", (void*)traversal_set_texture_array },
		{ (char*)"get_texture_array", (char*)"(JI)I", (void*)traversal_get_texture_array },
		{ (char*)"add_surface", (char*)"(JI)I", (void*)traversal_add_surface },
		{ (char*)"get_num_surfaces", (char*)"(J)I", (void*)traversal_get_num_surfaces },
		{ (char*)"set_surface_offset", (char*)"(JI)J", (void*)traversal_set_surface_offset },
		{ (char*)"get_surface_offset", (char*)"(J)I", (void*)traversal_get_surface_offset },
		{ (char*)"set_surface_mask", (char*)"(JII)J", (void*)traversal_set_surface_mask },
		{ (char*)"get_surface_mask", (char*)"(JI)I", (void*)traversal_get_surface_mask },
		{ (char*)"set_surface_masks", (char*)"(JIIIZ)J", (void*)traversal_set_surface_masks },
		{ (char*)"get_surface_masks", (char*)"(JII)I", (void*)traversal_get_surface_masks },
		{ (char*)"set_surface_array", (char*)"(JIIZ)J", (void*)traversal_set_surface_array },
		{ (char*)"get_surface_array", (char*)"(JI)I", (void*)traversal_get_surface_array },
		{ (char*)"add_uniform", (char*)"(JII)I", (void*)traversal_add_uniform },
		{ (char*)"get_num_uniforms", (char*)"(J)I", (void*)traversal_get_num_uniforms },
		{ (char*)"set_uniform_offset", (char*)"(JI)J", (void*)traversal_set_uniform_offset },
		{ (char*)"get_uniform_offset", (char*)"(J)I", (void*)traversal_get_uniform_offset },
		{ (char*)"set_uniform_mask", (char*)"(JIII)J", (void*)traversal_set_uniform_mask },
		{ (char*)"get_uniform_mask", (char*)"(JI)I", (void*)traversal_get_uniform_mask },
		{ (char*)"set_uniform_masks", (char*)"(JIIII)J", (void*)traversal_set_uniform_masks },
		{ (char*)"get_uniform_masks", (char*)"(JII)I", (void*)traversal_get_uniform_masks },
		{ (char*)"set_uniform_flags", (char*)"(JII)J", (void*)traversal_set_uniform_flags },
		{ (char*)"get_uniform_flags", (char*)"(JI)I", (void*)traversal_get_uniform_flags },
		{ (char*)"add_storage", (char*)"(JII)I", (void*)traversal_add_storage },
		{ (char*)"get_num_storages", (char*)"(J)I", (void*)traversal_get_num_storages },
		{ (char*)"set_storage_offset", (char*)"(JI)J", (void*)traversal_set_storage_offset },
		{ (char*)"get_storage_offset", (char*)"(J)I", (void*)traversal_get_storage_offset },
		{ (char*)"set_storage_mask", (char*)"(JIII)J", (void*)traversal_set_storage_mask },
		{ (char*)"get_storage_mask", (char*)"(JI)I", (void*)traversal_get_storage_mask },
		{ (char*)"set_storage_masks", (char*)"(JIIII)J", (void*)traversal_set_storage_masks },
		{ (char*)"get_storage_masks", (char*)"(JII)I", (void*)traversal_get_storage_masks },
		{ (char*)"set_storage_flags", (char*)"(JII)J", (void*)traversal_set_storage_flags },
		{ (char*)"get_storage_flags", (char*)"(JI)I", (void*)traversal_get_storage_flags },
		{ (char*)"add_tracing", (char*)"(JI)I", (void*)traversal_add_tracing },
		{ (char*)"get_num_tracings", (char*)"(J)I", (void*)traversal_get_num_tracings },
		{ (char*)"set_tracing_offset", (char*)"(JI)J", (void*)traversal_set_tracing_offset },
		{ (char*)"get_tracing_offset", (char*)"(J)I", (void*)traversal_get_tracing_offset },
		{ (char*)"set_tracing_mask", (char*)"(JII)J", (void*)traversal_set_tracing_mask },
		{ (char*)"get_tracing_mask", (char*)"(JI)I", (void*)traversal_get_tracing_mask },
		{ (char*)"set_tracing_masks", (char*)"(JIII)J", (void*)traversal_set_tracing_masks },
		{ (char*)"get_tracing_masks", (char*)"(JII)I", (void*)traversal_get_tracing_masks },
		{ (char*)"add_texel", (char*)"(JI)I", (void*)traversal_add_texel },
		{ (char*)"get_num_texels", (char*)"(J)I", (void*)traversal_get_num_texels },
		{ (char*)"set_texel_offset", (char*)"(JI)J", (void*)traversal_set_texel_offset },
		{ (char*)"get_texel_offset", (char*)"(J)I", (void*)traversal_get_texel_offset },
		{ (char*)"set_texel_mask", (char*)"(JII)J", (void*)traversal_set_texel_mask },
		{ (char*)"get_texel_mask", (char*)"(JI)I", (void*)traversal_get_texel_mask },
		{ (char*)"set_texel_masks", (char*)"(JIII)J", (void*)traversal_set_texel_masks },
		{ (char*)"get_texel_masks", (char*)"(JII)I", (void*)traversal_get_texel_masks },
		{ (char*)"add_table", (char*)"(JIIII)I", (void*)traversal_add_table },
		{ (char*)"get_num_tables", (char*)"(J)I", (void*)traversal_get_num_tables },
		{ (char*)"set_table_offset", (char*)"(JI)J", (void*)traversal_set_table_offset },
		{ (char*)"get_table_offset", (char*)"(J)I", (void*)traversal_get_table_offset },
		{ (char*)"set_table_type", (char*)"(JIIIII)J", (void*)traversal_set_table_type },
		{ (char*)"get_table_type", (char*)"(JI)I", (void*)traversal_get_table_type },
		{ (char*)"get_table_size", (char*)"(JI)I", (void*)traversal_get_table_size },
		{ (char*)"set_table_mask", (char*)"(JIII)J", (void*)traversal_set_table_mask },
		{ (char*)"get_table_mask", (char*)"(JI)I", (void*)traversal_get_table_mask },
		{ (char*)"set_table_flags", (char*)"(JII)J", (void*)traversal_set_table_flags },
		{ (char*)"get_table_flags", (char*)"(JI)I", (void*)traversal_get_table_flags },
		{ (char*)"set_recursion_depth", (char*)"(JI)V", (void*)traversal_set_recursion_depth },
		{ (char*)"get_recursion_depth", (char*)"(J)I", (void*)traversal_get_recursion_depth },
	};
	
	// Tellusim::D3D12Traversal
	static jlong d3d12_traversal_new(TS_JNI_ARGS) {
		return newD3D12Traversal();
	}
	static void d3d12_traversal_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Traversal*)self;
	}
	static jboolean d3d12_traversal_equal_traversal_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Traversal(self).operator==(toTraversal(base));
	}
	static jlong d3d12_traversal_cast_traversal_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Traversal(toTraversal(self));
	}
	static jlong d3d12_traversal_base_traversal_ptr(TS_JNI_ARGS, jlong self) {
		return newTraversal(toD3D12Traversal(self).getTraversal());
	}
	static jlong d3d12_traversal_get_root_signature(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Traversal(self).getRootSignature();
	}
	static const JNINativeMethod d3d12_traversal_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_traversal_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_traversal_delete },
		{ (char*)"equal_traversal_ptr", (char*)"(JJ)Z", (void*)d3d12_traversal_equal_traversal_ptr },
		{ (char*)"cast_traversal_ptr", (char*)"(J)J", (void*)d3d12_traversal_cast_traversal_ptr },
		{ (char*)"base_traversal_ptr", (char*)"(J)J", (void*)d3d12_traversal_base_traversal_ptr },
		{ (char*)"get_root_signature", (char*)"(J)J", (void*)d3d12_traversal_get_root_signature },
	};
	
	// Tellusim::FUTraversal
	static jlong fu_traversal_new(TS_JNI_ARGS) {
		return newFUTraversal();
	}
	static jlong fu_traversal_new_1(TS_JNI_ARGS, jlongArray traversals, jboolean owner) {
		Array<Traversal> traversals_((uint32_t)env->GetArrayLength(traversals));
		jlong *traversals__ = env->GetLongArrayElements(traversals, nullptr);
		for(uint32_t i = 0; i < traversals_.size(); i++) traversals_[i] = toTraversal(traversals__[i]);
		jlong ret_ = newFUTraversal(traversals_, (bool)owner);
		if(traversals__) env->ReleaseLongArrayElements(traversals, traversals__, 0);
		return ret_;
	}
	static void fu_traversal_delete(TS_JNI_ARGS, jlong self) {
		delete (FUTraversal*)self;
	}
	static jboolean fu_traversal_equal_traversal_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toFUTraversal(self).operator==(toTraversal(base));
	}
	static jlong fu_traversal_cast_traversal_ptr(TS_JNI_ARGS, jlong self) {
		return newFUTraversal(toTraversal(self));
	}
	static jlong fu_traversal_base_traversal_ptr(TS_JNI_ARGS, jlong self) {
		return newTraversal(toFUTraversal(self).getTraversal());
	}
	static void fu_traversal_set_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toFUTraversal(self).setMask((uint32_t)mask);
	}
	static jint fu_traversal_get_mask(TS_JNI_ARGS, jlong self) {
		return toFUTraversal(self).getMask();
	}
	static jint fu_traversal_get_num_traversals(TS_JNI_ARGS, jlong self) {
		return toFUTraversal(self).getNumTraversals();
	}
	static jlong fu_traversal_get_traversal(TS_JNI_ARGS, jlong self, jint index) {
		return newTraversal(toFUTraversal(self).getTraversal((uint32_t)index));
	}
	static jlong fu_traversal_get_traversal_1(TS_JNI_ARGS, jlong self, jint index) {
		return newTraversal(toFUTraversal(self).getTraversal((uint32_t)index));
	}
	static const JNINativeMethod fu_traversal_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fu_traversal_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)fu_traversal_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)fu_traversal_delete },
		{ (char*)"equal_traversal_ptr", (char*)"(JJ)Z", (void*)fu_traversal_equal_traversal_ptr },
		{ (char*)"cast_traversal_ptr", (char*)"(J)J", (void*)fu_traversal_cast_traversal_ptr },
		{ (char*)"base_traversal_ptr", (char*)"(J)J", (void*)fu_traversal_base_traversal_ptr },
		{ (char*)"set_mask", (char*)"(JI)V", (void*)fu_traversal_set_mask },
		{ (char*)"get_mask", (char*)"(J)I", (void*)fu_traversal_get_mask },
		{ (char*)"get_num_traversals", (char*)"(J)I", (void*)fu_traversal_get_num_traversals },
		{ (char*)"get_traversal", (char*)"(JI)J", (void*)fu_traversal_get_traversal },
		{ (char*)"get_traversal_1", (char*)"(JI)J", (void*)fu_traversal_get_traversal_1 },
	};
	
	// Tellusim::Surface
	static jlong surface_new(TS_JNI_ARGS) {
		return newSurface();
	}
	static jlong surface_new_1(TS_JNI_ARGS, jlong context) {
		return newSurface(toContext(context));
	}
	static jlong surface_new_2(TS_JNI_ARGS, jint platform) {
		return newSurface((Platform)platform);
	}
	static void surface_delete(TS_JNI_ARGS, jlong self) {
		delete (Surface*)self;
	}
	static jboolean surface_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toSurface(self) == toSurface(ptr));
	}
	static jlong surface_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newSurface(toSurface(self).clonePtr());
	}
	static void surface_clear_ptr(TS_JNI_ARGS, jlong self) {
		toSurface(self).clearPtr();
	}
	static void surface_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toSurface(self).destroyPtr();
	}
	static void surface_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toSurface(self).acquirePtr();
	}
	static void surface_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toSurface(self).unacquirePtr();
	}
	static jboolean surface_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toSurface(self).isValidPtr();
	}
	static jboolean surface_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toSurface(self).isOwnerPtr();
	}
	static jboolean surface_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toSurface(self).isConstPtr();
	}
	static jint surface_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getCountPtr();
	}
	static jlong surface_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toSurface(self).getInternalPtr();
	}
	static jint surface_get_platform(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getPlatform();
	}
	static jstring surface_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toSurface(self).getPlatformName());
	}
	static jint surface_get_index(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getIndex();
	}
	static void surface_set_size(TS_JNI_ARGS, jlong self, jint width, jint height) {
		toSurface(self).setSize((uint32_t)width, (uint32_t)height);
	}
	static jint surface_get_width(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getWidth();
	}
	static jint surface_get_height(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getHeight();
	}
	static void surface_set_multisample(TS_JNI_ARGS, jlong self, jint multisample) {
		toSurface(self).setMultisample((uint32_t)multisample);
	}
	static jint surface_get_multisample(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getMultisample();
	}
	static jboolean surface_has_multisample(TS_JNI_ARGS, jlong self) {
		return toSurface(self).hasMultisample();
	}
	static void surface_set_color_layer(TS_JNI_ARGS, jlong self, jint layer, jint layers) {
		toSurface(self).setColorLayer((uint32_t)layer, (uint32_t)layers);
	}
	static void surface_set_depth_layer(TS_JNI_ARGS, jlong self, jint layer, jint layers) {
		toSurface(self).setDepthLayer((uint32_t)layer, (uint32_t)layers);
	}
	static jint surface_get_color_layer(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getColorLayer();
	}
	static jint surface_get_depth_layer(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getDepthLayer();
	}
	static jint surface_get_color_layers(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getColorLayers();
	}
	static jint surface_get_depth_layers(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getDepthLayers();
	}
	static jboolean surface_has_color_layers(TS_JNI_ARGS, jlong self) {
		return toSurface(self).hasColorLayers();
	}
	static jboolean surface_has_depth_layers(TS_JNI_ARGS, jlong self) {
		return toSurface(self).hasDepthLayers();
	}
	static void surface_set_color_format(TS_JNI_ARGS, jlong self, jint format) {
		toSurface(self).setColorFormat((Format)format);
	}
	static void surface_set_depth_format(TS_JNI_ARGS, jlong self, jint format) {
		toSurface(self).setDepthFormat((Format)format);
	}
	static jint surface_get_color_format(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getColorFormat();
	}
	static jint surface_get_depth_format(TS_JNI_ARGS, jlong self) {
		return toSurface(self).getDepthFormat();
	}
	static const JNINativeMethod surface_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)surface_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)surface_new_1 },
		{ (char*)"new_2", (char*)"(I)J", (void*)surface_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)surface_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)surface_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)surface_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)surface_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)surface_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)surface_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)surface_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)surface_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)surface_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)surface_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)surface_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)surface_get_internal_ptr },
		{ (char*)"get_platform", (char*)"(J)I", (void*)surface_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)surface_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)surface_get_index },
		{ (char*)"set_size", (char*)"(JII)V", (void*)surface_set_size },
		{ (char*)"get_width", (char*)"(J)I", (void*)surface_get_width },
		{ (char*)"get_height", (char*)"(J)I", (void*)surface_get_height },
		{ (char*)"set_multisample", (char*)"(JI)V", (void*)surface_set_multisample },
		{ (char*)"get_multisample", (char*)"(J)I", (void*)surface_get_multisample },
		{ (char*)"has_multisample", (char*)"(J)Z", (void*)surface_has_multisample },
		{ (char*)"set_color_layer", (char*)"(JII)V", (void*)surface_set_color_layer },
		{ (char*)"set_depth_layer", (char*)"(JII)V", (void*)surface_set_depth_layer },
		{ (char*)"get_color_layer", (char*)"(J)I", (void*)surface_get_color_layer },
		{ (char*)"get_depth_layer", (char*)"(J)I", (void*)surface_get_depth_layer },
		{ (char*)"get_color_layers", (char*)"(J)I", (void*)surface_get_color_layers },
		{ (char*)"get_depth_layers", (char*)"(J)I", (void*)surface_get_depth_layers },
		{ (char*)"has_color_layers", (char*)"(J)Z", (void*)surface_has_color_layers },
		{ (char*)"has_depth_layers", (char*)"(J)Z", (void*)surface_has_depth_layers },
		{ (char*)"set_color_format", (char*)"(JI)V", (void*)surface_set_color_format },
		{ (char*)"set_depth_format", (char*)"(JI)V", (void*)surface_set_depth_format },
		{ (char*)"get_color_format", (char*)"(J)I", (void*)surface_get_color_format },
		{ (char*)"get_depth_format", (char*)"(J)I", (void*)surface_get_depth_format },
	};
	
	// Tellusim::D3D12Surface
	static jlong d3d12_surface_new(TS_JNI_ARGS) {
		return newD3D12Surface();
	}
	static jlong d3d12_surface_new_1(TS_JNI_ARGS, jlong context) {
		return newD3D12Surface(toD3D12Context(context));
	}
	static void d3d12_surface_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D12Surface*)self;
	}
	static jboolean d3d12_surface_equal_surface_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D12Surface(self).operator==(toSurface(base));
	}
	static jlong d3d12_surface_cast_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D12Surface(toSurface(self));
	}
	static jlong d3d12_surface_base_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newSurface(toD3D12Surface(self).getSurface());
	}
	static jlong d3d12_surface_get_factory(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Surface(self).getFactory();
	}
	static jlong d3d12_surface_get_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Surface(self).getDevice();
	}
	static jlong d3d12_surface_get_queue(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Surface(self).getQueue();
	}
	static jlong d3d12_surface_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Surface(self).getCommand();
	}
	static void d3d12_surface_set_swap_chain(TS_JNI_ARGS, jlong self, jlong swap_chain) {
		toD3D12Surface(self).setSwapChain((IDXGISwapChain*)swap_chain);
	}
	static jlong d3d12_surface_get_swap_chain(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Surface(self).getSwapChain();
	}
	static void d3d12_surface_set_render_target(TS_JNI_ARGS, jlong self, jlong render_target) {
		toD3D12Surface(self).setRenderTarget((ID3D12Resource*)render_target);
	}
	static void d3d12_surface_set_depth_stencil(TS_JNI_ARGS, jlong self, jlong depth_stencil) {
		toD3D12Surface(self).setDepthStencil((ID3D12Resource*)depth_stencil);
	}
	static jlong d3d12_surface_get_render_target(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Surface(self).getRenderTarget();
	}
	static jlong d3d12_surface_get_depth_stencil(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Surface(self).getDepthStencil();
	}
	static void d3d12_surface_set_render_target_view(TS_JNI_ARGS, jlong self, jlong render_target_view) {
		toD3D12Surface(self).setRenderTargetView((size_t)render_target_view);
	}
	static void d3d12_surface_set_depth_stencil_view(TS_JNI_ARGS, jlong self, jlong depth_stencil_view) {
		toD3D12Surface(self).setDepthStencilView((size_t)depth_stencil_view);
	}
	static jlong d3d12_surface_get_render_target_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Surface(self).getRenderTargetView();
	}
	static jlong d3d12_surface_get_depth_stencil_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D12Surface(self).getDepthStencilView();
	}
	static jint d3d12_surface_get_color_dxgi_format(TS_JNI_ARGS, jlong self) {
		return toD3D12Surface(self).getColorDXGIFormat();
	}
	static jint d3d12_surface_get_depth_dxgi_format(TS_JNI_ARGS, jlong self) {
		return toD3D12Surface(self).getDepthDXGIFormat();
	}
	static const JNINativeMethod d3d12_surface_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d12_surface_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)d3d12_surface_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d12_surface_delete },
		{ (char*)"equal_surface_ptr", (char*)"(JJ)Z", (void*)d3d12_surface_equal_surface_ptr },
		{ (char*)"cast_surface_ptr", (char*)"(J)J", (void*)d3d12_surface_cast_surface_ptr },
		{ (char*)"base_surface_ptr", (char*)"(J)J", (void*)d3d12_surface_base_surface_ptr },
		{ (char*)"get_factory", (char*)"(J)J", (void*)d3d12_surface_get_factory },
		{ (char*)"get_device", (char*)"(J)J", (void*)d3d12_surface_get_device },
		{ (char*)"get_queue", (char*)"(J)J", (void*)d3d12_surface_get_queue },
		{ (char*)"get_command", (char*)"(J)J", (void*)d3d12_surface_get_command },
		{ (char*)"set_swap_chain", (char*)"(JJ)V", (void*)d3d12_surface_set_swap_chain },
		{ (char*)"get_swap_chain", (char*)"(J)J", (void*)d3d12_surface_get_swap_chain },
		{ (char*)"set_render_target", (char*)"(JJ)V", (void*)d3d12_surface_set_render_target },
		{ (char*)"set_depth_stencil", (char*)"(JJ)V", (void*)d3d12_surface_set_depth_stencil },
		{ (char*)"get_render_target", (char*)"(J)J", (void*)d3d12_surface_get_render_target },
		{ (char*)"get_depth_stencil", (char*)"(J)J", (void*)d3d12_surface_get_depth_stencil },
		{ (char*)"set_render_target_view", (char*)"(JJ)V", (void*)d3d12_surface_set_render_target_view },
		{ (char*)"set_depth_stencil_view", (char*)"(JJ)V", (void*)d3d12_surface_set_depth_stencil_view },
		{ (char*)"get_render_target_view", (char*)"(J)J", (void*)d3d12_surface_get_render_target_view },
		{ (char*)"get_depth_stencil_view", (char*)"(J)J", (void*)d3d12_surface_get_depth_stencil_view },
		{ (char*)"get_color_dxgi_format", (char*)"(J)I", (void*)d3d12_surface_get_color_dxgi_format },
		{ (char*)"get_depth_dxgi_format", (char*)"(J)I", (void*)d3d12_surface_get_depth_dxgi_format },
	};
	
	// Tellusim::D3D11Surface
	static jlong d3d11_surface_new(TS_JNI_ARGS) {
		return newD3D11Surface();
	}
	static jlong d3d11_surface_new_1(TS_JNI_ARGS, jlong context) {
		return newD3D11Surface(toD3D11Context(context));
	}
	static void d3d11_surface_delete(TS_JNI_ARGS, jlong self) {
		delete (D3D11Surface*)self;
	}
	static jboolean d3d11_surface_equal_surface_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toD3D11Surface(self).operator==(toSurface(base));
	}
	static jlong d3d11_surface_cast_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newD3D11Surface(toSurface(self));
	}
	static jlong d3d11_surface_base_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newSurface(toD3D11Surface(self).getSurface());
	}
	static jlong d3d11_surface_get_factory(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Surface(self).getFactory();
	}
	static jlong d3d11_surface_get_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Surface(self).getDevice();
	}
	static jlong d3d11_surface_get_context(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Surface(self).getContext();
	}
	static void d3d11_surface_set_swap_chain(TS_JNI_ARGS, jlong self, jlong swap_chain) {
		toD3D11Surface(self).setSwapChain((IDXGISwapChain*)swap_chain);
	}
	static jlong d3d11_surface_get_swap_chain(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Surface(self).getSwapChain();
	}
	static void d3d11_surface_set_render_target(TS_JNI_ARGS, jlong self, jlong render_target) {
		toD3D11Surface(self).setRenderTarget((ID3D11Texture2D*)render_target);
	}
	static void d3d11_surface_set_depth_stencil(TS_JNI_ARGS, jlong self, jlong depth_stencil) {
		toD3D11Surface(self).setDepthStencil((ID3D11Texture2D*)depth_stencil);
	}
	static jlong d3d11_surface_get_render_target(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Surface(self).getRenderTarget();
	}
	static jlong d3d11_surface_get_depth_stencil(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Surface(self).getDepthStencil();
	}
	static void d3d11_surface_set_render_target_view(TS_JNI_ARGS, jlong self, jlong render_target_view) {
		toD3D11Surface(self).setRenderTargetView((ID3D11RenderTargetView*)render_target_view);
	}
	static void d3d11_surface_set_depth_stencil_view(TS_JNI_ARGS, jlong self, jlong depth_stencil_view) {
		toD3D11Surface(self).setDepthStencilView((ID3D11DepthStencilView*)depth_stencil_view);
	}
	static jlong d3d11_surface_get_render_target_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Surface(self).getRenderTargetView();
	}
	static jlong d3d11_surface_get_depth_stencil_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toD3D11Surface(self).getDepthStencilView();
	}
	static jint d3d11_surface_get_color_dxgi_format(TS_JNI_ARGS, jlong self) {
		return toD3D11Surface(self).getColorDXGIFormat();
	}
	static jint d3d11_surface_get_depth_dxgi_format(TS_JNI_ARGS, jlong self) {
		return toD3D11Surface(self).getDepthDXGIFormat();
	}
	static const JNINativeMethod d3d11_surface_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)d3d11_surface_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)d3d11_surface_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)d3d11_surface_delete },
		{ (char*)"equal_surface_ptr", (char*)"(JJ)Z", (void*)d3d11_surface_equal_surface_ptr },
		{ (char*)"cast_surface_ptr", (char*)"(J)J", (void*)d3d11_surface_cast_surface_ptr },
		{ (char*)"base_surface_ptr", (char*)"(J)J", (void*)d3d11_surface_base_surface_ptr },
		{ (char*)"get_factory", (char*)"(J)J", (void*)d3d11_surface_get_factory },
		{ (char*)"get_device", (char*)"(J)J", (void*)d3d11_surface_get_device },
		{ (char*)"get_context", (char*)"(J)J", (void*)d3d11_surface_get_context },
		{ (char*)"set_swap_chain", (char*)"(JJ)V", (void*)d3d11_surface_set_swap_chain },
		{ (char*)"get_swap_chain", (char*)"(J)J", (void*)d3d11_surface_get_swap_chain },
		{ (char*)"set_render_target", (char*)"(JJ)V", (void*)d3d11_surface_set_render_target },
		{ (char*)"set_depth_stencil", (char*)"(JJ)V", (void*)d3d11_surface_set_depth_stencil },
		{ (char*)"get_render_target", (char*)"(J)J", (void*)d3d11_surface_get_render_target },
		{ (char*)"get_depth_stencil", (char*)"(J)J", (void*)d3d11_surface_get_depth_stencil },
		{ (char*)"set_render_target_view", (char*)"(JJ)V", (void*)d3d11_surface_set_render_target_view },
		{ (char*)"set_depth_stencil_view", (char*)"(JJ)V", (void*)d3d11_surface_set_depth_stencil_view },
		{ (char*)"get_render_target_view", (char*)"(J)J", (void*)d3d11_surface_get_render_target_view },
		{ (char*)"get_depth_stencil_view", (char*)"(J)J", (void*)d3d11_surface_get_depth_stencil_view },
		{ (char*)"get_color_dxgi_format", (char*)"(J)I", (void*)d3d11_surface_get_color_dxgi_format },
		{ (char*)"get_depth_dxgi_format", (char*)"(J)I", (void*)d3d11_surface_get_depth_dxgi_format },
	};
	
	// Tellusim::MTLSurface
	static jlong mtl_surface_new(TS_JNI_ARGS) {
		return newMTLSurface();
	}
	static jlong mtl_surface_new_1(TS_JNI_ARGS, jlong context) {
		return newMTLSurface(toMTLContext(context));
	}
	static void mtl_surface_delete(TS_JNI_ARGS, jlong self) {
		delete (MTLSurface*)self;
	}
	static jboolean mtl_surface_equal_surface_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toMTLSurface(self).operator==(toSurface(base));
	}
	static jlong mtl_surface_cast_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newMTLSurface(toSurface(self));
	}
	static jlong mtl_surface_base_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newSurface(toMTLSurface(self).getSurface());
	}
	static jlong mtl_surface_get_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLSurface(self).getDevice();
	}
	static jlong mtl_surface_get_queue(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLSurface(self).getQueue();
	}
	static jlong mtl_surface_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLSurface(self).getCommand();
	}
	static void mtl_surface_set_descriptor(TS_JNI_ARGS, jlong self, jlong descriptor) {
		toMTLSurface(self).setDescriptor((void*)descriptor);
	}
	static jlong mtl_surface_get_descriptor(TS_JNI_ARGS, jlong self) {
		return (jlong)toMTLSurface(self).getDescriptor();
	}
	static jint mtl_surface_get_color_pixel_format(TS_JNI_ARGS, jlong self) {
		return toMTLSurface(self).getColorPixelFormat();
	}
	static jint mtl_surface_get_depth_pixel_format(TS_JNI_ARGS, jlong self) {
		return toMTLSurface(self).getDepthPixelFormat();
	}
	static const JNINativeMethod mtl_surface_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mtl_surface_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)mtl_surface_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)mtl_surface_delete },
		{ (char*)"equal_surface_ptr", (char*)"(JJ)Z", (void*)mtl_surface_equal_surface_ptr },
		{ (char*)"cast_surface_ptr", (char*)"(J)J", (void*)mtl_surface_cast_surface_ptr },
		{ (char*)"base_surface_ptr", (char*)"(J)J", (void*)mtl_surface_base_surface_ptr },
		{ (char*)"get_device", (char*)"(J)J", (void*)mtl_surface_get_device },
		{ (char*)"get_queue", (char*)"(J)J", (void*)mtl_surface_get_queue },
		{ (char*)"get_command", (char*)"(J)J", (void*)mtl_surface_get_command },
		{ (char*)"set_descriptor", (char*)"(JJ)V", (void*)mtl_surface_set_descriptor },
		{ (char*)"get_descriptor", (char*)"(J)J", (void*)mtl_surface_get_descriptor },
		{ (char*)"get_color_pixel_format", (char*)"(J)I", (void*)mtl_surface_get_color_pixel_format },
		{ (char*)"get_depth_pixel_format", (char*)"(J)I", (void*)mtl_surface_get_depth_pixel_format },
	};
	
	// Tellusim::VKSurface
	static jlong vk_surface_new(TS_JNI_ARGS) {
		return newVKSurface();
	}
	static jlong vk_surface_new_1(TS_JNI_ARGS, jlong context) {
		return newVKSurface(toVKContext(context));
	}
	static void vk_surface_delete(TS_JNI_ARGS, jlong self) {
		delete (VKSurface*)self;
	}
	static jboolean vk_surface_equal_surface_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toVKSurface(self).operator==(toSurface(base));
	}
	static jlong vk_surface_cast_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newVKSurface(toSurface(self));
	}
	static jlong vk_surface_base_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newSurface(toVKSurface(self).getSurface());
	}
	static jlong vk_surface_get_instance(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getInstance();
	}
	static jlong vk_surface_get_adapter(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getAdapter();
	}
	static jlong vk_surface_get_device(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getDevice();
	}
	static jlong vk_surface_get_queue(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getQueue();
	}
	static jlong vk_surface_get_command(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getCommand();
	}
	static jint vk_surface_get_family(TS_JNI_ARGS, jlong self) {
		return toVKSurface(self).getFamily();
	}
	static void vk_surface_set_color_image(TS_JNI_ARGS, jlong self, jlong image) {
		toVKSurface(self).setColorImage((VkImage)image);
	}
	static void vk_surface_set_depth_image(TS_JNI_ARGS, jlong self, jlong image) {
		toVKSurface(self).setDepthImage((VkImage)image);
	}
	static jlong vk_surface_get_color_image(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getColorImage();
	}
	static jlong vk_surface_get_depth_image(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getDepthImage();
	}
	static void vk_surface_set_color_image_view(TS_JNI_ARGS, jlong self, jlong image_view) {
		toVKSurface(self).setColorImageView((VkImageView)image_view);
	}
	static void vk_surface_set_depth_image_view(TS_JNI_ARGS, jlong self, jlong image_view) {
		toVKSurface(self).setDepthImageView((VkImageView)image_view);
	}
	static jlong vk_surface_get_color_image_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getColorImageView();
	}
	static jlong vk_surface_get_depth_image_view(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getDepthImageView();
	}
	static void vk_surface_set_render_pass(TS_JNI_ARGS, jlong self, jlong render_pass) {
		toVKSurface(self).setRenderPass((VkRenderPass)render_pass);
	}
	static void vk_surface_set_framebuffer(TS_JNI_ARGS, jlong self, jlong framebuffer) {
		toVKSurface(self).setFramebuffer((VkFramebuffer)framebuffer);
	}
	static jlong vk_surface_get_render_pass(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getRenderPass();
	}
	static jlong vk_surface_get_framebuffer(TS_JNI_ARGS, jlong self) {
		return (jlong)toVKSurface(self).getFramebuffer();
	}
	static jint vk_surface_get_color_pixel_format(TS_JNI_ARGS, jlong self) {
		return toVKSurface(self).getColorPixelFormat();
	}
	static jint vk_surface_get_depth_pixel_format(TS_JNI_ARGS, jlong self) {
		return toVKSurface(self).getDepthPixelFormat();
	}
	static const JNINativeMethod vk_surface_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)vk_surface_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)vk_surface_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)vk_surface_delete },
		{ (char*)"equal_surface_ptr", (char*)"(JJ)Z", (void*)vk_surface_equal_surface_ptr },
		{ (char*)"cast_surface_ptr", (char*)"(J)J", (void*)vk_surface_cast_surface_ptr },
		{ (char*)"base_surface_ptr", (char*)"(J)J", (void*)vk_surface_base_surface_ptr },
		{ (char*)"get_instance", (char*)"(J)J", (void*)vk_surface_get_instance },
		{ (char*)"get_adapter", (char*)"(J)J", (void*)vk_surface_get_adapter },
		{ (char*)"get_device", (char*)"(J)J", (void*)vk_surface_get_device },
		{ (char*)"get_queue", (char*)"(J)J", (void*)vk_surface_get_queue },
		{ (char*)"get_command", (char*)"(J)J", (void*)vk_surface_get_command },
		{ (char*)"get_family", (char*)"(J)I", (void*)vk_surface_get_family },
		{ (char*)"set_color_image", (char*)"(JJ)V", (void*)vk_surface_set_color_image },
		{ (char*)"set_depth_image", (char*)"(JJ)V", (void*)vk_surface_set_depth_image },
		{ (char*)"get_color_image", (char*)"(J)J", (void*)vk_surface_get_color_image },
		{ (char*)"get_depth_image", (char*)"(J)J", (void*)vk_surface_get_depth_image },
		{ (char*)"set_color_image_view", (char*)"(JJ)V", (void*)vk_surface_set_color_image_view },
		{ (char*)"set_depth_image_view", (char*)"(JJ)V", (void*)vk_surface_set_depth_image_view },
		{ (char*)"get_color_image_view", (char*)"(J)J", (void*)vk_surface_get_color_image_view },
		{ (char*)"get_depth_image_view", (char*)"(J)J", (void*)vk_surface_get_depth_image_view },
		{ (char*)"set_render_pass", (char*)"(JJ)V", (void*)vk_surface_set_render_pass },
		{ (char*)"set_framebuffer", (char*)"(JJ)V", (void*)vk_surface_set_framebuffer },
		{ (char*)"get_render_pass", (char*)"(J)J", (void*)vk_surface_get_render_pass },
		{ (char*)"get_framebuffer", (char*)"(J)J", (void*)vk_surface_get_framebuffer },
		{ (char*)"get_color_pixel_format", (char*)"(J)I", (void*)vk_surface_get_color_pixel_format },
		{ (char*)"get_depth_pixel_format", (char*)"(J)I", (void*)vk_surface_get_depth_pixel_format },
	};
	
	// Tellusim::GLSurface
	static jlong gl_surface_new(TS_JNI_ARGS) {
		return newGLSurface();
	}
	static jlong gl_surface_new_1(TS_JNI_ARGS, jlong context) {
		return newGLSurface(toGLContext(context));
	}
	static void gl_surface_delete(TS_JNI_ARGS, jlong self) {
		delete (GLSurface*)self;
	}
	static jboolean gl_surface_equal_surface_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLSurface(self).operator==(toSurface(base));
	}
	static jlong gl_surface_cast_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newGLSurface(toSurface(self));
	}
	static jlong gl_surface_base_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newSurface(toGLSurface(self).getSurface());
	}
	static jlong gl_surface_get_context(TS_JNI_ARGS, jlong self) {
		return (jlong)toGLSurface(self).getContext();
	}
	static void gl_surface_set_color_texture_id(TS_JNI_ARGS, jlong self, jint texture_id) {
		toGLSurface(self).setColorTextureID((uint32_t)texture_id);
	}
	static void gl_surface_set_depth_texture_id(TS_JNI_ARGS, jlong self, jint texture_id) {
		toGLSurface(self).setDepthTextureID((uint32_t)texture_id);
	}
	static jint gl_surface_get_color_texture_id(TS_JNI_ARGS, jlong self) {
		return toGLSurface(self).getColorTextureID();
	}
	static jint gl_surface_get_depth_texture_id(TS_JNI_ARGS, jlong self) {
		return toGLSurface(self).getDepthTextureID();
	}
	static void gl_surface_set_framebuffer_id(TS_JNI_ARGS, jlong self, jint framebuffer_id) {
		toGLSurface(self).setFramebufferID((uint32_t)framebuffer_id);
	}
	static jint gl_surface_get_framebuffer_id(TS_JNI_ARGS, jlong self) {
		return toGLSurface(self).getFramebufferID();
	}
	static jint gl_surface_get_color_internal_format(TS_JNI_ARGS, jlong self) {
		return toGLSurface(self).getColorInternalFormat();
	}
	static jint gl_surface_get_depth_internal_format(TS_JNI_ARGS, jlong self) {
		return toGLSurface(self).getDepthInternalFormat();
	}
	static const JNINativeMethod gl_surface_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gl_surface_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)gl_surface_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)gl_surface_delete },
		{ (char*)"equal_surface_ptr", (char*)"(JJ)Z", (void*)gl_surface_equal_surface_ptr },
		{ (char*)"cast_surface_ptr", (char*)"(J)J", (void*)gl_surface_cast_surface_ptr },
		{ (char*)"base_surface_ptr", (char*)"(J)J", (void*)gl_surface_base_surface_ptr },
		{ (char*)"get_context", (char*)"(J)J", (void*)gl_surface_get_context },
		{ (char*)"set_color_texture_id", (char*)"(JI)V", (void*)gl_surface_set_color_texture_id },
		{ (char*)"set_depth_texture_id", (char*)"(JI)V", (void*)gl_surface_set_depth_texture_id },
		{ (char*)"get_color_texture_id", (char*)"(J)I", (void*)gl_surface_get_color_texture_id },
		{ (char*)"get_depth_texture_id", (char*)"(J)I", (void*)gl_surface_get_depth_texture_id },
		{ (char*)"set_framebuffer_id", (char*)"(JI)V", (void*)gl_surface_set_framebuffer_id },
		{ (char*)"get_framebuffer_id", (char*)"(J)I", (void*)gl_surface_get_framebuffer_id },
		{ (char*)"get_color_internal_format", (char*)"(J)I", (void*)gl_surface_get_color_internal_format },
		{ (char*)"get_depth_internal_format", (char*)"(J)I", (void*)gl_surface_get_depth_internal_format },
	};
	
	// Tellusim::GLESSurface
	static jlong gles_surface_new(TS_JNI_ARGS) {
		return newGLESSurface();
	}
	static jlong gles_surface_new_1(TS_JNI_ARGS, jlong context) {
		return newGLESSurface(toGLESContext(context));
	}
	static void gles_surface_delete(TS_JNI_ARGS, jlong self) {
		delete (GLESSurface*)self;
	}
	static jboolean gles_surface_equal_surface_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toGLESSurface(self).operator==(toSurface(base));
	}
	static jlong gles_surface_cast_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newGLESSurface(toSurface(self));
	}
	static jlong gles_surface_base_surface_ptr(TS_JNI_ARGS, jlong self) {
		return newSurface(toGLESSurface(self).getSurface());
	}
	static jlong gles_surface_get_context(TS_JNI_ARGS, jlong self) {
		return (jlong)toGLESSurface(self).getContext();
	}
	static void gles_surface_set_color_texture_id(TS_JNI_ARGS, jlong self, jint texture_id) {
		toGLESSurface(self).setColorTextureID((uint32_t)texture_id);
	}
	static void gles_surface_set_depth_texture_id(TS_JNI_ARGS, jlong self, jint texture_id) {
		toGLESSurface(self).setDepthTextureID((uint32_t)texture_id);
	}
	static jint gles_surface_get_color_texture_id(TS_JNI_ARGS, jlong self) {
		return toGLESSurface(self).getColorTextureID();
	}
	static jint gles_surface_get_depth_texture_id(TS_JNI_ARGS, jlong self) {
		return toGLESSurface(self).getDepthTextureID();
	}
	static void gles_surface_set_framebuffer_id(TS_JNI_ARGS, jlong self, jint framebuffer_id) {
		toGLESSurface(self).setFramebufferID((uint32_t)framebuffer_id);
	}
	static jint gles_surface_get_framebuffer_id(TS_JNI_ARGS, jlong self) {
		return toGLESSurface(self).getFramebufferID();
	}
	static jint gles_surface_get_color_internal_format(TS_JNI_ARGS, jlong self) {
		return toGLESSurface(self).getColorInternalFormat();
	}
	static jint gles_surface_get_depth_internal_format(TS_JNI_ARGS, jlong self) {
		return toGLESSurface(self).getDepthInternalFormat();
	}
	static const JNINativeMethod gles_surface_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)gles_surface_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)gles_surface_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)gles_surface_delete },
		{ (char*)"equal_surface_ptr", (char*)"(JJ)Z", (void*)gles_surface_equal_surface_ptr },
		{ (char*)"cast_surface_ptr", (char*)"(J)J", (void*)gles_surface_cast_surface_ptr },
		{ (char*)"base_surface_ptr", (char*)"(J)J", (void*)gles_surface_base_surface_ptr },
		{ (char*)"get_context", (char*)"(J)J", (void*)gles_surface_get_context },
		{ (char*)"set_color_texture_id", (char*)"(JI)V", (void*)gles_surface_set_color_texture_id },
		{ (char*)"set_depth_texture_id", (char*)"(JI)V", (void*)gles_surface_set_depth_texture_id },
		{ (char*)"get_color_texture_id", (char*)"(J)I", (void*)gles_surface_get_color_texture_id },
		{ (char*)"get_depth_texture_id", (char*)"(J)I", (void*)gles_surface_get_depth_texture_id },
		{ (char*)"set_framebuffer_id", (char*)"(JI)V", (void*)gles_surface_set_framebuffer_id },
		{ (char*)"get_framebuffer_id", (char*)"(J)I", (void*)gles_surface_get_framebuffer_id },
		{ (char*)"get_color_internal_format", (char*)"(J)I", (void*)gles_surface_get_color_internal_format },
		{ (char*)"get_depth_internal_format", (char*)"(J)I", (void*)gles_surface_get_depth_internal_format },
	};
	
	// Tellusim::Window
	static void window_mouse_pressed_callback_func(Window::Button button, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$MousePressedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(I)V");
			if(!clazz) TS_LOGF(Error, "window_mouse_pressed_callback_func(): can't find \"%s\" class\n", "Window$MousePressedCallback");
			else if(!method_id) TS_LOGF(Error, "window_mouse_pressed_callback_func(): can't get \"%s\" method\n", "(I)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jint)button);
		}
	}
	static Window::MousePressedCallback make_window_mouse_pressed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_mouse_pressed_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return Window::MousePressedCallback();
	}
	static void window_mouse_released_callback_func(Window::Button button, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$MouseReleasedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(I)V");
			if(!clazz) TS_LOGF(Error, "window_mouse_released_callback_func(): can't find \"%s\" class\n", "Window$MouseReleasedCallback");
			else if(!method_id) TS_LOGF(Error, "window_mouse_released_callback_func(): can't get \"%s\" method\n", "(I)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jint)button);
		}
	}
	static Window::MouseReleasedCallback make_window_mouse_released_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_mouse_released_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return Window::MouseReleasedCallback();
	}
	static void window_mouse_changed_callback_func(int32_t x, int32_t y, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$MouseChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(II)V");
			if(!clazz) TS_LOGF(Error, "window_mouse_changed_callback_func(): can't find \"%s\" class\n", "Window$MouseChangedCallback");
			else if(!method_id) TS_LOGF(Error, "window_mouse_changed_callback_func(): can't get \"%s\" method\n", "(II)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jint)x, (jint)y);
		}
	}
	static Window::MouseChangedCallback make_window_mouse_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_mouse_changed_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return Window::MouseChangedCallback();
	}
	static void window_mouse_rotated_callback_func(Window::Axis axis, float32_t delta, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$MouseRotatedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(IF)V");
			if(!clazz) TS_LOGF(Error, "window_mouse_rotated_callback_func(): can't find \"%s\" class\n", "Window$MouseRotatedCallback");
			else if(!method_id) TS_LOGF(Error, "window_mouse_rotated_callback_func(): can't get \"%s\" method\n", "(IF)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jint)axis, (jfloat)delta);
		}
	}
	static Window::MouseRotatedCallback make_window_mouse_rotated_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_mouse_rotated_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return Window::MouseRotatedCallback();
	}
	static void window_touch_changed_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$TouchChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()V");
			if(!clazz) TS_LOGF(Error, "window_touch_changed_callback_func(): can't find \"%s\" class\n", "Window$TouchChangedCallback");
			else if(!method_id) TS_LOGF(Error, "window_touch_changed_callback_func(): can't get \"%s\" method\n", "()V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id);
		}
	}
	static Window::TouchChangedCallback make_window_touch_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_touch_changed_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return Window::TouchChangedCallback();
	}
	static void window_keyboard_pressed_callback_func(uint32_t key, uint32_t code, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$KeyboardPressedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(II)V");
			if(!clazz) TS_LOGF(Error, "window_keyboard_pressed_callback_func(): can't find \"%s\" class\n", "Window$KeyboardPressedCallback");
			else if(!method_id) TS_LOGF(Error, "window_keyboard_pressed_callback_func(): can't get \"%s\" method\n", "(II)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jint)key, (jint)code);
		}
	}
	static Window::KeyboardPressedCallback make_window_keyboard_pressed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_keyboard_pressed_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return Window::KeyboardPressedCallback();
	}
	static void window_keyboard_released_callback_func(uint32_t key, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$KeyboardReleasedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(I)V");
			if(!clazz) TS_LOGF(Error, "window_keyboard_released_callback_func(): can't find \"%s\" class\n", "Window$KeyboardReleasedCallback");
			else if(!method_id) TS_LOGF(Error, "window_keyboard_released_callback_func(): can't get \"%s\" method\n", "(I)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jint)key);
		}
	}
	static Window::KeyboardReleasedCallback make_window_keyboard_released_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_keyboard_released_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return Window::KeyboardReleasedCallback();
	}
	static void window_size_changed_callback_func(uint32_t width, uint32_t height, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$SizeChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(II)V");
			if(!clazz) TS_LOGF(Error, "window_size_changed_callback_func(): can't find \"%s\" class\n", "Window$SizeChangedCallback");
			else if(!method_id) TS_LOGF(Error, "window_size_changed_callback_func(): can't get \"%s\" method\n", "(II)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jint)width, (jint)height);
		}
	}
	static Window::SizeChangedCallback make_window_size_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_size_changed_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return Window::SizeChangedCallback();
	}
	static void window_focus_changed_callback_func(bool changed, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$FocusChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(Z)V");
			if(!clazz) TS_LOGF(Error, "window_focus_changed_callback_func(): can't find \"%s\" class\n", "Window$FocusChangedCallback");
			else if(!method_id) TS_LOGF(Error, "window_focus_changed_callback_func(): can't get \"%s\" method\n", "(Z)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jboolean)changed);
		}
	}
	static Window::FocusChangedCallback make_window_focus_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_focus_changed_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return Window::FocusChangedCallback();
	}
	static void window_close_clicked_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$CloseClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()V");
			if(!clazz) TS_LOGF(Error, "window_close_clicked_callback_func(): can't find \"%s\" class\n", "Window$CloseClickedCallback");
			else if(!method_id) TS_LOGF(Error, "window_close_clicked_callback_func(): can't get \"%s\" method\n", "()V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id);
		}
	}
	static Window::CloseClickedCallback make_window_close_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_close_clicked_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return Window::CloseClickedCallback();
	}
	static void window_pause_changed_callback_func(bool paused, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$PauseChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(Z)V");
			if(!clazz) TS_LOGF(Error, "window_pause_changed_callback_func(): can't find \"%s\" class\n", "Window$PauseChangedCallback");
			else if(!method_id) TS_LOGF(Error, "window_pause_changed_callback_func(): can't get \"%s\" method\n", "(Z)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jboolean)paused);
		}
	}
	static Window::PauseChangedCallback make_window_pause_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_pause_changed_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return Window::PauseChangedCallback();
	}
	static void window_file_dropped_callback_func(const char *name, uint32_t remain, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$FileDroppedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(Ljava/lang/String;I)V");
			if(!clazz) TS_LOGF(Error, "window_file_dropped_callback_func(): can't find \"%s\" class\n", "Window$FileDroppedCallback");
			else if(!method_id) TS_LOGF(Error, "window_file_dropped_callback_func(): can't get \"%s\" method\n", "(Ljava/lang/String;I)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jstring)name, (jint)remain);
		}
	}
	static Window::FileDroppedCallback make_window_file_dropped_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_file_dropped_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return Window::FileDroppedCallback();
	}
	static void window_update_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$UpdateCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()V");
			if(!clazz) TS_LOGF(Error, "window_update_callback_func(): can't find \"%s\" class\n", "Window$UpdateCallback");
			else if(!method_id) TS_LOGF(Error, "window_update_callback_func(): can't get \"%s\" method\n", "()V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id);
		}
	}
	static Window::UpdateCallback make_window_update_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_update_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return Window::UpdateCallback();
	}
	static void window_present_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$PresentCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()V");
			if(!clazz) TS_LOGF(Error, "window_present_callback_func(): can't find \"%s\" class\n", "Window$PresentCallback");
			else if(!method_id) TS_LOGF(Error, "window_present_callback_func(): can't get \"%s\" method\n", "()V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id);
		}
	}
	static Window::PresentCallback make_window_present_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_present_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return Window::PresentCallback();
	}
	static bool window_main_loop_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Window$MainLoopCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()Z");
			if(!clazz) TS_LOGF(Error, "window_main_loop_callback_func(): can't find \"%s\" class\n", "Window$MainLoopCallback");
			else if(!method_id) TS_LOGF(Error, "window_main_loop_callback_func(): can't get \"%s\" method\n", "()Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id) != 0);
		}
		return false;
	}
	static Window::MainLoopCallback make_window_main_loop_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(window_main_loop_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return Window::MainLoopCallback();
	}
	
	static jlong window_new(TS_JNI_ARGS) {
		return newWindow();
	}
	static jlong window_new_1(TS_JNI_ARGS, jint platform, jint index) {
		return newWindow((Platform)platform, (uint32_t)index);
	}
	static jlong window_new_2(TS_JNI_ARGS, jlong surface) {
		return newWindow(toSurface(surface));
	}
	static void window_delete(TS_JNI_ARGS, jlong self) {
		delete (Window*)self;
	}
	static jboolean window_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toWindow(self) == toWindow(ptr));
	}
	static jlong window_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newWindow(toWindow(self).clonePtr());
	}
	static void window_clear_ptr(TS_JNI_ARGS, jlong self) {
		toWindow(self).clearPtr();
	}
	static void window_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toWindow(self).destroyPtr();
	}
	static void window_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toWindow(self).acquirePtr();
	}
	static void window_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toWindow(self).unacquirePtr();
	}
	static jboolean window_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isValidPtr();
	}
	static jboolean window_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isOwnerPtr();
	}
	static jboolean window_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isConstPtr();
	}
	static jint window_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getCountPtr();
	}
	static jlong window_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toWindow(self).getInternalPtr();
	}
	static jint window_get_num_windows(TS_JNI_ARGS) {
		return Window::getNumWindows();
	}
	static jlong window_get_window(TS_JNI_ARGS, jint index) {
		return newWindow(Window::getWindow((uint32_t)index));
	}
	static void window_update(TS_JNI_ARGS, jboolean wait) {
		Window::update((bool)wait);
	}
	static jint window_get_platform(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getPlatform();
	}
	static jstring window_get_platform_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toWindow(self).getPlatformName());
	}
	static jint window_get_index(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getIndex();
	}
	static void window_set_surface(TS_JNI_ARGS, jlong self, jlong surface) {
		toWindow(self).setSurface(toSurface(surface));
	}
	static jlong window_get_surface(TS_JNI_ARGS, jlong self) {
		return newSurface(toWindow(self).getSurface());
	}
	static jlong window_get_handle(TS_JNI_ARGS, jlong self) {
		return (jlong)toWindow(self).getHandle();
	}
	static jboolean window_is_created(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isCreated();
	}
	static jboolean window_create(TS_JNI_ARGS, jlong self, jstring title, jint flags) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		bool ret_ = toWindow(self).create(title_, (Window::Flags)flags);
		env->ReleaseStringUTFChars(title, title_);
		return ret_;
	}
	static jboolean window_create_1(TS_JNI_ARGS, jlong self, jlong title, jint flags) {
		return toWindow(self).create(toString(title), (Window::Flags)flags);
	}
	static jboolean window_create_2(TS_JNI_ARGS, jlong self, jint flags) {
		return toWindow(self).create((Window::Flags)flags);
	}
	static void window_release(TS_JNI_ARGS, jlong self) {
		toWindow(self).release();
	}
	static jboolean window_clear(TS_JNI_ARGS, jlong self, jlong color) {
		return toWindow(self).clear(toColor(color));
	}
	static jboolean window_grab(TS_JNI_ARGS, jlong self, jlong image) {
		return toWindow(self).grab(toImage(image));
	}
	static jboolean window_render(TS_JNI_ARGS, jlong self) {
		return toWindow(self).render();
	}
	static jboolean window_present(TS_JNI_ARGS, jlong self) {
		return toWindow(self).present();
	}
	static jboolean window_finish(TS_JNI_ARGS, jlong self) {
		return toWindow(self).finish();
	}
	static jint window_get_color_format(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getColorFormat();
	}
	static jint window_get_depth_format(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getDepthFormat();
	}
	static jint window_get_multisample(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getMultisample();
	}
	static jboolean window_has_multisample(TS_JNI_ARGS, jlong self) {
		return toWindow(self).hasMultisample();
	}
	static void window_set_flags(TS_JNI_ARGS, jlong self, jint flags) {
		toWindow(self).setFlags((Window::Flags)flags);
	}
	static jint window_get_flags(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getFlags();
	}
	static jboolean window_has_flag(TS_JNI_ARGS, jlong self, jint flags) {
		return toWindow(self).hasFlag((Window::Flags)flags);
	}
	static jboolean window_has_flags(TS_JNI_ARGS, jlong self, jint flags) {
		return toWindow(self).hasFlags((Window::Flags)flags);
	}
	static void window_set_refresh_rate(TS_JNI_ARGS, jlong self, jint rate) {
		toWindow(self).setRefreshRate((uint32_t)rate);
	}
	static jint window_get_refresh_rate(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getRefreshRate();
	}
	static jboolean window_set_hidden(TS_JNI_ARGS, jlong self, jboolean hidden) {
		return toWindow(self).setHidden((bool)hidden);
	}
	static jboolean window_is_hidden(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isHidden();
	}
	static jboolean window_set_focused(TS_JNI_ARGS, jlong self, jboolean focused) {
		return toWindow(self).setFocused((bool)focused);
	}
	static jboolean window_is_focused(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isFocused();
	}
	static jboolean window_set_minimized(TS_JNI_ARGS, jlong self, jboolean minimized) {
		return toWindow(self).setMinimized((bool)minimized);
	}
	static jboolean window_is_minimized(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isMinimized();
	}
	static jboolean window_set_fullscreen(TS_JNI_ARGS, jlong self, jboolean fullscreen) {
		return toWindow(self).setFullscreen((bool)fullscreen);
	}
	static jboolean window_is_fullscreen(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isFullscreen();
	}
	static jboolean window_is_occluded(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isOccluded();
	}
	static jboolean window_set_title(TS_JNI_ARGS, jlong self, jstring title) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		bool ret_ = toWindow(self).setTitle(title_);
		env->ReleaseStringUTFChars(title, title_);
		return ret_;
	}
	static jboolean window_set_title_1(TS_JNI_ARGS, jlong self, jlong title) {
		return toWindow(self).setTitle(toString(title));
	}
	static jstring window_get_title(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toWindow(self).getTitle().get());
	}
	static jboolean window_set_icon(TS_JNI_ARGS, jlong self, jlong image) {
		return toWindow(self).setIcon(toImage(image));
	}
	static jlong window_get_icon(TS_JNI_ARGS, jlong self) {
		return newImage(toWindow(self).getIcon());
	}
	static jboolean window_set_geometry(TS_JNI_ARGS, jlong self, jint x, jint y, jint width, jint height, jboolean force) {
		return toWindow(self).setGeometry(x, y, (uint32_t)width, (uint32_t)height, (bool)force);
	}
	static jboolean window_set_position(TS_JNI_ARGS, jlong self, jint x, jint y, jboolean force) {
		return toWindow(self).setPosition(x, y, (bool)force);
	}
	static jint window_get_position_x(TS_JNI_ARGS, jlong self, jboolean title) {
		return toWindow(self).getPositionX((bool)title);
	}
	static jint window_get_position_y(TS_JNI_ARGS, jlong self, jboolean title) {
		return toWindow(self).getPositionY((bool)title);
	}
	static jboolean window_set_size(TS_JNI_ARGS, jlong self, jint width, jint height, jboolean force) {
		return toWindow(self).setSize((uint32_t)width, (uint32_t)height, (bool)force);
	}
	static jint window_get_width(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getWidth();
	}
	static jint window_get_height(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getHeight();
	}
	static jfloat window_get_scale(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getScale();
	}
	static jint window_get_dpi_x(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getDpiX();
	}
	static jint window_get_dpi_y(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getDpiY();
	}
	static jboolean window_set_mouse(TS_JNI_ARGS, jlong self, jint x, jint y, jboolean force) {
		return toWindow(self).setMouse(x, y, (bool)force);
	}
	static jint window_get_mouse_x(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getMouseX();
	}
	static jint window_get_mouse_y(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getMouseY();
	}
	static jboolean window_set_mouse_delta(TS_JNI_ARGS, jlong self, jint dx, jint dy) {
		return toWindow(self).setMouseDelta(dx, dy);
	}
	static jint window_get_mouse_dx(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getMouseDX();
	}
	static jint window_get_mouse_dy(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getMouseDY();
	}
	static jboolean window_set_mouse_hidden(TS_JNI_ARGS, jlong self, jboolean hidden, jboolean force) {
		return toWindow(self).setMouseHidden((bool)hidden, (bool)force);
	}
	static jboolean window_is_mouse_hidden(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isMouseHidden();
	}
	static jboolean window_set_mouse_clipped(TS_JNI_ARGS, jlong self, jboolean clipped, jboolean force) {
		return toWindow(self).setMouseClipped((bool)clipped, (bool)force);
	}
	static jboolean window_is_mouse_clipped(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isMouseClipped();
	}
	static jboolean window_is_mouse_inside(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isMouseInside();
	}
	static jboolean window_set_mouse_cursor(TS_JNI_ARGS, jlong self, jint cursor, jboolean force) {
		return toWindow(self).setMouseCursor((Window::Cursor)cursor, (bool)force);
	}
	static jint window_get_mouse_cursor(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getMouseCursor();
	}
	static jboolean window_set_mouse_buttons(TS_JNI_ARGS, jlong self, jint buttons) {
		return toWindow(self).setMouseButtons((Window::Button)buttons);
	}
	static jint window_get_mouse_buttons(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getMouseButtons();
	}
	static jboolean window_set_mouse_button(TS_JNI_ARGS, jlong self, jint button, jboolean value) {
		return toWindow(self).setMouseButton((Window::Button)button, (bool)value);
	}
	static jboolean window_get_mouse_button(TS_JNI_ARGS, jlong self, jint button, jboolean clear) {
		return toWindow(self).getMouseButton((Window::Button)button, (bool)clear);
	}
	static void window_release_mouse_buttons(TS_JNI_ARGS, jlong self, jint buttons) {
		toWindow(self).releaseMouseButtons((Window::Button)buttons);
	}
	static jint window_clear_mouse_buttons(TS_JNI_ARGS, jlong self) {
		return toWindow(self).clearMouseButtons();
	}
	static jboolean window_set_mouse_axis(TS_JNI_ARGS, jlong self, jint axis, jfloat value) {
		return toWindow(self).setMouseAxis((Window::Axis)axis, value);
	}
	static jfloat window_get_mouse_axis(TS_JNI_ARGS, jlong self, jint axis) {
		return toWindow(self).getMouseAxis((Window::Axis)axis);
	}
	static jfloat window_clear_mouse_axis(TS_JNI_ARGS, jlong self, jint axis) {
		return toWindow(self).clearMouseAxis((Window::Axis)axis);
	}
	static void window_set_mouse_pressed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setMousePressedCallback(make_window_mouse_pressed_callback(env, func));
	}
	static void window_set_mouse_released_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setMouseReleasedCallback(make_window_mouse_released_callback(env, func));
	}
	static void window_set_mouse_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setMouseChangedCallback(make_window_mouse_changed_callback(env, func));
	}
	static void window_set_mouse_rotated_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setMouseRotatedCallback(make_window_mouse_rotated_callback(env, func));
	}
	static jint window_get_num_touches(TS_JNI_ARGS, jlong self) {
		return toWindow(self).getNumTouches();
	}
	static jint window_add_touch(TS_JNI_ARGS, jlong self, jint x, jint y) {
		return toWindow(self).addTouch(x, y);
	}
	static jint window_get_touch_x(TS_JNI_ARGS, jlong self, jint touch) {
		return toWindow(self).getTouchX((uint32_t)touch);
	}
	static jint window_get_touch_y(TS_JNI_ARGS, jlong self, jint touch) {
		return toWindow(self).getTouchY((uint32_t)touch);
	}
	static jint window_find_touch(TS_JNI_ARGS, jlong self, jint x, jint y) {
		return toWindow(self).findTouch(x, y);
	}
	static void window_clear_touches(TS_JNI_ARGS, jlong self) {
		toWindow(self).clearTouches();
	}
	static void window_set_touch_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setTouchChangedCallback(make_window_touch_changed_callback(env, func));
	}
	static void window_set_keyboard_key(TS_JNI_ARGS, jlong self, jint key, jboolean value) {
		toWindow(self).setKeyboardKey((uint32_t)key, (bool)value);
	}
	static jboolean window_get_keyboard_key(TS_JNI_ARGS, jlong self, jint key, jboolean clear) {
		return toWindow(self).getKeyboardKey((uint32_t)key, (bool)clear);
	}
	static void window_set_keyboard_pressed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setKeyboardPressedCallback(make_window_keyboard_pressed_callback(env, func));
	}
	static void window_set_keyboard_released_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setKeyboardReleasedCallback(make_window_keyboard_released_callback(env, func));
	}
	static void window_set_size_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setSizeChangedCallback(make_window_size_changed_callback(env, func));
	}
	static void window_set_focus_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setFocusChangedCallback(make_window_focus_changed_callback(env, func));
	}
	static void window_set_close_clicked_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setCloseClickedCallback(make_window_close_clicked_callback(env, func));
	}
	static void window_set_pause_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setPauseChangedCallback(make_window_pause_changed_callback(env, func));
	}
	static void window_set_file_dropped_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setFileDroppedCallback(make_window_file_dropped_callback(env, func));
	}
	static void window_set_update_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setUpdateCallback(make_window_update_callback(env, func));
	}
	static void window_set_present_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toWindow(self).setPresentCallback(make_window_present_callback(env, func));
	}
	static jboolean window_run(TS_JNI_ARGS, jlong self, jobject func) {
		return toWindow(self).run(make_window_main_loop_callback(env, func));
	}
	static jboolean window_is_running(TS_JNI_ARGS, jlong self) {
		return toWindow(self).isRunning();
	}
	static void window_stop(TS_JNI_ARGS, jlong self) {
		toWindow(self).stop();
	}
	static jboolean window_set_copy_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		bool ret_ = toWindow(self).setCopyText(text_);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jboolean window_set_copy_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		return toWindow(self).setCopyText(toString(text));
	}
	static jstring window_get_paste_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toWindow(self).getPasteText().get());
	}
	static const JNINativeMethod window_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)window_new },
		{ (char*)"new_1", (char*)"(II)J", (void*)window_new_1 },
		{ (char*)"new_2", (char*)"(J)J", (void*)window_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)window_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)window_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)window_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)window_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)window_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)window_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)window_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)window_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)window_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)window_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)window_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)window_get_internal_ptr },
		{ (char*)"get_num_windows", (char*)"()I", (void*)window_get_num_windows },
		{ (char*)"get_window", (char*)"(I)J", (void*)window_get_window },
		{ (char*)"update_", (char*)"(Z)V", (void*)window_update },
		{ (char*)"get_platform", (char*)"(J)I", (void*)window_get_platform },
		{ (char*)"get_platform_name", (char*)"(J)Ljava/lang/String;", (void*)window_get_platform_name },
		{ (char*)"get_index", (char*)"(J)I", (void*)window_get_index },
		{ (char*)"set_surface", (char*)"(JJ)V", (void*)window_set_surface },
		{ (char*)"get_surface", (char*)"(J)J", (void*)window_get_surface },
		{ (char*)"get_handle", (char*)"(J)J", (void*)window_get_handle },
		{ (char*)"is_created", (char*)"(J)Z", (void*)window_is_created },
		{ (char*)"create_", (char*)"(JLjava/lang/String;I)Z", (void*)window_create },
		{ (char*)"create_1", (char*)"(JJI)Z", (void*)window_create_1 },
		{ (char*)"create_2", (char*)"(JI)Z", (void*)window_create_2 },
		{ (char*)"release_", (char*)"(J)V", (void*)window_release },
		{ (char*)"clear_", (char*)"(JJ)Z", (void*)window_clear },
		{ (char*)"grab_", (char*)"(JJ)Z", (void*)window_grab },
		{ (char*)"render_", (char*)"(J)Z", (void*)window_render },
		{ (char*)"present_", (char*)"(J)Z", (void*)window_present },
		{ (char*)"finish_", (char*)"(J)Z", (void*)window_finish },
		{ (char*)"get_color_format", (char*)"(J)I", (void*)window_get_color_format },
		{ (char*)"get_depth_format", (char*)"(J)I", (void*)window_get_depth_format },
		{ (char*)"get_multisample", (char*)"(J)I", (void*)window_get_multisample },
		{ (char*)"has_multisample", (char*)"(J)Z", (void*)window_has_multisample },
		{ (char*)"set_flags", (char*)"(JI)V", (void*)window_set_flags },
		{ (char*)"get_flags", (char*)"(J)I", (void*)window_get_flags },
		{ (char*)"has_flag", (char*)"(JI)Z", (void*)window_has_flag },
		{ (char*)"has_flags", (char*)"(JI)Z", (void*)window_has_flags },
		{ (char*)"set_refresh_rate", (char*)"(JI)V", (void*)window_set_refresh_rate },
		{ (char*)"get_refresh_rate", (char*)"(J)I", (void*)window_get_refresh_rate },
		{ (char*)"set_hidden", (char*)"(JZ)Z", (void*)window_set_hidden },
		{ (char*)"is_hidden", (char*)"(J)Z", (void*)window_is_hidden },
		{ (char*)"set_focused", (char*)"(JZ)Z", (void*)window_set_focused },
		{ (char*)"is_focused", (char*)"(J)Z", (void*)window_is_focused },
		{ (char*)"set_minimized", (char*)"(JZ)Z", (void*)window_set_minimized },
		{ (char*)"is_minimized", (char*)"(J)Z", (void*)window_is_minimized },
		{ (char*)"set_fullscreen", (char*)"(JZ)Z", (void*)window_set_fullscreen },
		{ (char*)"is_fullscreen", (char*)"(J)Z", (void*)window_is_fullscreen },
		{ (char*)"is_occluded", (char*)"(J)Z", (void*)window_is_occluded },
		{ (char*)"set_title", (char*)"(JLjava/lang/String;)Z", (void*)window_set_title },
		{ (char*)"set_title_1", (char*)"(JJ)Z", (void*)window_set_title_1 },
		{ (char*)"get_title", (char*)"(J)Ljava/lang/String;", (void*)window_get_title },
		{ (char*)"set_icon", (char*)"(JJ)Z", (void*)window_set_icon },
		{ (char*)"get_icon", (char*)"(J)J", (void*)window_get_icon },
		{ (char*)"set_geometry", (char*)"(JIIIIZ)Z", (void*)window_set_geometry },
		{ (char*)"set_position", (char*)"(JIIZ)Z", (void*)window_set_position },
		{ (char*)"get_position_x", (char*)"(JZ)I", (void*)window_get_position_x },
		{ (char*)"get_position_y", (char*)"(JZ)I", (void*)window_get_position_y },
		{ (char*)"set_size", (char*)"(JIIZ)Z", (void*)window_set_size },
		{ (char*)"get_width", (char*)"(J)I", (void*)window_get_width },
		{ (char*)"get_height", (char*)"(J)I", (void*)window_get_height },
		{ (char*)"get_scale", (char*)"(J)F", (void*)window_get_scale },
		{ (char*)"get_dpi_x", (char*)"(J)I", (void*)window_get_dpi_x },
		{ (char*)"get_dpi_y", (char*)"(J)I", (void*)window_get_dpi_y },
		{ (char*)"set_mouse", (char*)"(JIIZ)Z", (void*)window_set_mouse },
		{ (char*)"get_mouse_x", (char*)"(J)I", (void*)window_get_mouse_x },
		{ (char*)"get_mouse_y", (char*)"(J)I", (void*)window_get_mouse_y },
		{ (char*)"set_mouse_delta", (char*)"(JII)Z", (void*)window_set_mouse_delta },
		{ (char*)"get_mouse_dx", (char*)"(J)I", (void*)window_get_mouse_dx },
		{ (char*)"get_mouse_dy", (char*)"(J)I", (void*)window_get_mouse_dy },
		{ (char*)"set_mouse_hidden", (char*)"(JZZ)Z", (void*)window_set_mouse_hidden },
		{ (char*)"is_mouse_hidden", (char*)"(J)Z", (void*)window_is_mouse_hidden },
		{ (char*)"set_mouse_clipped", (char*)"(JZZ)Z", (void*)window_set_mouse_clipped },
		{ (char*)"is_mouse_clipped", (char*)"(J)Z", (void*)window_is_mouse_clipped },
		{ (char*)"is_mouse_inside", (char*)"(J)Z", (void*)window_is_mouse_inside },
		{ (char*)"set_mouse_cursor", (char*)"(JIZ)Z", (void*)window_set_mouse_cursor },
		{ (char*)"get_mouse_cursor", (char*)"(J)I", (void*)window_get_mouse_cursor },
		{ (char*)"set_mouse_buttons", (char*)"(JI)Z", (void*)window_set_mouse_buttons },
		{ (char*)"get_mouse_buttons", (char*)"(J)I", (void*)window_get_mouse_buttons },
		{ (char*)"set_mouse_button", (char*)"(JIZ)Z", (void*)window_set_mouse_button },
		{ (char*)"get_mouse_button", (char*)"(JIZ)Z", (void*)window_get_mouse_button },
		{ (char*)"release_mouse_buttons", (char*)"(JI)V", (void*)window_release_mouse_buttons },
		{ (char*)"clear_mouse_buttons", (char*)"(J)I", (void*)window_clear_mouse_buttons },
		{ (char*)"set_mouse_axis", (char*)"(JIF)Z", (void*)window_set_mouse_axis },
		{ (char*)"get_mouse_axis", (char*)"(JI)F", (void*)window_get_mouse_axis },
		{ (char*)"clear_mouse_axis", (char*)"(JI)F", (void*)window_clear_mouse_axis },
		{ (char*)"set_mouse_pressed_callback", (char*)"(JL" TS_JNI_PREFIX "Window$MousePressedCallback;)V", (void*)window_set_mouse_pressed_callback },
		{ (char*)"set_mouse_released_callback", (char*)"(JL" TS_JNI_PREFIX "Window$MouseReleasedCallback;)V", (void*)window_set_mouse_released_callback },
		{ (char*)"set_mouse_changed_callback", (char*)"(JL" TS_JNI_PREFIX "Window$MouseChangedCallback;)V", (void*)window_set_mouse_changed_callback },
		{ (char*)"set_mouse_rotated_callback", (char*)"(JL" TS_JNI_PREFIX "Window$MouseRotatedCallback;)V", (void*)window_set_mouse_rotated_callback },
		{ (char*)"get_num_touches", (char*)"(J)I", (void*)window_get_num_touches },
		{ (char*)"add_touch", (char*)"(JII)I", (void*)window_add_touch },
		{ (char*)"get_touch_x", (char*)"(JI)I", (void*)window_get_touch_x },
		{ (char*)"get_touch_y", (char*)"(JI)I", (void*)window_get_touch_y },
		{ (char*)"find_touch", (char*)"(JII)I", (void*)window_find_touch },
		{ (char*)"clear_touches", (char*)"(J)V", (void*)window_clear_touches },
		{ (char*)"set_touch_changed_callback", (char*)"(JL" TS_JNI_PREFIX "Window$TouchChangedCallback;)V", (void*)window_set_touch_changed_callback },
		{ (char*)"set_keyboard_key", (char*)"(JIZ)V", (void*)window_set_keyboard_key },
		{ (char*)"get_keyboard_key", (char*)"(JIZ)Z", (void*)window_get_keyboard_key },
		{ (char*)"set_keyboard_pressed_callback", (char*)"(JL" TS_JNI_PREFIX "Window$KeyboardPressedCallback;)V", (void*)window_set_keyboard_pressed_callback },
		{ (char*)"set_keyboard_released_callback", (char*)"(JL" TS_JNI_PREFIX "Window$KeyboardReleasedCallback;)V", (void*)window_set_keyboard_released_callback },
		{ (char*)"set_size_changed_callback", (char*)"(JL" TS_JNI_PREFIX "Window$SizeChangedCallback;)V", (void*)window_set_size_changed_callback },
		{ (char*)"set_focus_changed_callback", (char*)"(JL" TS_JNI_PREFIX "Window$FocusChangedCallback;)V", (void*)window_set_focus_changed_callback },
		{ (char*)"set_close_clicked_callback", (char*)"(JL" TS_JNI_PREFIX "Window$CloseClickedCallback;)V", (void*)window_set_close_clicked_callback },
		{ (char*)"set_pause_changed_callback", (char*)"(JL" TS_JNI_PREFIX "Window$PauseChangedCallback;)V", (void*)window_set_pause_changed_callback },
		{ (char*)"set_file_dropped_callback", (char*)"(JL" TS_JNI_PREFIX "Window$FileDroppedCallback;)V", (void*)window_set_file_dropped_callback },
		{ (char*)"set_update_callback", (char*)"(JL" TS_JNI_PREFIX "Window$UpdateCallback;)V", (void*)window_set_update_callback },
		{ (char*)"set_present_callback", (char*)"(JL" TS_JNI_PREFIX "Window$PresentCallback;)V", (void*)window_set_present_callback },
		{ (char*)"run_", (char*)"(JL" TS_JNI_PREFIX "Window$MainLoopCallback;)Z", (void*)window_run },
		{ (char*)"is_running", (char*)"(J)Z", (void*)window_is_running },
		{ (char*)"stop_", (char*)"(J)V", (void*)window_stop },
		{ (char*)"set_copy_text", (char*)"(JLjava/lang/String;)Z", (void*)window_set_copy_text },
		{ (char*)"set_copy_text_1", (char*)"(JJ)Z", (void*)window_set_copy_text_1 },
		{ (char*)"get_paste_text", (char*)"(J)Ljava/lang/String;", (void*)window_get_paste_text },
	};
	
	// Tellusim::Font
	static jlong font_new(TS_JNI_ARGS) {
		return newFont();
	}
	static void font_delete(TS_JNI_ARGS, jlong self) {
		delete (Font*)self;
	}
	static jboolean font_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toFont(self) == toFont(ptr));
	}
	static jlong font_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newFont(toFont(self).clonePtr());
	}
	static void font_clear_ptr(TS_JNI_ARGS, jlong self) {
		toFont(self).clearPtr();
	}
	static void font_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toFont(self).destroyPtr();
	}
	static void font_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toFont(self).acquirePtr();
	}
	static void font_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toFont(self).unacquirePtr();
	}
	static jboolean font_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toFont(self).isValidPtr();
	}
	static jboolean font_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toFont(self).isOwnerPtr();
	}
	static jboolean font_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toFont(self).isConstPtr();
	}
	static jint font_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toFont(self).getCountPtr();
	}
	static jlong font_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toFont(self).getInternalPtr();
	}
	static void font_clear(TS_JNI_ARGS, jlong self) {
		toFont(self).clear();
	}
	static jboolean font_is_loaded(TS_JNI_ARGS, jlong self) {
		return toFont(self).isLoaded();
	}
	static jboolean font_load(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toFont(self).load(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean font_load_1(TS_JNI_ARGS, jlong self, jlong stream) {
		return toFont(self).load(toStream(stream));
	}
	static jfloat font_get_advance(TS_JNI_ARGS, jlong self, jlong style, jint code) {
		return toFont(self).getAdvance(toFontStyle(style), (uint32_t)code);
	}
	static jlong font_get_rect(TS_JNI_ARGS, jlong self, jlong position, jlong style, jstring str) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		Rect ret_ = toFont(self).getRect(toVector3f(position), toFontStyle(style), str_);
		env->ReleaseStringUTFChars(str, str_);
		return newRect(ret_);
	}
	static jlong font_get_rect_1(TS_JNI_ARGS, jlong self, jlong position, jlong style, jintArray str) {
		return newRect(toFont(self).getRect(toVector3f(position), toFontStyle(style), (uint32_t*)IntArray(env, str).get()));
	}
	static void font_create(TS_JNI_ARGS, jlong self, jlong device, jlong style, jstring str) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		toFont(self).create(toDevice(device), toFontStyle(style), str_);
		env->ReleaseStringUTFChars(str, str_);
	}
	static void font_create_1(TS_JNI_ARGS, jlong self, jlong device, jlong style, jintArray str) {
		toFont(self).create(toDevice(device), toFontStyle(style), (uint32_t*)IntArray(env, str).get());
	}
	static void font_draw(TS_JNI_ARGS, jlong self, jlong command, jlong position, jlong style, jstring str) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		toFont(self).draw(toCommand(command), toVector3f(position), toFontStyle(style), str_);
		env->ReleaseStringUTFChars(str, str_);
	}
	static void font_draw_1(TS_JNI_ARGS, jlong self, jlong command, jlong position, jlong style, jintArray str) {
		toFont(self).draw(toCommand(command), toVector3f(position), toFontStyle(style), (uint32_t*)IntArray(env, str).get());
	}
	static jboolean font_flush(TS_JNI_ARGS, jlong self, jlong device) {
		return toFont(self).flush(toDevice(device));
	}
	static const JNINativeMethod font_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)font_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)font_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)font_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)font_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)font_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)font_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)font_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)font_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)font_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)font_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)font_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)font_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)font_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)font_clear },
		{ (char*)"is_loaded", (char*)"(J)Z", (void*)font_is_loaded },
		{ (char*)"load_", (char*)"(JLjava/lang/String;)Z", (void*)font_load },
		{ (char*)"load_1", (char*)"(JJ)Z", (void*)font_load_1 },
		{ (char*)"get_advance", (char*)"(JJI)F", (void*)font_get_advance },
		{ (char*)"get_rect", (char*)"(JJJLjava/lang/String;)J", (void*)font_get_rect },
		{ (char*)"get_rect_1", (char*)"(JJJ[I)J", (void*)font_get_rect_1 },
		{ (char*)"create_", (char*)"(JJJLjava/lang/String;)V", (void*)font_create },
		{ (char*)"create_1", (char*)"(JJJ[I)V", (void*)font_create_1 },
		{ (char*)"draw_", (char*)"(JJJJLjava/lang/String;)V", (void*)font_draw },
		{ (char*)"draw_1", (char*)"(JJJJ[I)V", (void*)font_draw_1 },
		{ (char*)"flush_", (char*)"(JJ)Z", (void*)font_flush },
	};
	
	// Tellusim::CanvasElement
	static bool canvas_element_draw_callback_func(Command command, CanvasElement element, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "CanvasElement$DrawCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JJ)Z");
			if(!clazz) TS_LOGF(Error, "canvas_element_draw_callback_func(): can't find \"%s\" class\n", "CanvasElement$DrawCallback");
			else if(!method_id) TS_LOGF(Error, "canvas_element_draw_callback_func(): can't get \"%s\" method\n", "(JJ)Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id, newCommand(command), newCanvasElement(element)) != 0);
		}
		return false;
	}
	static CanvasElement::DrawCallback make_canvas_element_draw_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(canvas_element_draw_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return CanvasElement::DrawCallback();
	}
	
	static jlong canvas_element_new(TS_JNI_ARGS) {
		return newCanvasElement();
	}
	static void canvas_element_delete(TS_JNI_ARGS, jlong self) {
		delete (CanvasElement*)self;
	}
	static jboolean canvas_element_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toCanvasElement(self) == toCanvasElement(ptr));
	}
	static jlong canvas_element_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasElement(toCanvasElement(self).clonePtr());
	}
	static void canvas_element_clear_ptr(TS_JNI_ARGS, jlong self) {
		toCanvasElement(self).clearPtr();
	}
	static void canvas_element_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toCanvasElement(self).destroyPtr();
	}
	static void canvas_element_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toCanvasElement(self).acquirePtr();
	}
	static void canvas_element_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toCanvasElement(self).unacquirePtr();
	}
	static jboolean canvas_element_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isValidPtr();
	}
	static jboolean canvas_element_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isOwnerPtr();
	}
	static jboolean canvas_element_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isConstPtr();
	}
	static jint canvas_element_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getCountPtr();
	}
	static jlong canvas_element_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toCanvasElement(self).getInternalPtr();
	}
	static jint canvas_element_get_type(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getType();
	}
	static jstring canvas_element_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(CanvasElement::getTypeName((CanvasElement::Type)type));
	}
	static jstring canvas_element_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toCanvasElement(self).getTypeName());
	}
	static jboolean canvas_element_is_text(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isText();
	}
	static jboolean canvas_element_is_mesh(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isMesh();
	}
	static jboolean canvas_element_is_rect(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isRect();
	}
	static jboolean canvas_element_is_triangle(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isTriangle();
	}
	static jboolean canvas_element_is_ellipse(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isEllipse();
	}
	static jboolean canvas_element_is_shape(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isShape();
	}
	static jboolean canvas_element_is_strip(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isStrip();
	}
	static void canvas_element_set_canvas(TS_JNI_ARGS, jlong self, jlong canvas) {
		toCanvasElement(self).setCanvas(toCanvas(canvas));
	}
	static jlong canvas_element_get_canvas(TS_JNI_ARGS, jlong self) {
		return newCanvas(toCanvasElement(self).getCanvas());
	}
	static jlong canvas_element_get_canvas_1(TS_JNI_ARGS, jlong self) {
		return newCanvas(toCanvasElement(self).getCanvas());
	}
	static void canvas_element_set_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toCanvasElement(self).setMode((CanvasElement::Mode)mode);
	}
	static jint canvas_element_get_mode(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getMode();
	}
	static void canvas_element_set_align(TS_JNI_ARGS, jlong self, jint align) {
		toCanvasElement(self).setAlign((CanvasElement::Align)align);
	}
	static jint canvas_element_get_align(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getAlign();
	}
	static jboolean canvas_element_has_align(TS_JNI_ARGS, jlong self, jint align) {
		return toCanvasElement(self).hasAlign((CanvasElement::Align)align);
	}
	static jboolean canvas_element_has_aligns(TS_JNI_ARGS, jlong self, jint aligns) {
		return toCanvasElement(self).hasAligns((CanvasElement::Align)aligns);
	}
	static void canvas_element_set_order(TS_JNI_ARGS, jlong self, jint order) {
		toCanvasElement(self).setOrder(order);
	}
	static jint canvas_element_get_order(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getOrder();
	}
	static void canvas_element_set_enabled(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toCanvasElement(self).setEnabled((bool)enabled);
	}
	static jboolean canvas_element_is_enabled(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).isEnabled();
	}
	static void canvas_element_clear_color(TS_JNI_ARGS, jlong self) {
		toCanvasElement(self).clearColor();
	}
	static void canvas_element_set_color(TS_JNI_ARGS, jlong self, jint op) {
		toCanvasElement(self).setColor((CanvasElement::Stack)op);
	}
	static void canvas_element_set_color_1(TS_JNI_ARGS, jlong self, jlong color, jint op) {
		toCanvasElement(self).setColor(toColor(color), (CanvasElement::Stack)op);
	}
	static void canvas_element_set_color_2(TS_JNI_ARGS, jlong self, jfloat r, jfloat g, jfloat b, jfloat a, jint op) {
		toCanvasElement(self).setColor(r, g, b, a, (CanvasElement::Stack)op);
	}
	static jlong canvas_element_get_color(TS_JNI_ARGS, jlong self) {
		return newColor(toCanvasElement(self).getColor());
	}
	static jint canvas_element_get_color_op(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getColorOp();
	}
	static void canvas_element_clear_transform(TS_JNI_ARGS, jlong self) {
		toCanvasElement(self).clearTransform();
	}
	static void canvas_element_set_transform(TS_JNI_ARGS, jlong self, jint op) {
		toCanvasElement(self).setTransform((CanvasElement::Stack)op);
	}
	static void canvas_element_set_transform_1(TS_JNI_ARGS, jlong self, jlong transform, jint op) {
		toCanvasElement(self).setTransform(toMatrix4x4f(transform), (CanvasElement::Stack)op);
	}
	static jlong canvas_element_get_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x4f(toCanvasElement(self).getTransform());
	}
	static jint canvas_element_get_transform_op(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getTransformOp();
	}
	static void canvas_element_clear_scissor(TS_JNI_ARGS, jlong self) {
		toCanvasElement(self).clearScissor();
	}
	static void canvas_element_set_scissor(TS_JNI_ARGS, jlong self, jint op) {
		toCanvasElement(self).setScissor((CanvasElement::Stack)op);
	}
	static void canvas_element_set_scissor_1(TS_JNI_ARGS, jlong self, jlong scissor, jint op) {
		toCanvasElement(self).setScissor(toRect(scissor), (CanvasElement::Stack)op);
	}
	static jlong canvas_element_get_scissor(TS_JNI_ARGS, jlong self) {
		return newRect(toCanvasElement(self).getScissor());
	}
	static jint canvas_element_get_scissor_op(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getScissorOp();
	}
	static void canvas_element_set_mipmap(TS_JNI_ARGS, jlong self, jfloat mipmap) {
		toCanvasElement(self).setMipmap(mipmap);
	}
	static jfloat canvas_element_get_mipmap(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getMipmap();
	}
	static void canvas_element_set_sampler(TS_JNI_ARGS, jlong self, jlong sampler) {
		toCanvasElement(self).setSampler(toSampler(sampler));
	}
	static jlong canvas_element_get_sampler(TS_JNI_ARGS, jlong self) {
		return newSampler(toCanvasElement(self).getSampler());
	}
	static void canvas_element_set_filter(TS_JNI_ARGS, jlong self, jint filter) {
		toCanvasElement(self).setFilter((Sampler::Filter)filter);
	}
	static jint canvas_element_get_filter(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getFilter();
	}
	static void canvas_element_set_anisotropy(TS_JNI_ARGS, jlong self, jint anisotropy) {
		toCanvasElement(self).setAnisotropy((uint32_t)anisotropy);
	}
	static jint canvas_element_get_anisotropy(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getAnisotropy();
	}
	static void canvas_element_set_wrap_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toCanvasElement(self).setWrapMode((Sampler::WrapMode)mode);
	}
	static jint canvas_element_get_wrap_mode(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getWrapMode();
	}
	static void canvas_element_set_texture(TS_JNI_ARGS, jlong self, jlong texture, jboolean linear) {
		toCanvasElement(self).setTexture(toTexture(texture), (bool)linear);
	}
	static jlong canvas_element_get_texture(TS_JNI_ARGS, jlong self) {
		return newTexture(toCanvasElement(self).getTexture());
	}
	static jboolean canvas_element_get_texture_linear(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getTextureLinear();
	}
	static void canvas_element_set_pipeline(TS_JNI_ARGS, jlong self, jlong pipeline) {
		toCanvasElement(self).setPipeline(toPipeline(pipeline));
	}
	static jlong canvas_element_get_pipeline(TS_JNI_ARGS, jlong self) {
		return newPipeline(toCanvasElement(self).getPipeline());
	}
	static void canvas_element_set_primitive(TS_JNI_ARGS, jlong self, jint primitive) {
		toCanvasElement(self).setPrimitive((Pipeline::Primitive)primitive);
	}
	static jint canvas_element_get_primitive(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getPrimitive();
	}
	static void canvas_element_set_cull_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toCanvasElement(self).setCullMode((Pipeline::CullMode)mode);
	}
	static jint canvas_element_get_cull_mode(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getCullMode();
	}
	static void canvas_element_set_front_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toCanvasElement(self).setFrontMode((Pipeline::FrontMode)mode);
	}
	static jint canvas_element_get_front_mode(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getFrontMode();
	}
	static void canvas_element_set_blend(TS_JNI_ARGS, jlong self, jint op, jint src, jint dest) {
		toCanvasElement(self).setBlend((Pipeline::BlendOp)op, (Pipeline::BlendFunc)src, (Pipeline::BlendFunc)dest);
	}
	static jint canvas_element_get_blend_op(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getBlendOp();
	}
	static jint canvas_element_get_blend_src_func(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getBlendSrcFunc();
	}
	static jint canvas_element_get_blend_dest_func(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getBlendDestFunc();
	}
	static void canvas_element_set_color_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toCanvasElement(self).setColorMask((Pipeline::ColorMask)mask);
	}
	static jint canvas_element_get_color_mask(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getColorMask();
	}
	static void canvas_element_set_depth_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toCanvasElement(self).setDepthMask((Pipeline::DepthMask)mask);
	}
	static jint canvas_element_get_depth_mask(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getDepthMask();
	}
	static void canvas_element_set_depth_func(TS_JNI_ARGS, jlong self, jint func) {
		toCanvasElement(self).setDepthFunc((Pipeline::DepthFunc)func);
	}
	static jint canvas_element_get_depth_func(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getDepthFunc();
	}
	static void canvas_element_set_stencil_ref(TS_JNI_ARGS, jlong self, jint ref) {
		toCanvasElement(self).setStencilRef((uint32_t)ref);
	}
	static void canvas_element_set_stencil_func(TS_JNI_ARGS, jlong self, jint func, jint fail_op, jint dfail_op, jint dpass_op) {
		toCanvasElement(self).setStencilFunc((Pipeline::StencilFunc)func, (Pipeline::StencilOp)fail_op, (Pipeline::StencilOp)dfail_op, (Pipeline::StencilOp)dpass_op);
	}
	static jint canvas_element_get_stencil_ref(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getStencilRef();
	}
	static jint canvas_element_get_stencil_func(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getStencilFunc();
	}
	static jint canvas_element_get_stencil_fail_op(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getStencilFailOp();
	}
	static jint canvas_element_get_stencil_depth_fail_op(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getStencilDepthFailOp();
	}
	static jint canvas_element_get_stencil_depth_pass_op(TS_JNI_ARGS, jlong self) {
		return toCanvasElement(self).getStencilDepthPassOp();
	}
	static void canvas_element_set_draw_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toCanvasElement(self).setDrawCallback(make_canvas_element_draw_callback(env, func));
	}
	static jlong canvas_element_get_rect(TS_JNI_ARGS, jlong self) {
		return newRect(toCanvasElement(self).getRect());
	}
	static const JNINativeMethod canvas_element_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)canvas_element_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)canvas_element_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)canvas_element_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)canvas_element_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)canvas_element_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)canvas_element_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)canvas_element_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)canvas_element_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)canvas_element_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)canvas_element_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)canvas_element_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)canvas_element_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)canvas_element_get_internal_ptr },
		{ (char*)"get_type", (char*)"(J)I", (void*)canvas_element_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)canvas_element_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)canvas_element_get_type_name_1 },
		{ (char*)"is_text", (char*)"(J)Z", (void*)canvas_element_is_text },
		{ (char*)"is_mesh", (char*)"(J)Z", (void*)canvas_element_is_mesh },
		{ (char*)"is_rect", (char*)"(J)Z", (void*)canvas_element_is_rect },
		{ (char*)"is_triangle", (char*)"(J)Z", (void*)canvas_element_is_triangle },
		{ (char*)"is_ellipse", (char*)"(J)Z", (void*)canvas_element_is_ellipse },
		{ (char*)"is_shape", (char*)"(J)Z", (void*)canvas_element_is_shape },
		{ (char*)"is_strip", (char*)"(J)Z", (void*)canvas_element_is_strip },
		{ (char*)"set_canvas", (char*)"(JJ)V", (void*)canvas_element_set_canvas },
		{ (char*)"get_canvas", (char*)"(J)J", (void*)canvas_element_get_canvas },
		{ (char*)"get_canvas_1", (char*)"(J)J", (void*)canvas_element_get_canvas_1 },
		{ (char*)"set_mode", (char*)"(JI)V", (void*)canvas_element_set_mode },
		{ (char*)"get_mode", (char*)"(J)I", (void*)canvas_element_get_mode },
		{ (char*)"set_align", (char*)"(JI)V", (void*)canvas_element_set_align },
		{ (char*)"get_align", (char*)"(J)I", (void*)canvas_element_get_align },
		{ (char*)"has_align", (char*)"(JI)Z", (void*)canvas_element_has_align },
		{ (char*)"has_aligns", (char*)"(JI)Z", (void*)canvas_element_has_aligns },
		{ (char*)"set_order", (char*)"(JI)V", (void*)canvas_element_set_order },
		{ (char*)"get_order", (char*)"(J)I", (void*)canvas_element_get_order },
		{ (char*)"set_enabled", (char*)"(JZ)V", (void*)canvas_element_set_enabled },
		{ (char*)"is_enabled", (char*)"(J)Z", (void*)canvas_element_is_enabled },
		{ (char*)"clear_color", (char*)"(J)V", (void*)canvas_element_clear_color },
		{ (char*)"set_color", (char*)"(JI)V", (void*)canvas_element_set_color },
		{ (char*)"set_color_1", (char*)"(JJI)V", (void*)canvas_element_set_color_1 },
		{ (char*)"set_color_2", (char*)"(JFFFFI)V", (void*)canvas_element_set_color_2 },
		{ (char*)"get_color", (char*)"(J)J", (void*)canvas_element_get_color },
		{ (char*)"get_color_op", (char*)"(J)I", (void*)canvas_element_get_color_op },
		{ (char*)"clear_transform", (char*)"(J)V", (void*)canvas_element_clear_transform },
		{ (char*)"set_transform", (char*)"(JI)V", (void*)canvas_element_set_transform },
		{ (char*)"set_transform_1", (char*)"(JJI)V", (void*)canvas_element_set_transform_1 },
		{ (char*)"get_transform", (char*)"(J)J", (void*)canvas_element_get_transform },
		{ (char*)"get_transform_op", (char*)"(J)I", (void*)canvas_element_get_transform_op },
		{ (char*)"clear_scissor", (char*)"(J)V", (void*)canvas_element_clear_scissor },
		{ (char*)"set_scissor", (char*)"(JI)V", (void*)canvas_element_set_scissor },
		{ (char*)"set_scissor_1", (char*)"(JJI)V", (void*)canvas_element_set_scissor_1 },
		{ (char*)"get_scissor", (char*)"(J)J", (void*)canvas_element_get_scissor },
		{ (char*)"get_scissor_op", (char*)"(J)I", (void*)canvas_element_get_scissor_op },
		{ (char*)"set_mipmap", (char*)"(JF)V", (void*)canvas_element_set_mipmap },
		{ (char*)"get_mipmap", (char*)"(J)F", (void*)canvas_element_get_mipmap },
		{ (char*)"set_sampler", (char*)"(JJ)V", (void*)canvas_element_set_sampler },
		{ (char*)"get_sampler", (char*)"(J)J", (void*)canvas_element_get_sampler },
		{ (char*)"set_filter", (char*)"(JI)V", (void*)canvas_element_set_filter },
		{ (char*)"get_filter", (char*)"(J)I", (void*)canvas_element_get_filter },
		{ (char*)"set_anisotropy", (char*)"(JI)V", (void*)canvas_element_set_anisotropy },
		{ (char*)"get_anisotropy", (char*)"(J)I", (void*)canvas_element_get_anisotropy },
		{ (char*)"set_wrap_mode", (char*)"(JI)V", (void*)canvas_element_set_wrap_mode },
		{ (char*)"get_wrap_mode", (char*)"(J)I", (void*)canvas_element_get_wrap_mode },
		{ (char*)"set_texture", (char*)"(JJZ)V", (void*)canvas_element_set_texture },
		{ (char*)"get_texture", (char*)"(J)J", (void*)canvas_element_get_texture },
		{ (char*)"get_texture_linear", (char*)"(J)Z", (void*)canvas_element_get_texture_linear },
		{ (char*)"set_pipeline", (char*)"(JJ)V", (void*)canvas_element_set_pipeline },
		{ (char*)"get_pipeline", (char*)"(J)J", (void*)canvas_element_get_pipeline },
		{ (char*)"set_primitive", (char*)"(JI)V", (void*)canvas_element_set_primitive },
		{ (char*)"get_primitive", (char*)"(J)I", (void*)canvas_element_get_primitive },
		{ (char*)"set_cull_mode", (char*)"(JI)V", (void*)canvas_element_set_cull_mode },
		{ (char*)"get_cull_mode", (char*)"(J)I", (void*)canvas_element_get_cull_mode },
		{ (char*)"set_front_mode", (char*)"(JI)V", (void*)canvas_element_set_front_mode },
		{ (char*)"get_front_mode", (char*)"(J)I", (void*)canvas_element_get_front_mode },
		{ (char*)"set_blend", (char*)"(JIII)V", (void*)canvas_element_set_blend },
		{ (char*)"get_blend_op", (char*)"(J)I", (void*)canvas_element_get_blend_op },
		{ (char*)"get_blend_src_func", (char*)"(J)I", (void*)canvas_element_get_blend_src_func },
		{ (char*)"get_blend_dest_func", (char*)"(J)I", (void*)canvas_element_get_blend_dest_func },
		{ (char*)"set_color_mask", (char*)"(JI)V", (void*)canvas_element_set_color_mask },
		{ (char*)"get_color_mask", (char*)"(J)I", (void*)canvas_element_get_color_mask },
		{ (char*)"set_depth_mask", (char*)"(JI)V", (void*)canvas_element_set_depth_mask },
		{ (char*)"get_depth_mask", (char*)"(J)I", (void*)canvas_element_get_depth_mask },
		{ (char*)"set_depth_func", (char*)"(JI)V", (void*)canvas_element_set_depth_func },
		{ (char*)"get_depth_func", (char*)"(J)I", (void*)canvas_element_get_depth_func },
		{ (char*)"set_stencil_ref", (char*)"(JI)V", (void*)canvas_element_set_stencil_ref },
		{ (char*)"set_stencil_func", (char*)"(JIIII)V", (void*)canvas_element_set_stencil_func },
		{ (char*)"get_stencil_ref", (char*)"(J)I", (void*)canvas_element_get_stencil_ref },
		{ (char*)"get_stencil_func", (char*)"(J)I", (void*)canvas_element_get_stencil_func },
		{ (char*)"get_stencil_fail_op", (char*)"(J)I", (void*)canvas_element_get_stencil_fail_op },
		{ (char*)"get_stencil_depth_fail_op", (char*)"(J)I", (void*)canvas_element_get_stencil_depth_fail_op },
		{ (char*)"get_stencil_depth_pass_op", (char*)"(J)I", (void*)canvas_element_get_stencil_depth_pass_op },
		{ (char*)"set_draw_callback", (char*)"(JL" TS_JNI_PREFIX "CanvasElement$DrawCallback;)V", (void*)canvas_element_set_draw_callback },
		{ (char*)"get_rect", (char*)"(J)J", (void*)canvas_element_get_rect },
	};
	
	// Tellusim::CanvasText
	static jlong canvas_text_new(TS_JNI_ARGS) {
		return newCanvasText();
	}
	static jlong canvas_text_new_1(TS_JNI_ARGS, jlong canvas) {
		return newCanvasText(toCanvas(canvas));
	}
	static jlong canvas_text_new_2(TS_JNI_ARGS, jlong canvas, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newCanvasText(toCanvas(canvas), text_);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong canvas_text_new_3(TS_JNI_ARGS, jlong canvas, jlong text) {
		return newCanvasText(toCanvas(canvas), toString(text));
	}
	static void canvas_text_delete(TS_JNI_ARGS, jlong self) {
		delete (CanvasText*)self;
	}
	static jboolean canvas_text_equal_canvas_element_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCanvasText(self).operator==(toCanvasElement(base));
	}
	static jlong canvas_text_cast_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasText(toCanvasElement(self));
	}
	static jlong canvas_text_base_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasElement(toCanvasText(self).getCanvasElement());
	}
	static void canvas_text_set_font_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toCanvasText(self).setFontName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void canvas_text_set_font_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toCanvasText(self).setFontName(toString(name));
	}
	static jstring canvas_text_get_font_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toCanvasText(self).getFontName().get());
	}
	static void canvas_text_set_font_color(TS_JNI_ARGS, jlong self, jlong color) {
		toCanvasText(self).setFontColor(toColor(color));
	}
	static jlong canvas_text_get_font_color(TS_JNI_ARGS, jlong self) {
		return newColor(toCanvasText(self).getFontColor());
	}
	static jboolean canvas_text_set_font_size(TS_JNI_ARGS, jlong self, jint scale) {
		return toCanvasText(self).setFontSize((uint32_t)scale);
	}
	static jint canvas_text_get_font_size(TS_JNI_ARGS, jlong self) {
		return toCanvasText(self).getFontSize();
	}
	static jboolean canvas_text_set_font_scale(TS_JNI_ARGS, jlong self, jint scale) {
		return toCanvasText(self).setFontScale((uint32_t)scale);
	}
	static jint canvas_text_get_font_scale(TS_JNI_ARGS, jlong self) {
		return toCanvasText(self).getFontScale();
	}
	static jboolean canvas_text_set_font_style(TS_JNI_ARGS, jlong self, jlong style) {
		return toCanvasText(self).setFontStyle(toFontStyle(style));
	}
	static jlong canvas_text_get_font_style_const(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toCanvasText(self).getFontStyleConst());
	}
	static jlong canvas_text_get_font_style(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toCanvasText(self).getFontStyle());
	}
	static jlong canvas_text_get_font_style_1(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toCanvasText(self).getFontStyle());
	}
	static void canvas_text_set_position(TS_JNI_ARGS, jlong self, jlong position) {
		toCanvasText(self).setPosition(toVector3f(position));
	}
	static void canvas_text_set_position_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		toCanvasText(self).setPosition(x, y, z);
	}
	static jlong canvas_text_get_position(TS_JNI_ARGS, jlong self) {
		return newVector3f(toCanvasText(self).getPosition());
	}
	static void canvas_text_set_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toCanvasText(self).setText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void canvas_text_set_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toCanvasText(self).setText(toString(text));
	}
	static jstring canvas_text_get_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toCanvasText(self).getText().get());
	}
	static void canvas_text_clear_batches(TS_JNI_ARGS, jlong self) {
		toCanvasText(self).clearBatches();
	}
	static const JNINativeMethod canvas_text_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)canvas_text_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)canvas_text_new_1 },
		{ (char*)"new_2", (char*)"(JLjava/lang/String;)J", (void*)canvas_text_new_2 },
		{ (char*)"new_3", (char*)"(JJ)J", (void*)canvas_text_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)canvas_text_delete },
		{ (char*)"equal_canvas_element_ptr", (char*)"(JJ)Z", (void*)canvas_text_equal_canvas_element_ptr },
		{ (char*)"cast_canvas_element_ptr", (char*)"(J)J", (void*)canvas_text_cast_canvas_element_ptr },
		{ (char*)"base_canvas_element_ptr", (char*)"(J)J", (void*)canvas_text_base_canvas_element_ptr },
		{ (char*)"set_font_name", (char*)"(JLjava/lang/String;)V", (void*)canvas_text_set_font_name },
		{ (char*)"set_font_name_1", (char*)"(JJ)V", (void*)canvas_text_set_font_name_1 },
		{ (char*)"get_font_name", (char*)"(J)Ljava/lang/String;", (void*)canvas_text_get_font_name },
		{ (char*)"set_font_color", (char*)"(JJ)V", (void*)canvas_text_set_font_color },
		{ (char*)"get_font_color", (char*)"(J)J", (void*)canvas_text_get_font_color },
		{ (char*)"set_font_size", (char*)"(JI)Z", (void*)canvas_text_set_font_size },
		{ (char*)"get_font_size", (char*)"(J)I", (void*)canvas_text_get_font_size },
		{ (char*)"set_font_scale", (char*)"(JI)Z", (void*)canvas_text_set_font_scale },
		{ (char*)"get_font_scale", (char*)"(J)I", (void*)canvas_text_get_font_scale },
		{ (char*)"set_font_style", (char*)"(JJ)Z", (void*)canvas_text_set_font_style },
		{ (char*)"get_font_style_const", (char*)"(J)J", (void*)canvas_text_get_font_style_const },
		{ (char*)"get_font_style", (char*)"(J)J", (void*)canvas_text_get_font_style },
		{ (char*)"get_font_style_1", (char*)"(J)J", (void*)canvas_text_get_font_style_1 },
		{ (char*)"set_position", (char*)"(JJ)V", (void*)canvas_text_set_position },
		{ (char*)"set_position_1", (char*)"(JFFF)V", (void*)canvas_text_set_position_1 },
		{ (char*)"get_position", (char*)"(J)J", (void*)canvas_text_get_position },
		{ (char*)"set_text", (char*)"(JLjava/lang/String;)V", (void*)canvas_text_set_text },
		{ (char*)"set_text_1", (char*)"(JJ)V", (void*)canvas_text_set_text_1 },
		{ (char*)"get_text", (char*)"(J)Ljava/lang/String;", (void*)canvas_text_get_text },
		{ (char*)"clear_batches", (char*)"(J)V", (void*)canvas_text_clear_batches },
	};
	
	// Tellusim::CanvasMesh
	static jlong canvas_mesh_new(TS_JNI_ARGS) {
		return newCanvasMesh();
	}
	static jlong canvas_mesh_new_1(TS_JNI_ARGS, jlong canvas) {
		return newCanvasMesh(toCanvas(canvas));
	}
	static jlong canvas_mesh_new_2(TS_JNI_ARGS, jlong canvas, jint mode) {
		return newCanvasMesh(toCanvas(canvas), (CanvasElement::Mode)mode);
	}
	static void canvas_mesh_delete(TS_JNI_ARGS, jlong self) {
		delete (CanvasMesh*)self;
	}
	static jboolean canvas_mesh_equal_canvas_element_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCanvasMesh(self).operator==(toCanvasElement(base));
	}
	static jlong canvas_mesh_cast_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasMesh(toCanvasElement(self));
	}
	static jlong canvas_mesh_base_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasElement(toCanvasMesh(self).getCanvasElement());
	}
	static void canvas_mesh_set_texture_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toCanvasMesh(self).setTextureName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void canvas_mesh_set_texture_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toCanvasMesh(self).setTextureName(toString(name));
	}
	static jstring canvas_mesh_get_texture_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toCanvasMesh(self).getTextureName().get());
	}
	static void canvas_mesh_set_gradient_style(TS_JNI_ARGS, jlong self, jlong style) {
		toCanvasMesh(self).setGradientStyle(toGradientStyle(style));
	}
	static jlong canvas_mesh_get_gradient_style_const(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasMesh(self).getGradientStyleConst());
	}
	static jlong canvas_mesh_get_gradient_style(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasMesh(self).getGradientStyle());
	}
	static jlong canvas_mesh_get_gradient_style_1(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasMesh(self).getGradientStyle());
	}
	static void canvas_mesh_clear_vertices(TS_JNI_ARGS, jlong self) {
		toCanvasMesh(self).clearVertices();
	}
	static void canvas_mesh_set_num_vertices(TS_JNI_ARGS, jlong self, jint num_vertices) {
		toCanvasMesh(self).setNumVertices((uint32_t)num_vertices);
	}
	static void canvas_mesh_reserve_vertices(TS_JNI_ARGS, jlong self, jint num_vertices) {
		toCanvasMesh(self).reserveVertices((uint32_t)num_vertices);
	}
	static jint canvas_mesh_get_num_vertices(TS_JNI_ARGS, jlong self) {
		return toCanvasMesh(self).getNumVertices();
	}
	static void canvas_mesh_set_vertices(TS_JNI_ARGS, jlong self, jlongArray vertices) {
		Array<CanvasVertex> vertices_((uint32_t)env->GetArrayLength(vertices));
		jlong *vertices__ = env->GetLongArrayElements(vertices, nullptr);
		for(uint32_t i = 0; i < vertices_.size(); i++) vertices_[i] = toCanvasVertex(vertices__[i]);
		toCanvasMesh(self).setVertices(vertices_.get(), vertices_.size());
		if(vertices__) env->ReleaseLongArrayElements(vertices, vertices__, 0);
	}
	static void canvas_mesh_add_vertices(TS_JNI_ARGS, jlong self, jlongArray vertices) {
		Array<CanvasVertex> vertices_((uint32_t)env->GetArrayLength(vertices));
		jlong *vertices__ = env->GetLongArrayElements(vertices, nullptr);
		for(uint32_t i = 0; i < vertices_.size(); i++) vertices_[i] = toCanvasVertex(vertices__[i]);
		toCanvasMesh(self).addVertices(vertices_.get(), vertices_.size());
		if(vertices__) env->ReleaseLongArrayElements(vertices, vertices__, 0);
	}
	static jlong canvas_mesh_get_vertices(TS_JNI_ARGS, jlong self) {
		return (jlong)toCanvasMesh(self).getVertices();
	}
	static jlong canvas_mesh_get_vertices_1(TS_JNI_ARGS, jlong self) {
		return (jlong)toCanvasMesh(self).getVertices();
	}
	static void canvas_mesh_set_vertex(TS_JNI_ARGS, jlong self, jint index, jlong vertex) {
		toCanvasMesh(self).setVertex((uint32_t)index, toCanvasVertex(vertex));
	}
	static jlong canvas_mesh_get_vertex(TS_JNI_ARGS, jlong self, jint index) {
		return newCanvasVertex(toCanvasMesh(self).getVertex((uint32_t)index));
	}
	static jlong canvas_mesh_get_vertex_1(TS_JNI_ARGS, jlong self, jint index) {
		return newCanvasVertex(toCanvasMesh(self).getVertex((uint32_t)index));
	}
	static void canvas_mesh_set_vertex_position(TS_JNI_ARGS, jlong self, jint index, jlong position) {
		toCanvasMesh(self).setVertexPosition((uint32_t)index, toVector3f(position));
	}
	static void canvas_mesh_set_vertex_position_1(TS_JNI_ARGS, jlong self, jint index, jfloat x, jfloat y, jfloat z) {
		toCanvasMesh(self).setVertexPosition((uint32_t)index, x, y, z);
	}
	static jlong canvas_mesh_get_vertex_position(TS_JNI_ARGS, jlong self, jint index) {
		return newVector3f(toCanvasMesh(self).getVertexPosition((uint32_t)index));
	}
	static void canvas_mesh_set_vertex_tex_coord(TS_JNI_ARGS, jlong self, jint index, jlong texcoord) {
		toCanvasMesh(self).setVertexTexCoord((uint32_t)index, toVector2f(texcoord));
	}
	static void canvas_mesh_set_vertex_tex_coord_1(TS_JNI_ARGS, jlong self, jint index, jfloat s, jfloat t) {
		toCanvasMesh(self).setVertexTexCoord((uint32_t)index, s, t);
	}
	static jlong canvas_mesh_get_vertex_tex_coord(TS_JNI_ARGS, jlong self, jint index) {
		return newVector2f(toCanvasMesh(self).getVertexTexCoord((uint32_t)index));
	}
	static void canvas_mesh_set_vertex_color(TS_JNI_ARGS, jlong self, jint index, jlong color) {
		toCanvasMesh(self).setVertexColor((uint32_t)index, toColor(color));
	}
	static void canvas_mesh_set_vertex_color_1(TS_JNI_ARGS, jlong self, jint index, jint color) {
		toCanvasMesh(self).setVertexColor((uint32_t)index, (uint32_t)color);
	}
	static jint canvas_mesh_get_vertex_color(TS_JNI_ARGS, jlong self, jint index) {
		return toCanvasMesh(self).getVertexColor((uint32_t)index);
	}
	static jint canvas_mesh_add_vertex(TS_JNI_ARGS, jlong self, jlong position) {
		return toCanvasMesh(self).addVertex(toVector3f(position));
	}
	static jint canvas_mesh_add_vertex_1(TS_JNI_ARGS, jlong self, jlong position, jint color) {
		return toCanvasMesh(self).addVertex(toVector3f(position), (uint32_t)color);
	}
	static jint canvas_mesh_add_vertex_2(TS_JNI_ARGS, jlong self, jlong position, jlong texcoord) {
		return toCanvasMesh(self).addVertex(toVector3f(position), toVector2f(texcoord));
	}
	static jint canvas_mesh_add_vertex_3(TS_JNI_ARGS, jlong self, jlong position, jlong texcoord, jint color) {
		return toCanvasMesh(self).addVertex(toVector3f(position), toVector2f(texcoord), (uint32_t)color);
	}
	static jint canvas_mesh_add_vertex_4(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z, jfloat s, jfloat t, jint color) {
		return toCanvasMesh(self).addVertex(x, y, z, s, t, (uint32_t)color);
	}
	static jint canvas_mesh_add_vertex_5(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z, jint color) {
		return toCanvasMesh(self).addVertex(x, y, z, (uint32_t)color);
	}
	static jint canvas_mesh_add_vertex_6(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jint color) {
		return toCanvasMesh(self).addVertex(x, y, (uint32_t)color);
	}
	static void canvas_mesh_clear_indices(TS_JNI_ARGS, jlong self) {
		toCanvasMesh(self).clearIndices();
	}
	static void canvas_mesh_set_num_indices(TS_JNI_ARGS, jlong self, jint num_indices) {
		toCanvasMesh(self).setNumIndices((uint32_t)num_indices);
	}
	static void canvas_mesh_reserve_indices(TS_JNI_ARGS, jlong self, jint num_indices) {
		toCanvasMesh(self).reserveIndices((uint32_t)num_indices);
	}
	static jint canvas_mesh_get_num_indices(TS_JNI_ARGS, jlong self) {
		return toCanvasMesh(self).getNumIndices();
	}
	static void canvas_mesh_set_indices(TS_JNI_ARGS, jlong self, jintArray indices) {
		toCanvasMesh(self).setIndices((uint32_t*)IntArray(env, indices).get(), (uint32_t)env->GetArrayLength(indices));
	}
	static void canvas_mesh_add_indices(TS_JNI_ARGS, jlong self, jintArray indices) {
		toCanvasMesh(self).addIndices((uint32_t*)IntArray(env, indices).get(), (uint32_t)env->GetArrayLength(indices));
	}
	static jlong canvas_mesh_get_indices(TS_JNI_ARGS, jlong self) {
		return (jlong)toCanvasMesh(self).getIndices();
	}
	static jlong canvas_mesh_get_indices_1(TS_JNI_ARGS, jlong self) {
		return (jlong)toCanvasMesh(self).getIndices();
	}
	static void canvas_mesh_set_index(TS_JNI_ARGS, jlong self, jint index, jint value) {
		toCanvasMesh(self).setIndex((uint32_t)index, (uint32_t)value);
	}
	static jint canvas_mesh_get_index(TS_JNI_ARGS, jlong self, jint index) {
		return toCanvasMesh(self).getIndex((uint32_t)index);
	}
	static void canvas_mesh_add_index(TS_JNI_ARGS, jlong self, jint i0) {
		toCanvasMesh(self).addIndex((uint32_t)i0);
	}
	static void canvas_mesh_add_indices_1(TS_JNI_ARGS, jlong self, jint i0, jint i1) {
		toCanvasMesh(self).addIndices((uint32_t)i0, (uint32_t)i1);
	}
	static void canvas_mesh_add_indices_2(TS_JNI_ARGS, jlong self, jint i0, jint i1, jint i2) {
		toCanvasMesh(self).addIndices((uint32_t)i0, (uint32_t)i1, (uint32_t)i2);
	}
	static void canvas_mesh_add_indices_3(TS_JNI_ARGS, jlong self, jint i0, jint i1, jint i2, jint i3) {
		toCanvasMesh(self).addIndices((uint32_t)i0, (uint32_t)i1, (uint32_t)i2, (uint32_t)i3);
	}
	static void canvas_mesh_set_rect(TS_JNI_ARGS, jlong self, jlong rect) {
		toCanvasMesh(self).setRect(toRect(rect));
	}
	static const JNINativeMethod canvas_mesh_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)canvas_mesh_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)canvas_mesh_new_1 },
		{ (char*)"new_2", (char*)"(JI)J", (void*)canvas_mesh_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)canvas_mesh_delete },
		{ (char*)"equal_canvas_element_ptr", (char*)"(JJ)Z", (void*)canvas_mesh_equal_canvas_element_ptr },
		{ (char*)"cast_canvas_element_ptr", (char*)"(J)J", (void*)canvas_mesh_cast_canvas_element_ptr },
		{ (char*)"base_canvas_element_ptr", (char*)"(J)J", (void*)canvas_mesh_base_canvas_element_ptr },
		{ (char*)"set_texture_name", (char*)"(JLjava/lang/String;)V", (void*)canvas_mesh_set_texture_name },
		{ (char*)"set_texture_name_1", (char*)"(JJ)V", (void*)canvas_mesh_set_texture_name_1 },
		{ (char*)"get_texture_name", (char*)"(J)Ljava/lang/String;", (void*)canvas_mesh_get_texture_name },
		{ (char*)"set_gradient_style", (char*)"(JJ)V", (void*)canvas_mesh_set_gradient_style },
		{ (char*)"get_gradient_style_const", (char*)"(J)J", (void*)canvas_mesh_get_gradient_style_const },
		{ (char*)"get_gradient_style", (char*)"(J)J", (void*)canvas_mesh_get_gradient_style },
		{ (char*)"get_gradient_style_1", (char*)"(J)J", (void*)canvas_mesh_get_gradient_style_1 },
		{ (char*)"clear_vertices", (char*)"(J)V", (void*)canvas_mesh_clear_vertices },
		{ (char*)"set_num_vertices", (char*)"(JI)V", (void*)canvas_mesh_set_num_vertices },
		{ (char*)"reserve_vertices", (char*)"(JI)V", (void*)canvas_mesh_reserve_vertices },
		{ (char*)"get_num_vertices", (char*)"(J)I", (void*)canvas_mesh_get_num_vertices },
		{ (char*)"set_vertices", (char*)"(J[J)V", (void*)canvas_mesh_set_vertices },
		{ (char*)"add_vertices", (char*)"(J[J)V", (void*)canvas_mesh_add_vertices },
		{ (char*)"get_vertices", (char*)"(J)J", (void*)canvas_mesh_get_vertices },
		{ (char*)"get_vertices_1", (char*)"(J)J", (void*)canvas_mesh_get_vertices_1 },
		{ (char*)"set_vertex", (char*)"(JIJ)V", (void*)canvas_mesh_set_vertex },
		{ (char*)"get_vertex", (char*)"(JI)J", (void*)canvas_mesh_get_vertex },
		{ (char*)"get_vertex_1", (char*)"(JI)J", (void*)canvas_mesh_get_vertex_1 },
		{ (char*)"set_vertex_position", (char*)"(JIJ)V", (void*)canvas_mesh_set_vertex_position },
		{ (char*)"set_vertex_position_1", (char*)"(JIFFF)V", (void*)canvas_mesh_set_vertex_position_1 },
		{ (char*)"get_vertex_position", (char*)"(JI)J", (void*)canvas_mesh_get_vertex_position },
		{ (char*)"set_vertex_tex_coord", (char*)"(JIJ)V", (void*)canvas_mesh_set_vertex_tex_coord },
		{ (char*)"set_vertex_tex_coord_1", (char*)"(JIFF)V", (void*)canvas_mesh_set_vertex_tex_coord_1 },
		{ (char*)"get_vertex_tex_coord", (char*)"(JI)J", (void*)canvas_mesh_get_vertex_tex_coord },
		{ (char*)"set_vertex_color", (char*)"(JIJ)V", (void*)canvas_mesh_set_vertex_color },
		{ (char*)"set_vertex_color_1", (char*)"(JII)V", (void*)canvas_mesh_set_vertex_color_1 },
		{ (char*)"get_vertex_color", (char*)"(JI)I", (void*)canvas_mesh_get_vertex_color },
		{ (char*)"add_vertex", (char*)"(JJ)I", (void*)canvas_mesh_add_vertex },
		{ (char*)"add_vertex_1", (char*)"(JJI)I", (void*)canvas_mesh_add_vertex_1 },
		{ (char*)"add_vertex_2", (char*)"(JJJ)I", (void*)canvas_mesh_add_vertex_2 },
		{ (char*)"add_vertex_3", (char*)"(JJJI)I", (void*)canvas_mesh_add_vertex_3 },
		{ (char*)"add_vertex_4", (char*)"(JFFFFFI)I", (void*)canvas_mesh_add_vertex_4 },
		{ (char*)"add_vertex_5", (char*)"(JFFFI)I", (void*)canvas_mesh_add_vertex_5 },
		{ (char*)"add_vertex_6", (char*)"(JFFI)I", (void*)canvas_mesh_add_vertex_6 },
		{ (char*)"clear_indices", (char*)"(J)V", (void*)canvas_mesh_clear_indices },
		{ (char*)"set_num_indices", (char*)"(JI)V", (void*)canvas_mesh_set_num_indices },
		{ (char*)"reserve_indices", (char*)"(JI)V", (void*)canvas_mesh_reserve_indices },
		{ (char*)"get_num_indices", (char*)"(J)I", (void*)canvas_mesh_get_num_indices },
		{ (char*)"set_indices", (char*)"(J[I)V", (void*)canvas_mesh_set_indices },
		{ (char*)"add_indices", (char*)"(J[I)V", (void*)canvas_mesh_add_indices },
		{ (char*)"get_indices", (char*)"(J)J", (void*)canvas_mesh_get_indices },
		{ (char*)"get_indices_1", (char*)"(J)J", (void*)canvas_mesh_get_indices_1 },
		{ (char*)"set_index", (char*)"(JII)V", (void*)canvas_mesh_set_index },
		{ (char*)"get_index", (char*)"(JI)I", (void*)canvas_mesh_get_index },
		{ (char*)"add_index", (char*)"(JI)V", (void*)canvas_mesh_add_index },
		{ (char*)"add_indices_1", (char*)"(JII)V", (void*)canvas_mesh_add_indices_1 },
		{ (char*)"add_indices_2", (char*)"(JIII)V", (void*)canvas_mesh_add_indices_2 },
		{ (char*)"add_indices_3", (char*)"(JIIII)V", (void*)canvas_mesh_add_indices_3 },
		{ (char*)"set_rect", (char*)"(JJ)V", (void*)canvas_mesh_set_rect },
	};
	
	// Tellusim::CanvasRect
	static jlong canvas_rect_new(TS_JNI_ARGS) {
		return newCanvasRect();
	}
	static jlong canvas_rect_new_1(TS_JNI_ARGS, jlong canvas) {
		return newCanvasRect(toCanvas(canvas));
	}
	static jlong canvas_rect_new_2(TS_JNI_ARGS, jlong canvas, jfloat radius) {
		return newCanvasRect(toCanvas(canvas), radius);
	}
	static jlong canvas_rect_new_3(TS_JNI_ARGS, jlong canvas, jfloat radius, jlong size) {
		return newCanvasRect(toCanvas(canvas), radius, toVector2f(size));
	}
	static void canvas_rect_delete(TS_JNI_ARGS, jlong self) {
		delete (CanvasRect*)self;
	}
	static jboolean canvas_rect_equal_canvas_element_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCanvasRect(self).operator==(toCanvasElement(base));
	}
	static jlong canvas_rect_cast_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasRect(toCanvasElement(self));
	}
	static jlong canvas_rect_base_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasElement(toCanvasRect(self).getCanvasElement());
	}
	static void canvas_rect_set_radius(TS_JNI_ARGS, jlong self, jfloat radius) {
		toCanvasRect(self).setRadius(radius);
	}
	static jfloat canvas_rect_get_radius(TS_JNI_ARGS, jlong self) {
		return toCanvasRect(self).getRadius();
	}
	static void canvas_rect_set_texture_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toCanvasRect(self).setTextureName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void canvas_rect_set_texture_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toCanvasRect(self).setTextureName(toString(name));
	}
	static jstring canvas_rect_get_texture_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toCanvasRect(self).getTextureName().get());
	}
	static void canvas_rect_set_stroke_color(TS_JNI_ARGS, jlong self, jlong color) {
		toCanvasRect(self).setStrokeColor(toColor(color));
	}
	static jlong canvas_rect_get_stroke_color(TS_JNI_ARGS, jlong self) {
		return newColor(toCanvasRect(self).getStrokeColor());
	}
	static void canvas_rect_set_stroke_style(TS_JNI_ARGS, jlong self, jlong style) {
		toCanvasRect(self).setStrokeStyle(toStrokeStyle(style));
	}
	static jlong canvas_rect_get_stroke_style_const(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasRect(self).getStrokeStyleConst());
	}
	static jlong canvas_rect_get_stroke_style(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasRect(self).getStrokeStyle());
	}
	static jlong canvas_rect_get_stroke_style_1(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasRect(self).getStrokeStyle());
	}
	static void canvas_rect_set_gradient_style(TS_JNI_ARGS, jlong self, jlong style) {
		toCanvasRect(self).setGradientStyle(toGradientStyle(style));
	}
	static jlong canvas_rect_get_gradient_style_const(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasRect(self).getGradientStyleConst());
	}
	static jlong canvas_rect_get_gradient_style(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasRect(self).getGradientStyle());
	}
	static jlong canvas_rect_get_gradient_style_1(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasRect(self).getGradientStyle());
	}
	static void canvas_rect_set_size(TS_JNI_ARGS, jlong self, jlong size) {
		toCanvasRect(self).setSize(toVector2f(size));
	}
	static void canvas_rect_set_size_1(TS_JNI_ARGS, jlong self, jfloat width, jfloat height) {
		toCanvasRect(self).setSize(width, height);
	}
	static jlong canvas_rect_get_size(TS_JNI_ARGS, jlong self) {
		return newVector2f(toCanvasRect(self).getSize());
	}
	static jfloat canvas_rect_get_width(TS_JNI_ARGS, jlong self) {
		return toCanvasRect(self).getWidth();
	}
	static jfloat canvas_rect_get_height(TS_JNI_ARGS, jlong self) {
		return toCanvasRect(self).getHeight();
	}
	static void canvas_rect_set_position(TS_JNI_ARGS, jlong self, jlong position) {
		toCanvasRect(self).setPosition(toVector3f(position));
	}
	static void canvas_rect_set_position_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		toCanvasRect(self).setPosition(x, y, z);
	}
	static jlong canvas_rect_get_position(TS_JNI_ARGS, jlong self) {
		return newVector3f(toCanvasRect(self).getPosition());
	}
	static void canvas_rect_set_tex_coord(TS_JNI_ARGS, jlong self, jlong texcoord) {
		toCanvasRect(self).setTexCoord(toRect(texcoord));
	}
	static void canvas_rect_set_tex_coord_1(TS_JNI_ARGS, jlong self, jfloat left, jfloat right, jfloat bottom, jfloat top) {
		toCanvasRect(self).setTexCoord(left, right, bottom, top);
	}
	static jlong canvas_rect_get_tex_coord(TS_JNI_ARGS, jlong self) {
		return newRect(toCanvasRect(self).getTexCoord());
	}
	static const JNINativeMethod canvas_rect_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)canvas_rect_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)canvas_rect_new_1 },
		{ (char*)"new_2", (char*)"(JF)J", (void*)canvas_rect_new_2 },
		{ (char*)"new_3", (char*)"(JFJ)J", (void*)canvas_rect_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)canvas_rect_delete },
		{ (char*)"equal_canvas_element_ptr", (char*)"(JJ)Z", (void*)canvas_rect_equal_canvas_element_ptr },
		{ (char*)"cast_canvas_element_ptr", (char*)"(J)J", (void*)canvas_rect_cast_canvas_element_ptr },
		{ (char*)"base_canvas_element_ptr", (char*)"(J)J", (void*)canvas_rect_base_canvas_element_ptr },
		{ (char*)"set_radius", (char*)"(JF)V", (void*)canvas_rect_set_radius },
		{ (char*)"get_radius", (char*)"(J)F", (void*)canvas_rect_get_radius },
		{ (char*)"set_texture_name", (char*)"(JLjava/lang/String;)V", (void*)canvas_rect_set_texture_name },
		{ (char*)"set_texture_name_1", (char*)"(JJ)V", (void*)canvas_rect_set_texture_name_1 },
		{ (char*)"get_texture_name", (char*)"(J)Ljava/lang/String;", (void*)canvas_rect_get_texture_name },
		{ (char*)"set_stroke_color", (char*)"(JJ)V", (void*)canvas_rect_set_stroke_color },
		{ (char*)"get_stroke_color", (char*)"(J)J", (void*)canvas_rect_get_stroke_color },
		{ (char*)"set_stroke_style", (char*)"(JJ)V", (void*)canvas_rect_set_stroke_style },
		{ (char*)"get_stroke_style_const", (char*)"(J)J", (void*)canvas_rect_get_stroke_style_const },
		{ (char*)"get_stroke_style", (char*)"(J)J", (void*)canvas_rect_get_stroke_style },
		{ (char*)"get_stroke_style_1", (char*)"(J)J", (void*)canvas_rect_get_stroke_style_1 },
		{ (char*)"set_gradient_style", (char*)"(JJ)V", (void*)canvas_rect_set_gradient_style },
		{ (char*)"get_gradient_style_const", (char*)"(J)J", (void*)canvas_rect_get_gradient_style_const },
		{ (char*)"get_gradient_style", (char*)"(J)J", (void*)canvas_rect_get_gradient_style },
		{ (char*)"get_gradient_style_1", (char*)"(J)J", (void*)canvas_rect_get_gradient_style_1 },
		{ (char*)"set_size", (char*)"(JJ)V", (void*)canvas_rect_set_size },
		{ (char*)"set_size_1", (char*)"(JFF)V", (void*)canvas_rect_set_size_1 },
		{ (char*)"get_size", (char*)"(J)J", (void*)canvas_rect_get_size },
		{ (char*)"get_width", (char*)"(J)F", (void*)canvas_rect_get_width },
		{ (char*)"get_height", (char*)"(J)F", (void*)canvas_rect_get_height },
		{ (char*)"set_position", (char*)"(JJ)V", (void*)canvas_rect_set_position },
		{ (char*)"set_position_1", (char*)"(JFFF)V", (void*)canvas_rect_set_position_1 },
		{ (char*)"get_position", (char*)"(J)J", (void*)canvas_rect_get_position },
		{ (char*)"set_tex_coord", (char*)"(JJ)V", (void*)canvas_rect_set_tex_coord },
		{ (char*)"set_tex_coord_1", (char*)"(JFFFF)V", (void*)canvas_rect_set_tex_coord_1 },
		{ (char*)"get_tex_coord", (char*)"(J)J", (void*)canvas_rect_get_tex_coord },
	};
	
	// Tellusim::CanvasTriangle
	static jlong canvas_triangle_new(TS_JNI_ARGS) {
		return newCanvasTriangle();
	}
	static jlong canvas_triangle_new_1(TS_JNI_ARGS, jlong canvas) {
		return newCanvasTriangle(toCanvas(canvas));
	}
	static jlong canvas_triangle_new_2(TS_JNI_ARGS, jlong canvas, jfloat radius) {
		return newCanvasTriangle(toCanvas(canvas), radius);
	}
	static void canvas_triangle_delete(TS_JNI_ARGS, jlong self) {
		delete (CanvasTriangle*)self;
	}
	static jboolean canvas_triangle_equal_canvas_element_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCanvasTriangle(self).operator==(toCanvasElement(base));
	}
	static jlong canvas_triangle_cast_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasTriangle(toCanvasElement(self));
	}
	static jlong canvas_triangle_base_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasElement(toCanvasTriangle(self).getCanvasElement());
	}
	static void canvas_triangle_set_radius(TS_JNI_ARGS, jlong self, jfloat radius) {
		toCanvasTriangle(self).setRadius(radius);
	}
	static jfloat canvas_triangle_get_radius(TS_JNI_ARGS, jlong self) {
		return toCanvasTriangle(self).getRadius();
	}
	static void canvas_triangle_set_stroke_color(TS_JNI_ARGS, jlong self, jlong color) {
		toCanvasTriangle(self).setStrokeColor(toColor(color));
	}
	static jlong canvas_triangle_get_stroke_color(TS_JNI_ARGS, jlong self) {
		return newColor(toCanvasTriangle(self).getStrokeColor());
	}
	static void canvas_triangle_set_stroke_style(TS_JNI_ARGS, jlong self, jlong style) {
		toCanvasTriangle(self).setStrokeStyle(toStrokeStyle(style));
	}
	static jlong canvas_triangle_get_stroke_style_const(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasTriangle(self).getStrokeStyleConst());
	}
	static jlong canvas_triangle_get_stroke_style(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasTriangle(self).getStrokeStyle());
	}
	static jlong canvas_triangle_get_stroke_style_1(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasTriangle(self).getStrokeStyle());
	}
	static void canvas_triangle_set_gradient_style(TS_JNI_ARGS, jlong self, jlong style) {
		toCanvasTriangle(self).setGradientStyle(toGradientStyle(style));
	}
	static jlong canvas_triangle_get_gradient_style_const(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasTriangle(self).getGradientStyleConst());
	}
	static jlong canvas_triangle_get_gradient_style(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasTriangle(self).getGradientStyle());
	}
	static jlong canvas_triangle_get_gradient_style_1(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasTriangle(self).getGradientStyle());
	}
	static void canvas_triangle_set_position0(TS_JNI_ARGS, jlong self, jlong position) {
		toCanvasTriangle(self).setPosition0(toVector3f(position));
	}
	static void canvas_triangle_set_position1(TS_JNI_ARGS, jlong self, jlong position) {
		toCanvasTriangle(self).setPosition1(toVector3f(position));
	}
	static void canvas_triangle_set_position2(TS_JNI_ARGS, jlong self, jlong position) {
		toCanvasTriangle(self).setPosition2(toVector3f(position));
	}
	static void canvas_triangle_set_position0_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		toCanvasTriangle(self).setPosition0(x, y, z);
	}
	static void canvas_triangle_set_position1_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		toCanvasTriangle(self).setPosition1(x, y, z);
	}
	static void canvas_triangle_set_position2_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		toCanvasTriangle(self).setPosition2(x, y, z);
	}
	static void canvas_triangle_set_position(TS_JNI_ARGS, jlong self, jlong position_0, jlong position_1, jlong position_2) {
		toCanvasTriangle(self).setPosition(toVector3f(position_0), toVector3f(position_1), toVector3f(position_2));
	}
	static jlong canvas_triangle_get_position0(TS_JNI_ARGS, jlong self) {
		return newVector3f(toCanvasTriangle(self).getPosition0());
	}
	static jlong canvas_triangle_get_position1(TS_JNI_ARGS, jlong self) {
		return newVector3f(toCanvasTriangle(self).getPosition1());
	}
	static jlong canvas_triangle_get_position2(TS_JNI_ARGS, jlong self) {
		return newVector3f(toCanvasTriangle(self).getPosition2());
	}
	static const JNINativeMethod canvas_triangle_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)canvas_triangle_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)canvas_triangle_new_1 },
		{ (char*)"new_2", (char*)"(JF)J", (void*)canvas_triangle_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)canvas_triangle_delete },
		{ (char*)"equal_canvas_element_ptr", (char*)"(JJ)Z", (void*)canvas_triangle_equal_canvas_element_ptr },
		{ (char*)"cast_canvas_element_ptr", (char*)"(J)J", (void*)canvas_triangle_cast_canvas_element_ptr },
		{ (char*)"base_canvas_element_ptr", (char*)"(J)J", (void*)canvas_triangle_base_canvas_element_ptr },
		{ (char*)"set_radius", (char*)"(JF)V", (void*)canvas_triangle_set_radius },
		{ (char*)"get_radius", (char*)"(J)F", (void*)canvas_triangle_get_radius },
		{ (char*)"set_stroke_color", (char*)"(JJ)V", (void*)canvas_triangle_set_stroke_color },
		{ (char*)"get_stroke_color", (char*)"(J)J", (void*)canvas_triangle_get_stroke_color },
		{ (char*)"set_stroke_style", (char*)"(JJ)V", (void*)canvas_triangle_set_stroke_style },
		{ (char*)"get_stroke_style_const", (char*)"(J)J", (void*)canvas_triangle_get_stroke_style_const },
		{ (char*)"get_stroke_style", (char*)"(J)J", (void*)canvas_triangle_get_stroke_style },
		{ (char*)"get_stroke_style_1", (char*)"(J)J", (void*)canvas_triangle_get_stroke_style_1 },
		{ (char*)"set_gradient_style", (char*)"(JJ)V", (void*)canvas_triangle_set_gradient_style },
		{ (char*)"get_gradient_style_const", (char*)"(J)J", (void*)canvas_triangle_get_gradient_style_const },
		{ (char*)"get_gradient_style", (char*)"(J)J", (void*)canvas_triangle_get_gradient_style },
		{ (char*)"get_gradient_style_1", (char*)"(J)J", (void*)canvas_triangle_get_gradient_style_1 },
		{ (char*)"set_position0", (char*)"(JJ)V", (void*)canvas_triangle_set_position0 },
		{ (char*)"set_position1", (char*)"(JJ)V", (void*)canvas_triangle_set_position1 },
		{ (char*)"set_position2", (char*)"(JJ)V", (void*)canvas_triangle_set_position2 },
		{ (char*)"set_position0_1", (char*)"(JFFF)V", (void*)canvas_triangle_set_position0_1 },
		{ (char*)"set_position1_1", (char*)"(JFFF)V", (void*)canvas_triangle_set_position1_1 },
		{ (char*)"set_position2_1", (char*)"(JFFF)V", (void*)canvas_triangle_set_position2_1 },
		{ (char*)"set_position", (char*)"(JJJJ)V", (void*)canvas_triangle_set_position },
		{ (char*)"get_position0", (char*)"(J)J", (void*)canvas_triangle_get_position0 },
		{ (char*)"get_position1", (char*)"(J)J", (void*)canvas_triangle_get_position1 },
		{ (char*)"get_position2", (char*)"(J)J", (void*)canvas_triangle_get_position2 },
	};
	
	// Tellusim::CanvasEllipse
	static jlong canvas_ellipse_new(TS_JNI_ARGS) {
		return newCanvasEllipse();
	}
	static jlong canvas_ellipse_new_1(TS_JNI_ARGS, jlong canvas) {
		return newCanvasEllipse(toCanvas(canvas));
	}
	static jlong canvas_ellipse_new_2(TS_JNI_ARGS, jlong canvas, jfloat radius) {
		return newCanvasEllipse(toCanvas(canvas), radius);
	}
	static void canvas_ellipse_delete(TS_JNI_ARGS, jlong self) {
		delete (CanvasEllipse*)self;
	}
	static jboolean canvas_ellipse_equal_canvas_element_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCanvasEllipse(self).operator==(toCanvasElement(base));
	}
	static jlong canvas_ellipse_cast_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasEllipse(toCanvasElement(self));
	}
	static jlong canvas_ellipse_base_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasElement(toCanvasEllipse(self).getCanvasElement());
	}
	static void canvas_ellipse_set_radius(TS_JNI_ARGS, jlong self, jfloat radius) {
		toCanvasEllipse(self).setRadius(radius);
	}
	static jfloat canvas_ellipse_get_radius(TS_JNI_ARGS, jlong self) {
		return toCanvasEllipse(self).getRadius();
	}
	static void canvas_ellipse_set_texture_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toCanvasEllipse(self).setTextureName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void canvas_ellipse_set_texture_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toCanvasEllipse(self).setTextureName(toString(name));
	}
	static jstring canvas_ellipse_get_texture_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toCanvasEllipse(self).getTextureName().get());
	}
	static void canvas_ellipse_set_stroke_color(TS_JNI_ARGS, jlong self, jlong color) {
		toCanvasEllipse(self).setStrokeColor(toColor(color));
	}
	static jlong canvas_ellipse_get_stroke_color(TS_JNI_ARGS, jlong self) {
		return newColor(toCanvasEllipse(self).getStrokeColor());
	}
	static void canvas_ellipse_set_stroke_style(TS_JNI_ARGS, jlong self, jlong style) {
		toCanvasEllipse(self).setStrokeStyle(toStrokeStyle(style));
	}
	static jlong canvas_ellipse_get_stroke_style_const(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasEllipse(self).getStrokeStyleConst());
	}
	static jlong canvas_ellipse_get_stroke_style(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasEllipse(self).getStrokeStyle());
	}
	static jlong canvas_ellipse_get_stroke_style_1(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasEllipse(self).getStrokeStyle());
	}
	static void canvas_ellipse_set_gradient_style(TS_JNI_ARGS, jlong self, jlong style) {
		toCanvasEllipse(self).setGradientStyle(toGradientStyle(style));
	}
	static jlong canvas_ellipse_get_gradient_style_const(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasEllipse(self).getGradientStyleConst());
	}
	static jlong canvas_ellipse_get_gradient_style(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasEllipse(self).getGradientStyle());
	}
	static jlong canvas_ellipse_get_gradient_style_1(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasEllipse(self).getGradientStyle());
	}
	static void canvas_ellipse_set_position(TS_JNI_ARGS, jlong self, jlong position) {
		toCanvasEllipse(self).setPosition(toVector3f(position));
	}
	static void canvas_ellipse_set_position0(TS_JNI_ARGS, jlong self, jlong position) {
		toCanvasEllipse(self).setPosition0(toVector3f(position));
	}
	static void canvas_ellipse_set_position1(TS_JNI_ARGS, jlong self, jlong position) {
		toCanvasEllipse(self).setPosition1(toVector3f(position));
	}
	static void canvas_ellipse_set_position_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		toCanvasEllipse(self).setPosition(x, y, z);
	}
	static void canvas_ellipse_set_position0_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		toCanvasEllipse(self).setPosition0(x, y, z);
	}
	static void canvas_ellipse_set_position1_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		toCanvasEllipse(self).setPosition1(x, y, z);
	}
	static void canvas_ellipse_set_position_2(TS_JNI_ARGS, jlong self, jlong position_0, jlong position_1) {
		toCanvasEllipse(self).setPosition(toVector3f(position_0), toVector3f(position_1));
	}
	static jlong canvas_ellipse_get_position0(TS_JNI_ARGS, jlong self) {
		return newVector3f(toCanvasEllipse(self).getPosition0());
	}
	static jlong canvas_ellipse_get_position1(TS_JNI_ARGS, jlong self) {
		return newVector3f(toCanvasEllipse(self).getPosition1());
	}
	static void canvas_ellipse_set_tex_coord(TS_JNI_ARGS, jlong self, jlong texcoord) {
		toCanvasEllipse(self).setTexCoord(toRect(texcoord));
	}
	static void canvas_ellipse_set_tex_coord_1(TS_JNI_ARGS, jlong self, jfloat left, jfloat right, jfloat bottom, jfloat top) {
		toCanvasEllipse(self).setTexCoord(left, right, bottom, top);
	}
	static jlong canvas_ellipse_get_tex_coord(TS_JNI_ARGS, jlong self) {
		return newRect(toCanvasEllipse(self).getTexCoord());
	}
	static const JNINativeMethod canvas_ellipse_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)canvas_ellipse_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)canvas_ellipse_new_1 },
		{ (char*)"new_2", (char*)"(JF)J", (void*)canvas_ellipse_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)canvas_ellipse_delete },
		{ (char*)"equal_canvas_element_ptr", (char*)"(JJ)Z", (void*)canvas_ellipse_equal_canvas_element_ptr },
		{ (char*)"cast_canvas_element_ptr", (char*)"(J)J", (void*)canvas_ellipse_cast_canvas_element_ptr },
		{ (char*)"base_canvas_element_ptr", (char*)"(J)J", (void*)canvas_ellipse_base_canvas_element_ptr },
		{ (char*)"set_radius", (char*)"(JF)V", (void*)canvas_ellipse_set_radius },
		{ (char*)"get_radius", (char*)"(J)F", (void*)canvas_ellipse_get_radius },
		{ (char*)"set_texture_name", (char*)"(JLjava/lang/String;)V", (void*)canvas_ellipse_set_texture_name },
		{ (char*)"set_texture_name_1", (char*)"(JJ)V", (void*)canvas_ellipse_set_texture_name_1 },
		{ (char*)"get_texture_name", (char*)"(J)Ljava/lang/String;", (void*)canvas_ellipse_get_texture_name },
		{ (char*)"set_stroke_color", (char*)"(JJ)V", (void*)canvas_ellipse_set_stroke_color },
		{ (char*)"get_stroke_color", (char*)"(J)J", (void*)canvas_ellipse_get_stroke_color },
		{ (char*)"set_stroke_style", (char*)"(JJ)V", (void*)canvas_ellipse_set_stroke_style },
		{ (char*)"get_stroke_style_const", (char*)"(J)J", (void*)canvas_ellipse_get_stroke_style_const },
		{ (char*)"get_stroke_style", (char*)"(J)J", (void*)canvas_ellipse_get_stroke_style },
		{ (char*)"get_stroke_style_1", (char*)"(J)J", (void*)canvas_ellipse_get_stroke_style_1 },
		{ (char*)"set_gradient_style", (char*)"(JJ)V", (void*)canvas_ellipse_set_gradient_style },
		{ (char*)"get_gradient_style_const", (char*)"(J)J", (void*)canvas_ellipse_get_gradient_style_const },
		{ (char*)"get_gradient_style", (char*)"(J)J", (void*)canvas_ellipse_get_gradient_style },
		{ (char*)"get_gradient_style_1", (char*)"(J)J", (void*)canvas_ellipse_get_gradient_style_1 },
		{ (char*)"set_position", (char*)"(JJ)V", (void*)canvas_ellipse_set_position },
		{ (char*)"set_position0", (char*)"(JJ)V", (void*)canvas_ellipse_set_position0 },
		{ (char*)"set_position1", (char*)"(JJ)V", (void*)canvas_ellipse_set_position1 },
		{ (char*)"set_position_1", (char*)"(JFFF)V", (void*)canvas_ellipse_set_position_1 },
		{ (char*)"set_position0_1", (char*)"(JFFF)V", (void*)canvas_ellipse_set_position0_1 },
		{ (char*)"set_position1_1", (char*)"(JFFF)V", (void*)canvas_ellipse_set_position1_1 },
		{ (char*)"set_position_2", (char*)"(JJJ)V", (void*)canvas_ellipse_set_position_2 },
		{ (char*)"get_position0", (char*)"(J)J", (void*)canvas_ellipse_get_position0 },
		{ (char*)"get_position1", (char*)"(J)J", (void*)canvas_ellipse_get_position1 },
		{ (char*)"set_tex_coord", (char*)"(JJ)V", (void*)canvas_ellipse_set_tex_coord },
		{ (char*)"set_tex_coord_1", (char*)"(JFFFF)V", (void*)canvas_ellipse_set_tex_coord_1 },
		{ (char*)"get_tex_coord", (char*)"(J)J", (void*)canvas_ellipse_get_tex_coord },
	};
	
	// Tellusim::CanvasShape
	static jlong canvas_shape_new(TS_JNI_ARGS) {
		return newCanvasShape();
	}
	static jlong canvas_shape_new_1(TS_JNI_ARGS, jlong canvas) {
		return newCanvasShape(toCanvas(canvas));
	}
	static jlong canvas_shape_new_2(TS_JNI_ARGS, jlong canvas, jboolean cubic) {
		return newCanvasShape(toCanvas(canvas), (bool)cubic);
	}
	static void canvas_shape_delete(TS_JNI_ARGS, jlong self) {
		delete (CanvasShape*)self;
	}
	static jboolean canvas_shape_equal_canvas_element_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCanvasShape(self).operator==(toCanvasElement(base));
	}
	static jlong canvas_shape_cast_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasShape(toCanvasElement(self));
	}
	static jlong canvas_shape_base_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasElement(toCanvasShape(self).getCanvasElement());
	}
	static void canvas_shape_set_cubic(TS_JNI_ARGS, jlong self, jboolean cubic) {
		toCanvasShape(self).setCubic((bool)cubic);
	}
	static jboolean canvas_shape_is_cubic(TS_JNI_ARGS, jlong self) {
		return toCanvasShape(self).isCubic();
	}
	static void canvas_shape_set_threshold(TS_JNI_ARGS, jlong self, jfloat threshold) {
		toCanvasShape(self).setThreshold(threshold);
	}
	static jfloat canvas_shape_get_threshold(TS_JNI_ARGS, jlong self) {
		return toCanvasShape(self).getThreshold();
	}
	static void canvas_shape_set_stroke_color(TS_JNI_ARGS, jlong self, jlong color) {
		toCanvasShape(self).setStrokeColor(toColor(color));
	}
	static jlong canvas_shape_get_stroke_color(TS_JNI_ARGS, jlong self) {
		return newColor(toCanvasShape(self).getStrokeColor());
	}
	static void canvas_shape_set_stroke_style(TS_JNI_ARGS, jlong self, jlong style) {
		toCanvasShape(self).setStrokeStyle(toStrokeStyle(style));
	}
	static jlong canvas_shape_get_stroke_style_const(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasShape(self).getStrokeStyleConst());
	}
	static jlong canvas_shape_get_stroke_style(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasShape(self).getStrokeStyle());
	}
	static jlong canvas_shape_get_stroke_style_1(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasShape(self).getStrokeStyle());
	}
	static void canvas_shape_set_gradient_style(TS_JNI_ARGS, jlong self, jlong style) {
		toCanvasShape(self).setGradientStyle(toGradientStyle(style));
	}
	static jlong canvas_shape_get_gradient_style_const(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasShape(self).getGradientStyleConst());
	}
	static jlong canvas_shape_get_gradient_style(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasShape(self).getGradientStyle());
	}
	static jlong canvas_shape_get_gradient_style_1(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toCanvasShape(self).getGradientStyle());
	}
	static jboolean canvas_shape_create_svg(TS_JNI_ARGS, jlong self, jstring src, jfloat scale) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		bool ret_ = toCanvasShape(self).createSVG(src_, scale);
		env->ReleaseStringUTFChars(src, src_);
		return ret_;
	}
	static void canvas_shape_clear_positions(TS_JNI_ARGS, jlong self) {
		toCanvasShape(self).clearPositions();
	}
	static void canvas_shape_set_num_positions(TS_JNI_ARGS, jlong self, jint num_positions) {
		toCanvasShape(self).setNumPositions((uint32_t)num_positions);
	}
	static void canvas_shape_reserve_positions(TS_JNI_ARGS, jlong self, jint num_positions) {
		toCanvasShape(self).reservePositions((uint32_t)num_positions);
	}
	static jint canvas_shape_get_num_positions(TS_JNI_ARGS, jlong self) {
		return toCanvasShape(self).getNumPositions();
	}
	static void canvas_shape_set_positions(TS_JNI_ARGS, jlong self, jlongArray positions) {
		Array<Vector3f> positions_((uint32_t)env->GetArrayLength(positions));
		jlong *positions__ = env->GetLongArrayElements(positions, nullptr);
		for(uint32_t i = 0; i < positions_.size(); i++) positions_[i] = toVector3f(positions__[i]);
		toCanvasShape(self).setPositions(positions_.get(), positions_.size());
		if(positions__) env->ReleaseLongArrayElements(positions, positions__, 0);
	}
	static void canvas_shape_add_positions(TS_JNI_ARGS, jlong self, jlongArray positions) {
		Array<Vector3f> positions_((uint32_t)env->GetArrayLength(positions));
		jlong *positions__ = env->GetLongArrayElements(positions, nullptr);
		for(uint32_t i = 0; i < positions_.size(); i++) positions_[i] = toVector3f(positions__[i]);
		toCanvasShape(self).addPositions(positions_.get(), positions_.size());
		if(positions__) env->ReleaseLongArrayElements(positions, positions__, 0);
	}
	static jlong canvas_shape_get_positions(TS_JNI_ARGS, jlong self) {
		return (jlong)toCanvasShape(self).getPositions();
	}
	static jlong canvas_shape_get_positions_1(TS_JNI_ARGS, jlong self) {
		return (jlong)toCanvasShape(self).getPositions();
	}
	static void canvas_shape_set_position(TS_JNI_ARGS, jlong self, jint index, jlong position) {
		toCanvasShape(self).setPosition((uint32_t)index, toVector3f(position));
	}
	static void canvas_shape_set_position_1(TS_JNI_ARGS, jlong self, jint index, jfloat x, jfloat y, jfloat z) {
		toCanvasShape(self).setPosition((uint32_t)index, x, y, z);
	}
	static jlong canvas_shape_get_position(TS_JNI_ARGS, jlong self, jint index) {
		return newVector3f(toCanvasShape(self).getPosition((uint32_t)index));
	}
	static jlong canvas_shape_get_position_1(TS_JNI_ARGS, jlong self, jint index) {
		return newVector3f(toCanvasShape(self).getPosition((uint32_t)index));
	}
	static jint canvas_shape_add_position(TS_JNI_ARGS, jlong self, jlong position) {
		return toCanvasShape(self).addPosition(toVector2f(position));
	}
	static jint canvas_shape_add_position_1(TS_JNI_ARGS, jlong self, jlong position) {
		return toCanvasShape(self).addPosition(toVector3f(position));
	}
	static jint canvas_shape_add_position_2(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		return toCanvasShape(self).addPosition(x, y, z);
	}
	static void canvas_shape_set_tex_coord(TS_JNI_ARGS, jlong self, jlong texcoord) {
		toCanvasShape(self).setTexCoord(toRect(texcoord));
	}
	static void canvas_shape_set_tex_coord_1(TS_JNI_ARGS, jlong self, jfloat left, jfloat right, jfloat bottom, jfloat top) {
		toCanvasShape(self).setTexCoord(left, right, bottom, top);
	}
	static jlong canvas_shape_get_tex_coord(TS_JNI_ARGS, jlong self) {
		return newRect(toCanvasShape(self).getTexCoord());
	}
	static const JNINativeMethod canvas_shape_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)canvas_shape_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)canvas_shape_new_1 },
		{ (char*)"new_2", (char*)"(JZ)J", (void*)canvas_shape_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)canvas_shape_delete },
		{ (char*)"equal_canvas_element_ptr", (char*)"(JJ)Z", (void*)canvas_shape_equal_canvas_element_ptr },
		{ (char*)"cast_canvas_element_ptr", (char*)"(J)J", (void*)canvas_shape_cast_canvas_element_ptr },
		{ (char*)"base_canvas_element_ptr", (char*)"(J)J", (void*)canvas_shape_base_canvas_element_ptr },
		{ (char*)"set_cubic", (char*)"(JZ)V", (void*)canvas_shape_set_cubic },
		{ (char*)"is_cubic", (char*)"(J)Z", (void*)canvas_shape_is_cubic },
		{ (char*)"set_threshold", (char*)"(JF)V", (void*)canvas_shape_set_threshold },
		{ (char*)"get_threshold", (char*)"(J)F", (void*)canvas_shape_get_threshold },
		{ (char*)"set_stroke_color", (char*)"(JJ)V", (void*)canvas_shape_set_stroke_color },
		{ (char*)"get_stroke_color", (char*)"(J)J", (void*)canvas_shape_get_stroke_color },
		{ (char*)"set_stroke_style", (char*)"(JJ)V", (void*)canvas_shape_set_stroke_style },
		{ (char*)"get_stroke_style_const", (char*)"(J)J", (void*)canvas_shape_get_stroke_style_const },
		{ (char*)"get_stroke_style", (char*)"(J)J", (void*)canvas_shape_get_stroke_style },
		{ (char*)"get_stroke_style_1", (char*)"(J)J", (void*)canvas_shape_get_stroke_style_1 },
		{ (char*)"set_gradient_style", (char*)"(JJ)V", (void*)canvas_shape_set_gradient_style },
		{ (char*)"get_gradient_style_const", (char*)"(J)J", (void*)canvas_shape_get_gradient_style_const },
		{ (char*)"get_gradient_style", (char*)"(J)J", (void*)canvas_shape_get_gradient_style },
		{ (char*)"get_gradient_style_1", (char*)"(J)J", (void*)canvas_shape_get_gradient_style_1 },
		{ (char*)"create_svg", (char*)"(JLjava/lang/String;F)Z", (void*)canvas_shape_create_svg },
		{ (char*)"clear_positions", (char*)"(J)V", (void*)canvas_shape_clear_positions },
		{ (char*)"set_num_positions", (char*)"(JI)V", (void*)canvas_shape_set_num_positions },
		{ (char*)"reserve_positions", (char*)"(JI)V", (void*)canvas_shape_reserve_positions },
		{ (char*)"get_num_positions", (char*)"(J)I", (void*)canvas_shape_get_num_positions },
		{ (char*)"set_positions", (char*)"(J[J)V", (void*)canvas_shape_set_positions },
		{ (char*)"add_positions", (char*)"(J[J)V", (void*)canvas_shape_add_positions },
		{ (char*)"get_positions", (char*)"(J)J", (void*)canvas_shape_get_positions },
		{ (char*)"get_positions_1", (char*)"(J)J", (void*)canvas_shape_get_positions_1 },
		{ (char*)"set_position", (char*)"(JIJ)V", (void*)canvas_shape_set_position },
		{ (char*)"set_position_1", (char*)"(JIFFF)V", (void*)canvas_shape_set_position_1 },
		{ (char*)"get_position", (char*)"(JI)J", (void*)canvas_shape_get_position },
		{ (char*)"get_position_1", (char*)"(JI)J", (void*)canvas_shape_get_position_1 },
		{ (char*)"add_position", (char*)"(JJ)I", (void*)canvas_shape_add_position },
		{ (char*)"add_position_1", (char*)"(JJ)I", (void*)canvas_shape_add_position_1 },
		{ (char*)"add_position_2", (char*)"(JFFF)I", (void*)canvas_shape_add_position_2 },
		{ (char*)"set_tex_coord", (char*)"(JJ)V", (void*)canvas_shape_set_tex_coord },
		{ (char*)"set_tex_coord_1", (char*)"(JFFFF)V", (void*)canvas_shape_set_tex_coord_1 },
		{ (char*)"get_tex_coord", (char*)"(J)J", (void*)canvas_shape_get_tex_coord },
	};
	
	// Tellusim::CanvasStrip
	static jlong canvas_strip_new(TS_JNI_ARGS) {
		return newCanvasStrip();
	}
	static jlong canvas_strip_new_1(TS_JNI_ARGS, jlong canvas) {
		return newCanvasStrip(toCanvas(canvas));
	}
	static jlong canvas_strip_new_2(TS_JNI_ARGS, jlong canvas, jfloat width) {
		return newCanvasStrip(toCanvas(canvas), width);
	}
	static void canvas_strip_delete(TS_JNI_ARGS, jlong self) {
		delete (CanvasStrip*)self;
	}
	static jboolean canvas_strip_equal_canvas_element_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toCanvasStrip(self).operator==(toCanvasElement(base));
	}
	static jlong canvas_strip_cast_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasStrip(toCanvasElement(self));
	}
	static jlong canvas_strip_base_canvas_element_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvasElement(toCanvasStrip(self).getCanvasElement());
	}
	static void canvas_strip_set_width(TS_JNI_ARGS, jlong self, jfloat width) {
		toCanvasStrip(self).setWidth(width);
	}
	static jfloat canvas_strip_get_width(TS_JNI_ARGS, jlong self) {
		return toCanvasStrip(self).getWidth();
	}
	static void canvas_strip_set_offset(TS_JNI_ARGS, jlong self, jfloat offset) {
		toCanvasStrip(self).setOffset(offset);
	}
	static jfloat canvas_strip_get_offset(TS_JNI_ARGS, jlong self) {
		return toCanvasStrip(self).getOffset();
	}
	static void canvas_strip_set_stroke_color(TS_JNI_ARGS, jlong self, jlong color) {
		toCanvasStrip(self).setStrokeColor(toColor(color));
	}
	static jlong canvas_strip_get_stroke_color(TS_JNI_ARGS, jlong self) {
		return newColor(toCanvasStrip(self).getStrokeColor());
	}
	static void canvas_strip_set_stroke_style(TS_JNI_ARGS, jlong self, jlong style) {
		toCanvasStrip(self).setStrokeStyle(toStrokeStyle(style));
	}
	static jlong canvas_strip_get_stroke_style_const(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasStrip(self).getStrokeStyleConst());
	}
	static jlong canvas_strip_get_stroke_style(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasStrip(self).getStrokeStyle());
	}
	static jlong canvas_strip_get_stroke_style_1(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toCanvasStrip(self).getStrokeStyle());
	}
	static void canvas_strip_create_quadratic(TS_JNI_ARGS, jlong self, jlong p0, jlong p1, jlong p2, jfloat threshold) {
		toCanvasStrip(self).createQuadratic(toVector2f(p0), toVector2f(p1), toVector2f(p2), threshold);
	}
	static void canvas_strip_create_quadratic_1(TS_JNI_ARGS, jlong self, jlong p0, jlong p1, jlong p2, jfloat threshold) {
		toCanvasStrip(self).createQuadratic(toVector3f(p0), toVector3f(p1), toVector3f(p2), threshold);
	}
	static void canvas_strip_create_cubic(TS_JNI_ARGS, jlong self, jlong p0, jlong p1, jlong p2, jlong p3, jfloat threshold) {
		toCanvasStrip(self).createCubic(toVector2f(p0), toVector2f(p1), toVector2f(p2), toVector2f(p3), threshold);
	}
	static void canvas_strip_create_cubic_1(TS_JNI_ARGS, jlong self, jlong p0, jlong p1, jlong p2, jlong p3, jfloat threshold) {
		toCanvasStrip(self).createCubic(toVector3f(p0), toVector3f(p1), toVector3f(p2), toVector3f(p3), threshold);
	}
	static void canvas_strip_clear_positions(TS_JNI_ARGS, jlong self) {
		toCanvasStrip(self).clearPositions();
	}
	static void canvas_strip_set_num_positions(TS_JNI_ARGS, jlong self, jint num_positions) {
		toCanvasStrip(self).setNumPositions((uint32_t)num_positions);
	}
	static void canvas_strip_reserve_positions(TS_JNI_ARGS, jlong self, jint num_positions) {
		toCanvasStrip(self).reservePositions((uint32_t)num_positions);
	}
	static jint canvas_strip_get_num_positions(TS_JNI_ARGS, jlong self) {
		return toCanvasStrip(self).getNumPositions();
	}
	static void canvas_strip_set_positions(TS_JNI_ARGS, jlong self, jlongArray positions) {
		Array<Vector3f> positions_((uint32_t)env->GetArrayLength(positions));
		jlong *positions__ = env->GetLongArrayElements(positions, nullptr);
		for(uint32_t i = 0; i < positions_.size(); i++) positions_[i] = toVector3f(positions__[i]);
		toCanvasStrip(self).setPositions(positions_.get(), positions_.size());
		if(positions__) env->ReleaseLongArrayElements(positions, positions__, 0);
	}
	static void canvas_strip_add_positions(TS_JNI_ARGS, jlong self, jlongArray positions) {
		Array<Vector3f> positions_((uint32_t)env->GetArrayLength(positions));
		jlong *positions__ = env->GetLongArrayElements(positions, nullptr);
		for(uint32_t i = 0; i < positions_.size(); i++) positions_[i] = toVector3f(positions__[i]);
		toCanvasStrip(self).addPositions(positions_.get(), positions_.size());
		if(positions__) env->ReleaseLongArrayElements(positions, positions__, 0);
	}
	static jlong canvas_strip_get_positions(TS_JNI_ARGS, jlong self) {
		return (jlong)toCanvasStrip(self).getPositions();
	}
	static jlong canvas_strip_get_positions_1(TS_JNI_ARGS, jlong self) {
		return (jlong)toCanvasStrip(self).getPositions();
	}
	static void canvas_strip_set_position(TS_JNI_ARGS, jlong self, jint index, jlong position) {
		toCanvasStrip(self).setPosition((uint32_t)index, toVector3f(position));
	}
	static void canvas_strip_set_position_1(TS_JNI_ARGS, jlong self, jint index, jfloat x, jfloat y, jfloat z) {
		toCanvasStrip(self).setPosition((uint32_t)index, x, y, z);
	}
	static jlong canvas_strip_get_position(TS_JNI_ARGS, jlong self, jint index) {
		return newVector3f(toCanvasStrip(self).getPosition((uint32_t)index));
	}
	static jlong canvas_strip_get_position_1(TS_JNI_ARGS, jlong self, jint index) {
		return newVector3f(toCanvasStrip(self).getPosition((uint32_t)index));
	}
	static jint canvas_strip_add_position(TS_JNI_ARGS, jlong self, jlong position) {
		return toCanvasStrip(self).addPosition(toVector2f(position));
	}
	static jint canvas_strip_add_position_1(TS_JNI_ARGS, jlong self, jlong position) {
		return toCanvasStrip(self).addPosition(toVector3f(position));
	}
	static jint canvas_strip_add_position_2(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		return toCanvasStrip(self).addPosition(x, y, z);
	}
	static const JNINativeMethod canvas_strip_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)canvas_strip_new },
		{ (char*)"new_1", (char*)"(J)J", (void*)canvas_strip_new_1 },
		{ (char*)"new_2", (char*)"(JF)J", (void*)canvas_strip_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)canvas_strip_delete },
		{ (char*)"equal_canvas_element_ptr", (char*)"(JJ)Z", (void*)canvas_strip_equal_canvas_element_ptr },
		{ (char*)"cast_canvas_element_ptr", (char*)"(J)J", (void*)canvas_strip_cast_canvas_element_ptr },
		{ (char*)"base_canvas_element_ptr", (char*)"(J)J", (void*)canvas_strip_base_canvas_element_ptr },
		{ (char*)"set_width", (char*)"(JF)V", (void*)canvas_strip_set_width },
		{ (char*)"get_width", (char*)"(J)F", (void*)canvas_strip_get_width },
		{ (char*)"set_offset", (char*)"(JF)V", (void*)canvas_strip_set_offset },
		{ (char*)"get_offset", (char*)"(J)F", (void*)canvas_strip_get_offset },
		{ (char*)"set_stroke_color", (char*)"(JJ)V", (void*)canvas_strip_set_stroke_color },
		{ (char*)"get_stroke_color", (char*)"(J)J", (void*)canvas_strip_get_stroke_color },
		{ (char*)"set_stroke_style", (char*)"(JJ)V", (void*)canvas_strip_set_stroke_style },
		{ (char*)"get_stroke_style_const", (char*)"(J)J", (void*)canvas_strip_get_stroke_style_const },
		{ (char*)"get_stroke_style", (char*)"(J)J", (void*)canvas_strip_get_stroke_style },
		{ (char*)"get_stroke_style_1", (char*)"(J)J", (void*)canvas_strip_get_stroke_style_1 },
		{ (char*)"create_quadratic", (char*)"(JJJJF)V", (void*)canvas_strip_create_quadratic },
		{ (char*)"create_quadratic_1", (char*)"(JJJJF)V", (void*)canvas_strip_create_quadratic_1 },
		{ (char*)"create_cubic", (char*)"(JJJJJF)V", (void*)canvas_strip_create_cubic },
		{ (char*)"create_cubic_1", (char*)"(JJJJJF)V", (void*)canvas_strip_create_cubic_1 },
		{ (char*)"clear_positions", (char*)"(J)V", (void*)canvas_strip_clear_positions },
		{ (char*)"set_num_positions", (char*)"(JI)V", (void*)canvas_strip_set_num_positions },
		{ (char*)"reserve_positions", (char*)"(JI)V", (void*)canvas_strip_reserve_positions },
		{ (char*)"get_num_positions", (char*)"(J)I", (void*)canvas_strip_get_num_positions },
		{ (char*)"set_positions", (char*)"(J[J)V", (void*)canvas_strip_set_positions },
		{ (char*)"add_positions", (char*)"(J[J)V", (void*)canvas_strip_add_positions },
		{ (char*)"get_positions", (char*)"(J)J", (void*)canvas_strip_get_positions },
		{ (char*)"get_positions_1", (char*)"(J)J", (void*)canvas_strip_get_positions_1 },
		{ (char*)"set_position", (char*)"(JIJ)V", (void*)canvas_strip_set_position },
		{ (char*)"set_position_1", (char*)"(JIFFF)V", (void*)canvas_strip_set_position_1 },
		{ (char*)"get_position", (char*)"(JI)J", (void*)canvas_strip_get_position },
		{ (char*)"get_position_1", (char*)"(JI)J", (void*)canvas_strip_get_position_1 },
		{ (char*)"add_position", (char*)"(JJ)I", (void*)canvas_strip_add_position },
		{ (char*)"add_position_1", (char*)"(JJ)I", (void*)canvas_strip_add_position_1 },
		{ (char*)"add_position_2", (char*)"(JFFF)I", (void*)canvas_strip_add_position_2 },
	};
	
	// Tellusim::Canvas
	static bool canvas_create_callback_func(const Device device, Canvas canvas, uint32_t scale, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Canvas$CreateCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JJI)Z");
			if(!clazz) TS_LOGF(Error, "canvas_create_callback_func(): can't find \"%s\" class\n", "Canvas$CreateCallback");
			else if(!method_id) TS_LOGF(Error, "canvas_create_callback_func(): can't get \"%s\" method\n", "(JJI)Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id, newDevice(device), newCanvas(canvas), (jint)scale) != 0);
		}
		return false;
	}
	static Canvas::CreateCallback make_canvas_create_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(canvas_create_callback_func);
			ret.setArg3(env);
			ret.setArg4(func);
			return ret;
		}
		return Canvas::CreateCallback();
	}
	static bool canvas_pipeline_callback_func(Pipeline pipeline, Canvas canvas, CanvasElement element, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Canvas$PipelineCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JJJ)Z");
			if(!clazz) TS_LOGF(Error, "canvas_pipeline_callback_func(): can't find \"%s\" class\n", "Canvas$PipelineCallback");
			else if(!method_id) TS_LOGF(Error, "canvas_pipeline_callback_func(): can't get \"%s\" method\n", "(JJJ)Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id, newPipeline(pipeline), newCanvas(canvas), newCanvasElement(element)) != 0);
		}
		return false;
	}
	static Canvas::PipelineCallback make_canvas_pipeline_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(canvas_pipeline_callback_func);
			ret.setArg3(env);
			ret.setArg4(func);
			return ret;
		}
		return Canvas::PipelineCallback();
	}
	static bool canvas_begin_callback_func(Command command, Canvas canvas, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Canvas$BeginCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JJ)Z");
			if(!clazz) TS_LOGF(Error, "canvas_begin_callback_func(): can't find \"%s\" class\n", "Canvas$BeginCallback");
			else if(!method_id) TS_LOGF(Error, "canvas_begin_callback_func(): can't get \"%s\" method\n", "(JJ)Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id, newCommand(command), newCanvas(canvas)) != 0);
		}
		return false;
	}
	static Canvas::BeginCallback make_canvas_begin_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(canvas_begin_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return Canvas::BeginCallback();
	}
	static bool canvas_draw_callback_func(Command command, Canvas canvas, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "Canvas$DrawCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JJ)Z");
			if(!clazz) TS_LOGF(Error, "canvas_draw_callback_func(): can't find \"%s\" class\n", "Canvas$DrawCallback");
			else if(!method_id) TS_LOGF(Error, "canvas_draw_callback_func(): can't get \"%s\" method\n", "(JJ)Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id, newCommand(command), newCanvas(canvas)) != 0);
		}
		return false;
	}
	static Canvas::DrawCallback make_canvas_draw_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(canvas_draw_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return Canvas::DrawCallback();
	}
	
	static jlong canvas_new(TS_JNI_ARGS) {
		return newCanvas();
	}
	static jlong canvas_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Canvas> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toCanvas(parent__[i]);
		jlong ret_ = newCanvas(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void canvas_delete(TS_JNI_ARGS, jlong self) {
		delete (Canvas*)self;
	}
	static jboolean canvas_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toCanvas(self) == toCanvas(ptr));
	}
	static jlong canvas_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newCanvas(toCanvas(self).clonePtr());
	}
	static void canvas_clear_ptr(TS_JNI_ARGS, jlong self) {
		toCanvas(self).clearPtr();
	}
	static void canvas_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toCanvas(self).destroyPtr();
	}
	static void canvas_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toCanvas(self).acquirePtr();
	}
	static void canvas_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toCanvas(self).unacquirePtr();
	}
	static jboolean canvas_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).isValidPtr();
	}
	static jboolean canvas_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).isOwnerPtr();
	}
	static jboolean canvas_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).isConstPtr();
	}
	static jint canvas_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getCountPtr();
	}
	static jlong canvas_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toCanvas(self).getInternalPtr();
	}
	static void canvas_clear(TS_JNI_ARGS, jlong self) {
		toCanvas(self).clear();
	}
	static jboolean canvas_is_created(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).isCreated();
	}
	static jint canvas_get_scale(TS_JNI_ARGS, jlong self, jlong target, jint scale) {
		return toCanvas(self).getScale(toTarget(target), (uint32_t)scale);
	}
	static jboolean canvas_create(TS_JNI_ARGS, jlong self, jlong device, jint color, jint depth, jint multisample, jint scale) {
		return toCanvas(self).create(toDevice(device), (Format)color, (Format)depth, (uint32_t)multisample, (uint32_t)scale);
	}
	static jboolean canvas_create_1(TS_JNI_ARGS, jlong self, jlong device, jlong target, jint scale) {
		return toCanvas(self).create(toDevice(device), toTarget(target), (uint32_t)scale);
	}
	static void canvas_set_pipeline_hash(TS_JNI_ARGS, jlong self, jint hash) {
		toCanvas(self).setPipelineHash((uint32_t)hash);
	}
	static jint canvas_get_pipeline_hash(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getPipelineHash();
	}
	static jint canvas_get_color_format(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getColorFormat();
	}
	static jint canvas_get_depth_format(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getDepthFormat();
	}
	static jint canvas_get_multisample(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getMultisample();
	}
	static void canvas_set_order(TS_JNI_ARGS, jlong self, jint order) {
		toCanvas(self).setOrder(order);
	}
	static jint canvas_get_order(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getOrder();
	}
	static void canvas_set_enabled(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toCanvas(self).setEnabled((bool)enabled);
	}
	static jboolean canvas_is_enabled(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).isEnabled();
	}
	static void canvas_set_viewport(TS_JNI_ARGS, jlong self, jlong viewport) {
		toCanvas(self).setViewport(toViewport(viewport));
	}
	static void canvas_set_viewport_1(TS_JNI_ARGS, jlong self, jint width, jint height) {
		toCanvas(self).setViewport((uint32_t)width, (uint32_t)height);
	}
	static void canvas_set_viewport_2(TS_JNI_ARGS, jlong self, jfloat width, jfloat height) {
		toCanvas(self).setViewport(width, height);
	}
	static jlong canvas_get_viewport(TS_JNI_ARGS, jlong self) {
		return newViewport(toCanvas(self).getViewport());
	}
	static jfloat canvas_get_width(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getWidth();
	}
	static jfloat canvas_get_height(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getHeight();
	}
	static void canvas_clear_color(TS_JNI_ARGS, jlong self) {
		toCanvas(self).clearColor();
	}
	static void canvas_set_color(TS_JNI_ARGS, jlong self, jlong color) {
		toCanvas(self).setColor(toColor(color));
	}
	static void canvas_set_color_1(TS_JNI_ARGS, jlong self, jfloat r, jfloat g, jfloat b, jfloat a) {
		toCanvas(self).setColor(r, g, b, a);
	}
	static jlong canvas_get_color(TS_JNI_ARGS, jlong self) {
		return newColor(toCanvas(self).getColor());
	}
	static void canvas_clear_scissor(TS_JNI_ARGS, jlong self) {
		toCanvas(self).clearScissor();
	}
	static void canvas_set_scissor(TS_JNI_ARGS, jlong self, jlong scissor) {
		toCanvas(self).setScissor(toRect(scissor));
	}
	static jlong canvas_get_scissor(TS_JNI_ARGS, jlong self) {
		return newRect(toCanvas(self).getScissor());
	}
	static void canvas_clear_transform(TS_JNI_ARGS, jlong self) {
		toCanvas(self).clearTransform();
	}
	static void canvas_set_transform(TS_JNI_ARGS, jlong self, jlong transform) {
		toCanvas(self).setTransform(toMatrix4x4f(transform));
	}
	static jlong canvas_get_transform(TS_JNI_ARGS, jlong self) {
		return newMatrix4x4f(toCanvas(self).getTransform());
	}
	static jint canvas_set_parent(TS_JNI_ARGS, jlong self, jlong parent) {
		return toCanvas(self).setParent(toCanvas(parent));
	}
	static jlong canvas_get_parent(TS_JNI_ARGS, jlong self) {
		return newCanvas(toCanvas(self).getParent());
	}
	static jlong canvas_get_parent_1(TS_JNI_ARGS, jlong self) {
		return newCanvas(toCanvas(self).getParent());
	}
	static jint canvas_add_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toCanvas(self).addChild(toCanvas(child));
	}
	static jboolean canvas_remove_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toCanvas(self).removeChild(toCanvas(child));
	}
	static jboolean canvas_raise_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toCanvas(self).raiseChild(toCanvas(child));
	}
	static jboolean canvas_lower_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toCanvas(self).lowerChild(toCanvas(child));
	}
	static void canvas_release_children(TS_JNI_ARGS, jlong self) {
		toCanvas(self).releaseChildren();
	}
	static jint canvas_find_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toCanvas(self).findChild(toCanvas(child));
	}
	static jboolean canvas_is_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toCanvas(self).isChild(toCanvas(child));
	}
	static jint canvas_get_num_children(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getNumChildren();
	}
	static jlong canvas_get_child(TS_JNI_ARGS, jlong self, jint index) {
		return newCanvas(toCanvas(self).getChild((uint32_t)index));
	}
	static jlong canvas_get_child_1(TS_JNI_ARGS, jlong self, jint index) {
		return newCanvas(toCanvas(self).getChild((uint32_t)index));
	}
	static jint canvas_add_element(TS_JNI_ARGS, jlong self, jlong element) {
		return toCanvas(self).addElement(toCanvasElement(element));
	}
	static jboolean canvas_remove_element(TS_JNI_ARGS, jlong self, jlong element) {
		return toCanvas(self).removeElement(toCanvasElement(element));
	}
	static jboolean canvas_raise_element(TS_JNI_ARGS, jlong self, jlong element) {
		return toCanvas(self).raiseElement(toCanvasElement(element));
	}
	static jboolean canvas_lower_element(TS_JNI_ARGS, jlong self, jlong element) {
		return toCanvas(self).lowerElement(toCanvasElement(element));
	}
	static jint canvas_find_element(TS_JNI_ARGS, jlong self, jlong element) {
		return toCanvas(self).findElement(toCanvasElement(element));
	}
	static jboolean canvas_is_element(TS_JNI_ARGS, jlong self, jlong element) {
		return toCanvas(self).isElement(toCanvasElement(element));
	}
	static jint canvas_get_num_elements(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getNumElements();
	}
	static jlong canvas_get_element(TS_JNI_ARGS, jlong self, jint index) {
		return newCanvasElement(toCanvas(self).getElement((uint32_t)index));
	}
	static jlong canvas_get_element_1(TS_JNI_ARGS, jlong self, jint index) {
		return newCanvasElement(toCanvas(self).getElement((uint32_t)index));
	}
	static jboolean canvas_is_font(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toCanvas(self).isFont(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean canvas_add_font(TS_JNI_ARGS, jlong self, jstring name, jlong stream) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toCanvas(self).addFont(name_, toStream(stream));
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void canvas_remove_font(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toCanvas(self).removeFont(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jlong canvas_get_font(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Font ret_ = toCanvas(self).getFont(name_);
		env->ReleaseStringUTFChars(name, name_);
		return newFont(ret_);
	}
	static jboolean canvas_is_texture(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toCanvas(self).isTexture(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean canvas_add_texture(TS_JNI_ARGS, jlong self, jstring name, jlong stream) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toCanvas(self).addTexture(name_, toStream(stream));
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean canvas_add_texture_1(TS_JNI_ARGS, jlong self, jstring name, jlong texture) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toCanvas(self).addTexture(name_, toTexture(texture));
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static void canvas_remove_texture(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toCanvas(self).removeTexture(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static jlong canvas_get_texture(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Texture ret_ = toCanvas(self).getTexture(name_);
		env->ReleaseStringUTFChars(name, name_);
		return newTexture(ret_);
	}
	static void canvas_set_depth_mask(TS_JNI_ARGS, jlong self, jint mask) {
		toCanvas(self).setDepthMask((Pipeline::DepthMask)mask);
	}
	static jint canvas_get_depth_mask(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getDepthMask();
	}
	static void canvas_set_depth_func(TS_JNI_ARGS, jlong self, jint func) {
		toCanvas(self).setDepthFunc((Pipeline::DepthFunc)func);
	}
	static jint canvas_get_depth_func(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getDepthFunc();
	}
	static void canvas_draw(TS_JNI_ARGS, jlong self, jlong command, jlong target) {
		toCanvas(self).draw(toCommand(command), toTarget(target));
	}
	static void canvas_draw_1(TS_JNI_ARGS, jlong self, jlong command) {
		toCanvas(self).draw(toCommand(command));
	}
	static void canvas_set_create_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toCanvas(self).setCreateCallback(make_canvas_create_callback(env, func));
	}
	static void canvas_set_pipeline_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toCanvas(self).setPipelineCallback(make_canvas_pipeline_callback(env, func));
	}
	static void canvas_set_begin_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toCanvas(self).setBeginCallback(make_canvas_begin_callback(env, func));
	}
	static void canvas_set_draw_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toCanvas(self).setDrawCallback(make_canvas_draw_callback(env, func));
	}
	static jint canvas_get_num_draw_pipelines(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getNumDrawPipelines();
	}
	static jint canvas_get_num_draw_elements(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getNumDrawElements();
	}
	static jint canvas_get_num_draw_commands(TS_JNI_ARGS, jlong self) {
		return toCanvas(self).getNumDrawCommands();
	}
	static jlong canvas_get_rect(TS_JNI_ARGS, jlong self) {
		return newRect(toCanvas(self).getRect());
	}
	static const JNINativeMethod canvas_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)canvas_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)canvas_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)canvas_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)canvas_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)canvas_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)canvas_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)canvas_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)canvas_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)canvas_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)canvas_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)canvas_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)canvas_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)canvas_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)canvas_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)canvas_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)canvas_is_created },
		{ (char*)"get_scale", (char*)"(JJI)I", (void*)canvas_get_scale },
		{ (char*)"create_", (char*)"(JJIIII)Z", (void*)canvas_create },
		{ (char*)"create_1", (char*)"(JJJI)Z", (void*)canvas_create_1 },
		{ (char*)"set_pipeline_hash", (char*)"(JI)V", (void*)canvas_set_pipeline_hash },
		{ (char*)"get_pipeline_hash", (char*)"(J)I", (void*)canvas_get_pipeline_hash },
		{ (char*)"get_color_format", (char*)"(J)I", (void*)canvas_get_color_format },
		{ (char*)"get_depth_format", (char*)"(J)I", (void*)canvas_get_depth_format },
		{ (char*)"get_multisample", (char*)"(J)I", (void*)canvas_get_multisample },
		{ (char*)"set_order", (char*)"(JI)V", (void*)canvas_set_order },
		{ (char*)"get_order", (char*)"(J)I", (void*)canvas_get_order },
		{ (char*)"set_enabled", (char*)"(JZ)V", (void*)canvas_set_enabled },
		{ (char*)"is_enabled", (char*)"(J)Z", (void*)canvas_is_enabled },
		{ (char*)"set_viewport", (char*)"(JJ)V", (void*)canvas_set_viewport },
		{ (char*)"set_viewport_1", (char*)"(JII)V", (void*)canvas_set_viewport_1 },
		{ (char*)"set_viewport_2", (char*)"(JFF)V", (void*)canvas_set_viewport_2 },
		{ (char*)"get_viewport", (char*)"(J)J", (void*)canvas_get_viewport },
		{ (char*)"get_width", (char*)"(J)F", (void*)canvas_get_width },
		{ (char*)"get_height", (char*)"(J)F", (void*)canvas_get_height },
		{ (char*)"clear_color", (char*)"(J)V", (void*)canvas_clear_color },
		{ (char*)"set_color", (char*)"(JJ)V", (void*)canvas_set_color },
		{ (char*)"set_color_1", (char*)"(JFFFF)V", (void*)canvas_set_color_1 },
		{ (char*)"get_color", (char*)"(J)J", (void*)canvas_get_color },
		{ (char*)"clear_scissor", (char*)"(J)V", (void*)canvas_clear_scissor },
		{ (char*)"set_scissor", (char*)"(JJ)V", (void*)canvas_set_scissor },
		{ (char*)"get_scissor", (char*)"(J)J", (void*)canvas_get_scissor },
		{ (char*)"clear_transform", (char*)"(J)V", (void*)canvas_clear_transform },
		{ (char*)"set_transform", (char*)"(JJ)V", (void*)canvas_set_transform },
		{ (char*)"get_transform", (char*)"(J)J", (void*)canvas_get_transform },
		{ (char*)"set_parent", (char*)"(JJ)I", (void*)canvas_set_parent },
		{ (char*)"get_parent", (char*)"(J)J", (void*)canvas_get_parent },
		{ (char*)"get_parent_1", (char*)"(J)J", (void*)canvas_get_parent_1 },
		{ (char*)"add_child", (char*)"(JJ)I", (void*)canvas_add_child },
		{ (char*)"remove_child", (char*)"(JJ)Z", (void*)canvas_remove_child },
		{ (char*)"raise_child", (char*)"(JJ)Z", (void*)canvas_raise_child },
		{ (char*)"lower_child", (char*)"(JJ)Z", (void*)canvas_lower_child },
		{ (char*)"release_children", (char*)"(J)V", (void*)canvas_release_children },
		{ (char*)"find_child", (char*)"(JJ)I", (void*)canvas_find_child },
		{ (char*)"is_child", (char*)"(JJ)Z", (void*)canvas_is_child },
		{ (char*)"get_num_children", (char*)"(J)I", (void*)canvas_get_num_children },
		{ (char*)"get_child", (char*)"(JI)J", (void*)canvas_get_child },
		{ (char*)"get_child_1", (char*)"(JI)J", (void*)canvas_get_child_1 },
		{ (char*)"add_element", (char*)"(JJ)I", (void*)canvas_add_element },
		{ (char*)"remove_element", (char*)"(JJ)Z", (void*)canvas_remove_element },
		{ (char*)"raise_element", (char*)"(JJ)Z", (void*)canvas_raise_element },
		{ (char*)"lower_element", (char*)"(JJ)Z", (void*)canvas_lower_element },
		{ (char*)"find_element", (char*)"(JJ)I", (void*)canvas_find_element },
		{ (char*)"is_element", (char*)"(JJ)Z", (void*)canvas_is_element },
		{ (char*)"get_num_elements", (char*)"(J)I", (void*)canvas_get_num_elements },
		{ (char*)"get_element", (char*)"(JI)J", (void*)canvas_get_element },
		{ (char*)"get_element_1", (char*)"(JI)J", (void*)canvas_get_element_1 },
		{ (char*)"is_font", (char*)"(JLjava/lang/String;)Z", (void*)canvas_is_font },
		{ (char*)"add_font", (char*)"(JLjava/lang/String;J)Z", (void*)canvas_add_font },
		{ (char*)"remove_font", (char*)"(JLjava/lang/String;)V", (void*)canvas_remove_font },
		{ (char*)"get_font", (char*)"(JLjava/lang/String;)J", (void*)canvas_get_font },
		{ (char*)"is_texture", (char*)"(JLjava/lang/String;)Z", (void*)canvas_is_texture },
		{ (char*)"add_texture", (char*)"(JLjava/lang/String;J)Z", (void*)canvas_add_texture },
		{ (char*)"add_texture_1", (char*)"(JLjava/lang/String;J)Z", (void*)canvas_add_texture_1 },
		{ (char*)"remove_texture", (char*)"(JLjava/lang/String;)V", (void*)canvas_remove_texture },
		{ (char*)"get_texture", (char*)"(JLjava/lang/String;)J", (void*)canvas_get_texture },
		{ (char*)"set_depth_mask", (char*)"(JI)V", (void*)canvas_set_depth_mask },
		{ (char*)"get_depth_mask", (char*)"(J)I", (void*)canvas_get_depth_mask },
		{ (char*)"set_depth_func", (char*)"(JI)V", (void*)canvas_set_depth_func },
		{ (char*)"get_depth_func", (char*)"(J)I", (void*)canvas_get_depth_func },
		{ (char*)"draw_", (char*)"(JJJ)V", (void*)canvas_draw },
		{ (char*)"draw_1", (char*)"(JJ)V", (void*)canvas_draw_1 },
		{ (char*)"set_create_callback", (char*)"(JL" TS_JNI_PREFIX "Canvas$CreateCallback;)V", (void*)canvas_set_create_callback },
		{ (char*)"set_pipeline_callback", (char*)"(JL" TS_JNI_PREFIX "Canvas$PipelineCallback;)V", (void*)canvas_set_pipeline_callback },
		{ (char*)"set_begin_callback", (char*)"(JL" TS_JNI_PREFIX "Canvas$BeginCallback;)V", (void*)canvas_set_begin_callback },
		{ (char*)"set_draw_callback", (char*)"(JL" TS_JNI_PREFIX "Canvas$DrawCallback;)V", (void*)canvas_set_draw_callback },
		{ (char*)"get_num_draw_pipelines", (char*)"(J)I", (void*)canvas_get_num_draw_pipelines },
		{ (char*)"get_num_draw_elements", (char*)"(J)I", (void*)canvas_get_num_draw_elements },
		{ (char*)"get_num_draw_commands", (char*)"(J)I", (void*)canvas_get_num_draw_commands },
		{ (char*)"get_rect", (char*)"(J)J", (void*)canvas_get_rect },
	};
	
	// Tellusim::Control
	static jlong control_new(TS_JNI_ARGS) {
		return newControl();
	}
	static jlong control_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControl(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_new_2(TS_JNI_ARGS, jlongArray parent, jfloat width, jfloat height) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControl(parent_.get(), width, height);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_delete(TS_JNI_ARGS, jlong self) {
		delete (Control*)self;
	}
	static jboolean control_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toControl(self) == toControl(ptr));
	}
	static jlong control_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newControl(toControl(self).clonePtr());
	}
	static void control_clear_ptr(TS_JNI_ARGS, jlong self) {
		toControl(self).clearPtr();
	}
	static void control_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toControl(self).destroyPtr();
	}
	static void control_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toControl(self).acquirePtr();
	}
	static void control_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toControl(self).unacquirePtr();
	}
	static jboolean control_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toControl(self).isValidPtr();
	}
	static jboolean control_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toControl(self).isOwnerPtr();
	}
	static jboolean control_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toControl(self).isConstPtr();
	}
	static jint control_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toControl(self).getCountPtr();
	}
	static jlong control_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toControl(self).getInternalPtr();
	}
	static jint control_get_type(TS_JNI_ARGS, jlong self) {
		return toControl(self).getType();
	}
	static jstring control_get_type_name(TS_JNI_ARGS, jint type) {
		return env->NewStringUTF(Control::getTypeName((Control::Type)type));
	}
	static jstring control_get_type_name_1(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControl(self).getTypeName());
	}
	static jboolean control_is_unknown(TS_JNI_ARGS, jlong self) {
		return toControl(self).isUnknown();
	}
	static jboolean control_is_root(TS_JNI_ARGS, jlong self) {
		return toControl(self).isRoot();
	}
	static jboolean control_is_text(TS_JNI_ARGS, jlong self) {
		return toControl(self).isText();
	}
	static jboolean control_is_rect(TS_JNI_ARGS, jlong self) {
		return toControl(self).isRect();
	}
	static jboolean control_is_grid(TS_JNI_ARGS, jlong self) {
		return toControl(self).isGrid();
	}
	static jboolean control_is_group(TS_JNI_ARGS, jlong self) {
		return toControl(self).isGroup();
	}
	static jboolean control_is_panel(TS_JNI_ARGS, jlong self) {
		return toControl(self).isPanel();
	}
	static jboolean control_is_dialog(TS_JNI_ARGS, jlong self) {
		return toControl(self).isDialog();
	}
	static jboolean control_is_window(TS_JNI_ARGS, jlong self) {
		return toControl(self).isWindow();
	}
	static jboolean control_is_check(TS_JNI_ARGS, jlong self) {
		return toControl(self).isCheck();
	}
	static jboolean control_is_combo(TS_JNI_ARGS, jlong self) {
		return toControl(self).isCombo();
	}
	static jboolean control_is_button(TS_JNI_ARGS, jlong self) {
		return toControl(self).isButton();
	}
	static jboolean control_is_slider(TS_JNI_ARGS, jlong self) {
		return toControl(self).isSlider();
	}
	static jboolean control_is_scroll(TS_JNI_ARGS, jlong self) {
		return toControl(self).isScroll();
	}
	static jboolean control_is_split(TS_JNI_ARGS, jlong self) {
		return toControl(self).isSplit();
	}
	static jboolean control_is_area(TS_JNI_ARGS, jlong self) {
		return toControl(self).isArea();
	}
	static jboolean control_is_tree(TS_JNI_ARGS, jlong self) {
		return toControl(self).isTree();
	}
	static jboolean control_is_edit(TS_JNI_ARGS, jlong self) {
		return toControl(self).isEdit();
	}
	static void control_set_align(TS_JNI_ARGS, jlong self, jint align) {
		toControl(self).setAlign((Control::Align)align);
	}
	static jint control_get_align(TS_JNI_ARGS, jlong self) {
		return toControl(self).getAlign();
	}
	static jboolean control_has_align(TS_JNI_ARGS, jlong self, jint align) {
		return toControl(self).hasAlign((Control::Align)align);
	}
	static jboolean control_has_aligns(TS_JNI_ARGS, jlong self, jint aligns) {
		return toControl(self).hasAligns((Control::Align)aligns);
	}
	static jboolean control_is_spacer(TS_JNI_ARGS, jlong self) {
		return toControl(self).isSpacer();
	}
	static void control_set_enabled(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toControl(self).setEnabled((bool)enabled);
	}
	static jboolean control_is_enabled(TS_JNI_ARGS, jlong self) {
		return toControl(self).isEnabled();
	}
	static jboolean control_was_enabled(TS_JNI_ARGS, jlong self) {
		return toControl(self).wasEnabled();
	}
	static jboolean control_was_updated(TS_JNI_ARGS, jlong self) {
		return toControl(self).wasUpdated();
	}
	static void control_set_disabled(TS_JNI_ARGS, jlong self, jboolean disabled) {
		toControl(self).setDisabled((bool)disabled);
	}
	static jboolean control_is_disabled(TS_JNI_ARGS, jlong self) {
		return toControl(self).isDisabled();
	}
	static jlong control_get_canvas(TS_JNI_ARGS, jlong self) {
		return newCanvas(toControl(self).getCanvas());
	}
	static jlong control_get_root(TS_JNI_ARGS, jlong self) {
		return newControlRoot(toControl(self).getRoot());
	}
	static jlong control_get_root_1(TS_JNI_ARGS, jlong self) {
		return newControlRoot(toControl(self).getRoot());
	}
	static jlong control_get_panel(TS_JNI_ARGS, jlong self) {
		return newControlPanel(toControl(self).getPanel());
	}
	static jlong control_get_panel_1(TS_JNI_ARGS, jlong self) {
		return newControlPanel(toControl(self).getPanel());
	}
	static jint control_set_parent(TS_JNI_ARGS, jlong self, jlong parent) {
		return toControl(self).setParent(toControl(parent));
	}
	static jlong control_get_parent(TS_JNI_ARGS, jlong self) {
		return newControl(toControl(self).getParent());
	}
	static jlong control_get_parent_1(TS_JNI_ARGS, jlong self) {
		return newControl(toControl(self).getParent());
	}
	static jboolean control_is_parent_enabled(TS_JNI_ARGS, jlong self) {
		return toControl(self).isParentEnabled();
	}
	static jboolean control_is_parent_disabled(TS_JNI_ARGS, jlong self) {
		return toControl(self).isParentDisabled();
	}
	static jint control_add_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toControl(self).addChild(toControl(child));
	}
	static jboolean control_remove_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toControl(self).removeChild(toControl(child));
	}
	static jboolean control_raise_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toControl(self).raiseChild(toControl(child));
	}
	static jboolean control_lower_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toControl(self).lowerChild(toControl(child));
	}
	static void control_release_children(TS_JNI_ARGS, jlong self) {
		toControl(self).releaseChildren();
	}
	static jint control_find_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toControl(self).findChild(toControl(child));
	}
	static jboolean control_is_child(TS_JNI_ARGS, jlong self, jlong child) {
		return toControl(self).isChild(toControl(child));
	}
	static jint control_get_num_children(TS_JNI_ARGS, jlong self) {
		return toControl(self).getNumChildren();
	}
	static jlong control_get_child(TS_JNI_ARGS, jlong self, jint index) {
		return newControl(toControl(self).getChild((uint32_t)index));
	}
	static jlong control_get_child_1(TS_JNI_ARGS, jlong self, jint index) {
		return newControl(toControl(self).getChild((uint32_t)index));
	}
	static void control_set_size(TS_JNI_ARGS, jlong self, jlong size) {
		toControl(self).setSize(toVector2f(size));
	}
	static void control_set_size_1(TS_JNI_ARGS, jlong self, jfloat width, jfloat height) {
		toControl(self).setSize(width, height);
	}
	static jlong control_get_size(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControl(self).getSize());
	}
	static jfloat control_get_width(TS_JNI_ARGS, jlong self) {
		return toControl(self).getWidth();
	}
	static jfloat control_get_height(TS_JNI_ARGS, jlong self) {
		return toControl(self).getHeight();
	}
	static void control_set_position(TS_JNI_ARGS, jlong self, jlong position) {
		toControl(self).setPosition(toVector3f(position));
	}
	static void control_set_position_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		toControl(self).setPosition(x, y, z);
	}
	static jlong control_get_position(TS_JNI_ARGS, jlong self) {
		return newVector3f(toControl(self).getPosition());
	}
	static jfloat control_get_position_x(TS_JNI_ARGS, jlong self) {
		return toControl(self).getPositionX();
	}
	static jfloat control_get_position_y(TS_JNI_ARGS, jlong self) {
		return toControl(self).getPositionY();
	}
	static void control_set_offset(TS_JNI_ARGS, jlong self, jlong offset) {
		toControl(self).setOffset(toVector3f(offset));
	}
	static void control_set_offset_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jfloat z) {
		toControl(self).setOffset(x, y, z);
	}
	static jlong control_get_offset(TS_JNI_ARGS, jlong self) {
		return newVector3f(toControl(self).getOffset());
	}
	static jfloat control_get_offset_x(TS_JNI_ARGS, jlong self) {
		return toControl(self).getOffsetX();
	}
	static jfloat control_get_offset_y(TS_JNI_ARGS, jlong self) {
		return toControl(self).getOffsetY();
	}
	static void control_set_margin(TS_JNI_ARGS, jlong self, jfloat value) {
		toControl(self).setMargin(value);
	}
	static void control_set_margin_1(TS_JNI_ARGS, jlong self, jfloat horizontal, jfloat vertical) {
		toControl(self).setMargin(horizontal, vertical);
	}
	static void control_set_margin_2(TS_JNI_ARGS, jlong self, jfloat left, jfloat right, jfloat bottom, jfloat top) {
		toControl(self).setMargin(left, right, bottom, top);
	}
	static void control_set_margin_3(TS_JNI_ARGS, jlong self, jlong margin) {
		toControl(self).setMargin(toRect(margin));
	}
	static jlong control_get_margin(TS_JNI_ARGS, jlong self) {
		return newRect(toControl(self).getMargin());
	}
	static jlong control_get_rect(TS_JNI_ARGS, jlong self) {
		return newRect(toControl(self).getRect());
	}
	static jint control_get_state(TS_JNI_ARGS, jlong self) {
		return toControl(self).getState();
	}
	static const JNINativeMethod control_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_new_1 },
		{ (char*)"new_2", (char*)"([JFF)J", (void*)control_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)control_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)control_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)control_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)control_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)control_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)control_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)control_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)control_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)control_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)control_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)control_get_internal_ptr },
		{ (char*)"get_type", (char*)"(J)I", (void*)control_get_type },
		{ (char*)"get_type_name", (char*)"(I)Ljava/lang/String;", (void*)control_get_type_name },
		{ (char*)"get_type_name_1", (char*)"(J)Ljava/lang/String;", (void*)control_get_type_name_1 },
		{ (char*)"is_unknown", (char*)"(J)Z", (void*)control_is_unknown },
		{ (char*)"is_root", (char*)"(J)Z", (void*)control_is_root },
		{ (char*)"is_text", (char*)"(J)Z", (void*)control_is_text },
		{ (char*)"is_rect", (char*)"(J)Z", (void*)control_is_rect },
		{ (char*)"is_grid", (char*)"(J)Z", (void*)control_is_grid },
		{ (char*)"is_group", (char*)"(J)Z", (void*)control_is_group },
		{ (char*)"is_panel", (char*)"(J)Z", (void*)control_is_panel },
		{ (char*)"is_dialog", (char*)"(J)Z", (void*)control_is_dialog },
		{ (char*)"is_window", (char*)"(J)Z", (void*)control_is_window },
		{ (char*)"is_check", (char*)"(J)Z", (void*)control_is_check },
		{ (char*)"is_combo", (char*)"(J)Z", (void*)control_is_combo },
		{ (char*)"is_button", (char*)"(J)Z", (void*)control_is_button },
		{ (char*)"is_slider", (char*)"(J)Z", (void*)control_is_slider },
		{ (char*)"is_scroll", (char*)"(J)Z", (void*)control_is_scroll },
		{ (char*)"is_split", (char*)"(J)Z", (void*)control_is_split },
		{ (char*)"is_area", (char*)"(J)Z", (void*)control_is_area },
		{ (char*)"is_tree", (char*)"(J)Z", (void*)control_is_tree },
		{ (char*)"is_edit", (char*)"(J)Z", (void*)control_is_edit },
		{ (char*)"set_align", (char*)"(JI)V", (void*)control_set_align },
		{ (char*)"get_align", (char*)"(J)I", (void*)control_get_align },
		{ (char*)"has_align", (char*)"(JI)Z", (void*)control_has_align },
		{ (char*)"has_aligns", (char*)"(JI)Z", (void*)control_has_aligns },
		{ (char*)"is_spacer", (char*)"(J)Z", (void*)control_is_spacer },
		{ (char*)"set_enabled", (char*)"(JZ)V", (void*)control_set_enabled },
		{ (char*)"is_enabled", (char*)"(J)Z", (void*)control_is_enabled },
		{ (char*)"was_enabled", (char*)"(J)Z", (void*)control_was_enabled },
		{ (char*)"was_updated", (char*)"(J)Z", (void*)control_was_updated },
		{ (char*)"set_disabled", (char*)"(JZ)V", (void*)control_set_disabled },
		{ (char*)"is_disabled", (char*)"(J)Z", (void*)control_is_disabled },
		{ (char*)"get_canvas", (char*)"(J)J", (void*)control_get_canvas },
		{ (char*)"get_root", (char*)"(J)J", (void*)control_get_root },
		{ (char*)"get_root_1", (char*)"(J)J", (void*)control_get_root_1 },
		{ (char*)"get_panel", (char*)"(J)J", (void*)control_get_panel },
		{ (char*)"get_panel_1", (char*)"(J)J", (void*)control_get_panel_1 },
		{ (char*)"set_parent", (char*)"(JJ)I", (void*)control_set_parent },
		{ (char*)"get_parent", (char*)"(J)J", (void*)control_get_parent },
		{ (char*)"get_parent_1", (char*)"(J)J", (void*)control_get_parent_1 },
		{ (char*)"is_parent_enabled", (char*)"(J)Z", (void*)control_is_parent_enabled },
		{ (char*)"is_parent_disabled", (char*)"(J)Z", (void*)control_is_parent_disabled },
		{ (char*)"add_child", (char*)"(JJ)I", (void*)control_add_child },
		{ (char*)"remove_child", (char*)"(JJ)Z", (void*)control_remove_child },
		{ (char*)"raise_child", (char*)"(JJ)Z", (void*)control_raise_child },
		{ (char*)"lower_child", (char*)"(JJ)Z", (void*)control_lower_child },
		{ (char*)"release_children", (char*)"(J)V", (void*)control_release_children },
		{ (char*)"find_child", (char*)"(JJ)I", (void*)control_find_child },
		{ (char*)"is_child", (char*)"(JJ)Z", (void*)control_is_child },
		{ (char*)"get_num_children", (char*)"(J)I", (void*)control_get_num_children },
		{ (char*)"get_child", (char*)"(JI)J", (void*)control_get_child },
		{ (char*)"get_child_1", (char*)"(JI)J", (void*)control_get_child_1 },
		{ (char*)"set_size", (char*)"(JJ)V", (void*)control_set_size },
		{ (char*)"set_size_1", (char*)"(JFF)V", (void*)control_set_size_1 },
		{ (char*)"get_size", (char*)"(J)J", (void*)control_get_size },
		{ (char*)"get_width", (char*)"(J)F", (void*)control_get_width },
		{ (char*)"get_height", (char*)"(J)F", (void*)control_get_height },
		{ (char*)"set_position", (char*)"(JJ)V", (void*)control_set_position },
		{ (char*)"set_position_1", (char*)"(JFFF)V", (void*)control_set_position_1 },
		{ (char*)"get_position", (char*)"(J)J", (void*)control_get_position },
		{ (char*)"get_position_x", (char*)"(J)F", (void*)control_get_position_x },
		{ (char*)"get_position_y", (char*)"(J)F", (void*)control_get_position_y },
		{ (char*)"set_offset", (char*)"(JJ)V", (void*)control_set_offset },
		{ (char*)"set_offset_1", (char*)"(JFFF)V", (void*)control_set_offset_1 },
		{ (char*)"get_offset", (char*)"(J)J", (void*)control_get_offset },
		{ (char*)"get_offset_x", (char*)"(J)F", (void*)control_get_offset_x },
		{ (char*)"get_offset_y", (char*)"(J)F", (void*)control_get_offset_y },
		{ (char*)"set_margin", (char*)"(JF)V", (void*)control_set_margin },
		{ (char*)"set_margin_1", (char*)"(JFF)V", (void*)control_set_margin_1 },
		{ (char*)"set_margin_2", (char*)"(JFFFF)V", (void*)control_set_margin_2 },
		{ (char*)"set_margin_3", (char*)"(JJ)V", (void*)control_set_margin_3 },
		{ (char*)"get_margin", (char*)"(J)J", (void*)control_get_margin },
		{ (char*)"get_rect", (char*)"(J)J", (void*)control_get_rect },
		{ (char*)"get_state", (char*)"(J)I", (void*)control_get_state },
	};
	
	// Tellusim::ControlRoot
	static void control_root_copy_callback_func(ControlRoot a0, const char *text, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlRoot$CopyCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JLjava/lang/String;)V");
			if(!clazz) TS_LOGF(Error, "control_root_copy_callback_func(): can't find \"%s\" class\n", "ControlRoot$CopyCallback");
			else if(!method_id) TS_LOGF(Error, "control_root_copy_callback_func(): can't get \"%s\" method\n", "(JLjava/lang/String;)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlRoot(a0), (jstring)text);
		}
	}
	static ControlRoot::CopyCallback make_control_root_copy_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_root_copy_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return ControlRoot::CopyCallback();
	}
	static String control_root_paste_callback_func(ControlRoot a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlRoot$PasteCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)Ljava/lang/String;");
			if(!clazz) TS_LOGF(Error, "control_root_paste_callback_func(): can't find \"%s\" class\n", "ControlRoot$PasteCallback");
			else if(!method_id) TS_LOGF(Error, "control_root_paste_callback_func(): can't get \"%s\" method\n", "(J)Ljava/lang/String;");
		}
		if(method_id) {
			jstring ret = (jstring)env->CallObjectMethod(func, method_id, newControlRoot(a0));
			if(ret) {
				const char *s = env->GetStringUTFChars(ret, nullptr);
				String ret_ = String(s);
				env->ReleaseStringUTFChars(ret, s);
				return ret_;
			}
		}
		return String::null;
	}
	static ControlRoot::PasteCallback make_control_root_paste_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_root_paste_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlRoot::PasteCallback();
	}
	
	static jlong control_root_new(TS_JNI_ARGS) {
		return newControlRoot();
	}
	static jlong control_root_new_1(TS_JNI_ARGS, jlong canvas, jboolean blob) {
		return newControlRoot(toCanvas(canvas), (bool)blob);
	}
	static void control_root_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlRoot*)self;
	}
	static jboolean control_root_equal_control_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlRoot(self).operator==(toControl(base));
	}
	static jlong control_root_cast_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControlRoot(toControl(self));
	}
	static jlong control_root_base_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControl(toControlRoot(self).getControl());
	}
	static void control_root_set_viewport(TS_JNI_ARGS, jlong self, jlong viewport) {
		toControlRoot(self).setViewport(toViewport(viewport));
	}
	static void control_root_set_viewport_1(TS_JNI_ARGS, jlong self, jint width, jint height) {
		toControlRoot(self).setViewport((uint32_t)width, (uint32_t)height);
	}
	static void control_root_set_viewport_2(TS_JNI_ARGS, jlong self, jfloat width, jfloat height) {
		toControlRoot(self).setViewport(width, height);
	}
	static jlong control_root_get_viewport(TS_JNI_ARGS, jlong self) {
		return newViewport(toControlRoot(self).getViewport());
	}
	static jstring control_root_get_font_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlRoot(self).getFontName().get());
	}
	static void control_root_set_font_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toControlRoot(self).setFontName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void control_root_set_font_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toControlRoot(self).setFontName(toString(name));
	}
	static jboolean control_root_set_font_size(TS_JNI_ARGS, jlong self, jint size, jboolean update) {
		return toControlRoot(self).setFontSize((uint32_t)size, (bool)update);
	}
	static jint control_root_get_font_size(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getFontSize();
	}
	static jboolean control_root_set_font_scale(TS_JNI_ARGS, jlong self, jint scale, jboolean update) {
		return toControlRoot(self).setFontScale((uint32_t)scale, (bool)update);
	}
	static jint control_root_get_font_scale(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getFontScale();
	}
	static jboolean control_root_set_font_style(TS_JNI_ARGS, jlong self, jlong style, jboolean update) {
		return toControlRoot(self).setFontStyle(toFontStyle(style), (bool)update);
	}
	static jlong control_root_get_font_style(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toControlRoot(self).getFontStyle());
	}
	static jlong control_root_get_font_style_1(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toControlRoot(self).getFontStyle());
	}
	static jstring control_root_get_texture_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlRoot(self).getTextureName().get());
	}
	static jboolean control_root_set_texture_name(TS_JNI_ARGS, jlong self, jstring name, jint width, jint height, jfloat border) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toControlRoot(self).setTextureName(name_, (uint32_t)width, (uint32_t)height, border);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean control_root_set_texture_name_1(TS_JNI_ARGS, jlong self, jlong name, jint width, jint height, jfloat border) {
		return toControlRoot(self).setTextureName(toString(name), (uint32_t)width, (uint32_t)height, border);
	}
	static jfloat control_root_get_texture_width(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getTextureWidth();
	}
	static jfloat control_root_get_texture_height(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getTextureHeight();
	}
	static void control_root_set_text_color(TS_JNI_ARGS, jlong self, jint type, jint state, jlong color) {
		toControlRoot(self).setTextColor((Control::Type)type, (Control::State)state, toColor(color));
	}
	static void control_root_set_text_offset(TS_JNI_ARGS, jlong self, jint type, jint state, jlong offset) {
		toControlRoot(self).setTextOffset((Control::Type)type, (Control::State)state, toVector3f(offset));
	}
	static jlong control_root_get_text_color(TS_JNI_ARGS, jlong self, jint type, jint state) {
		return newColor(toControlRoot(self).getTextColor((Control::Type)type, (Control::State)state));
	}
	static jlong control_root_get_text_offset(TS_JNI_ARGS, jlong self, jint type, jint state) {
		return newVector3f(toControlRoot(self).getTextOffset((Control::Type)type, (Control::State)state));
	}
	static void control_root_set_mesh_color(TS_JNI_ARGS, jlong self, jint mesh, jint state, jlong color) {
		toControlRoot(self).setMeshColor((Control::Mesh)mesh, (Control::State)state, toColor(color));
	}
	static void control_root_set_mesh_region(TS_JNI_ARGS, jlong self, jint mesh, jlong grid, jlong region, jlong border) {
		toControlRoot(self).setMeshRegion((Control::Mesh)mesh, toRect(grid), toRect(region), toVector2f(border));
	}
	static void control_root_set_mesh_regions(TS_JNI_ARGS, jlong self, jint mesh, jlong grid, jlong regions, jlong border) {
		toControlRoot(self).setMeshRegions((Control::Mesh)mesh, toRect(grid), toRect(regions), toVector2f(border));
	}
	static jint control_root_get_mesh_color(TS_JNI_ARGS, jlong self, jint mesh, jint state) {
		return toControlRoot(self).getMeshColor((Control::Mesh)mesh, (Control::State)state);
	}
	static jlong control_root_get_mesh_grid(TS_JNI_ARGS, jlong self, jint mesh) {
		return newRect(toControlRoot(self).getMeshGrid((Control::Mesh)mesh));
	}
	static jlong control_root_get_mesh_margin(TS_JNI_ARGS, jlong self, jint mesh) {
		return newRect(toControlRoot(self).getMeshMargin((Control::Mesh)mesh));
	}
	static jlong control_root_get_mesh_region(TS_JNI_ARGS, jlong self, jint mesh, jint state) {
		return newRect(toControlRoot(self).getMeshRegion((Control::Mesh)mesh, (Control::State)state));
	}
	static void control_root_set_group_radius(TS_JNI_ARGS, jlong self, jfloat radius) {
		toControlRoot(self).setGroupRadius(radius);
	}
	static void control_root_set_group_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlRoot(self).setGroupColor(toColor(color));
	}
	static jfloat control_root_get_group_radius(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getGroupRadius();
	}
	static jlong control_root_get_group_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlRoot(self).getGroupColor());
	}
	static void control_root_set_panel_radius(TS_JNI_ARGS, jlong self, jfloat radius) {
		toControlRoot(self).setPanelRadius(radius);
	}
	static void control_root_set_panel_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlRoot(self).setPanelColor(toColor(color));
	}
	static jfloat control_root_get_panel_radius(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getPanelRadius();
	}
	static jlong control_root_get_panel_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlRoot(self).getPanelColor());
	}
	static void control_root_set_checked_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlRoot(self).setCheckedColor(toColor(color));
	}
	static jlong control_root_get_checked_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlRoot(self).getCheckedColor());
	}
	static void control_root_set_mouse(TS_JNI_ARGS, jlong self, jint x, jint y, jint buttons) {
		toControlRoot(self).setMouse(x, y, (Control::Button)buttons);
	}
	static void control_root_set_mouse_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y, jint buttons) {
		toControlRoot(self).setMouse(x, y, (Control::Button)buttons);
	}
	static jlong control_root_get_mouse(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlRoot(self).getMouse());
	}
	static jint control_root_get_mouse_buttons(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getMouseButtons();
	}
	static jfloat control_root_get_mouse_x(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getMouseX();
	}
	static jfloat control_root_get_mouse_y(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getMouseY();
	}
	static void control_root_set_mouse_axis(TS_JNI_ARGS, jlong self, jint axis, jfloat delta) {
		toControlRoot(self).setMouseAxis((Control::Axis)axis, delta);
	}
	static void control_root_set_mouse_align(TS_JNI_ARGS, jlong self, jint align, jboolean clear) {
		toControlRoot(self).setMouseAlign((Control::Align)align, (bool)clear);
	}
	static jint control_root_get_mouse_align(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getMouseAlign();
	}
	static jboolean control_root_has_mouse_align(TS_JNI_ARGS, jlong self, jint align) {
		return toControlRoot(self).hasMouseAlign((Control::Align)align);
	}
	static jboolean control_root_has_mouse_aligns(TS_JNI_ARGS, jlong self, jint aligns) {
		return toControlRoot(self).hasMouseAligns((Control::Align)aligns);
	}
	static jboolean control_root_set_keyboard_key(TS_JNI_ARGS, jlong self, jint key, jint code, jboolean value) {
		return toControlRoot(self).setKeyboardKey((uint32_t)key, (uint32_t)code, (bool)value);
	}
	static jboolean control_root_get_keyboard_key(TS_JNI_ARGS, jlong self, jint key, jboolean clear) {
		return toControlRoot(self).getKeyboardKey((uint32_t)key, (bool)clear);
	}
	static void control_root_clear_current_control(TS_JNI_ARGS, jlong self) {
		toControlRoot(self).clearCurrentControl();
	}
	static void control_root_set_current_control(TS_JNI_ARGS, jlong self, jlong control, jboolean grab) {
		toControlRoot(self).setCurrentControl(toControl(control), (bool)grab);
	}
	static jlong control_root_get_current_control(TS_JNI_ARGS, jlong self) {
		return newControl(toControlRoot(self).getCurrentControl());
	}
	static jboolean control_root_get_control_grab(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).getControlGrab();
	}
	static void control_root_clear_focused_control(TS_JNI_ARGS, jlong self) {
		toControlRoot(self).clearFocusedControl();
	}
	static void control_root_set_focused_control(TS_JNI_ARGS, jlong self, jlong control) {
		toControlRoot(self).setFocusedControl(toControl(control));
	}
	static jlong control_root_get_focused_control(TS_JNI_ARGS, jlong self) {
		return newControl(toControlRoot(self).getFocusedControl());
	}
	static jboolean control_root_is_focused_control(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).isFocusedControl();
	}
	static void control_root_clear_mouse_control(TS_JNI_ARGS, jlong self) {
		toControlRoot(self).clearMouseControl();
	}
	static void control_root_set_mouse_control(TS_JNI_ARGS, jlong self, jlong control) {
		toControlRoot(self).setMouseControl(toControl(control));
	}
	static jlong control_root_get_mouse_control(TS_JNI_ARGS, jlong self) {
		return newControl(toControlRoot(self).getMouseControl());
	}
	static jboolean control_root_is_mouse_control(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).isMouseControl();
	}
	static void control_root_clear_input_control(TS_JNI_ARGS, jlong self) {
		toControlRoot(self).clearInputControl();
	}
	static void control_root_set_input_control(TS_JNI_ARGS, jlong self, jlong control) {
		toControlRoot(self).setInputControl(toControl(control));
	}
	static jlong control_root_get_input_control(TS_JNI_ARGS, jlong self) {
		return newControl(toControlRoot(self).getInputControl());
	}
	static jboolean control_root_is_input_control(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).isInputControl();
	}
	static void control_root_clear_modal_control(TS_JNI_ARGS, jlong self) {
		toControlRoot(self).clearModalControl();
	}
	static void control_root_set_modal_control(TS_JNI_ARGS, jlong self, jlong control) {
		toControlRoot(self).setModalControl(toControl(control));
	}
	static jlong control_root_get_modal_control(TS_JNI_ARGS, jlong self) {
		return newControl(toControlRoot(self).getModalControl());
	}
	static jboolean control_root_is_modal_control(TS_JNI_ARGS, jlong self) {
		return toControlRoot(self).isModalControl();
	}
	static jboolean control_root_update(TS_JNI_ARGS, jlong self, jint scale, jint order) {
		return toControlRoot(self).update((uint32_t)scale, order);
	}
	static void control_root_set_copy_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlRoot(self).setCopyText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_root_set_copy_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toControlRoot(self).setCopyText(toString(text));
	}
	static jstring control_root_get_paste_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlRoot(self).getPasteText().get());
	}
	static void control_root_set_copy_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlRoot(self).setCopyCallback(make_control_root_copy_callback(env, func));
	}
	static void control_root_set_paste_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlRoot(self).setPasteCallback(make_control_root_paste_callback(env, func));
	}
	static const JNINativeMethod control_root_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_root_new },
		{ (char*)"new_1", (char*)"(JZ)J", (void*)control_root_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_root_delete },
		{ (char*)"equal_control_ptr", (char*)"(JJ)Z", (void*)control_root_equal_control_ptr },
		{ (char*)"cast_control_ptr", (char*)"(J)J", (void*)control_root_cast_control_ptr },
		{ (char*)"base_control_ptr", (char*)"(J)J", (void*)control_root_base_control_ptr },
		{ (char*)"set_viewport", (char*)"(JJ)V", (void*)control_root_set_viewport },
		{ (char*)"set_viewport_1", (char*)"(JII)V", (void*)control_root_set_viewport_1 },
		{ (char*)"set_viewport_2", (char*)"(JFF)V", (void*)control_root_set_viewport_2 },
		{ (char*)"get_viewport", (char*)"(J)J", (void*)control_root_get_viewport },
		{ (char*)"get_font_name", (char*)"(J)Ljava/lang/String;", (void*)control_root_get_font_name },
		{ (char*)"set_font_name", (char*)"(JLjava/lang/String;)V", (void*)control_root_set_font_name },
		{ (char*)"set_font_name_1", (char*)"(JJ)V", (void*)control_root_set_font_name_1 },
		{ (char*)"set_font_size", (char*)"(JIZ)Z", (void*)control_root_set_font_size },
		{ (char*)"get_font_size", (char*)"(J)I", (void*)control_root_get_font_size },
		{ (char*)"set_font_scale", (char*)"(JIZ)Z", (void*)control_root_set_font_scale },
		{ (char*)"get_font_scale", (char*)"(J)I", (void*)control_root_get_font_scale },
		{ (char*)"set_font_style", (char*)"(JJZ)Z", (void*)control_root_set_font_style },
		{ (char*)"get_font_style", (char*)"(J)J", (void*)control_root_get_font_style },
		{ (char*)"get_font_style_1", (char*)"(J)J", (void*)control_root_get_font_style_1 },
		{ (char*)"get_texture_name", (char*)"(J)Ljava/lang/String;", (void*)control_root_get_texture_name },
		{ (char*)"set_texture_name", (char*)"(JLjava/lang/String;IIF)Z", (void*)control_root_set_texture_name },
		{ (char*)"set_texture_name_1", (char*)"(JJIIF)Z", (void*)control_root_set_texture_name_1 },
		{ (char*)"get_texture_width", (char*)"(J)F", (void*)control_root_get_texture_width },
		{ (char*)"get_texture_height", (char*)"(J)F", (void*)control_root_get_texture_height },
		{ (char*)"set_text_color", (char*)"(JIIJ)V", (void*)control_root_set_text_color },
		{ (char*)"set_text_offset", (char*)"(JIIJ)V", (void*)control_root_set_text_offset },
		{ (char*)"get_text_color", (char*)"(JII)J", (void*)control_root_get_text_color },
		{ (char*)"get_text_offset", (char*)"(JII)J", (void*)control_root_get_text_offset },
		{ (char*)"set_mesh_color", (char*)"(JIIJ)V", (void*)control_root_set_mesh_color },
		{ (char*)"set_mesh_region", (char*)"(JIJJJ)V", (void*)control_root_set_mesh_region },
		{ (char*)"set_mesh_regions", (char*)"(JIJJJ)V", (void*)control_root_set_mesh_regions },
		{ (char*)"get_mesh_color", (char*)"(JII)I", (void*)control_root_get_mesh_color },
		{ (char*)"get_mesh_grid", (char*)"(JI)J", (void*)control_root_get_mesh_grid },
		{ (char*)"get_mesh_margin", (char*)"(JI)J", (void*)control_root_get_mesh_margin },
		{ (char*)"get_mesh_region", (char*)"(JII)J", (void*)control_root_get_mesh_region },
		{ (char*)"set_group_radius", (char*)"(JF)V", (void*)control_root_set_group_radius },
		{ (char*)"set_group_color", (char*)"(JJ)V", (void*)control_root_set_group_color },
		{ (char*)"get_group_radius", (char*)"(J)F", (void*)control_root_get_group_radius },
		{ (char*)"get_group_color", (char*)"(J)J", (void*)control_root_get_group_color },
		{ (char*)"set_panel_radius", (char*)"(JF)V", (void*)control_root_set_panel_radius },
		{ (char*)"set_panel_color", (char*)"(JJ)V", (void*)control_root_set_panel_color },
		{ (char*)"get_panel_radius", (char*)"(J)F", (void*)control_root_get_panel_radius },
		{ (char*)"get_panel_color", (char*)"(J)J", (void*)control_root_get_panel_color },
		{ (char*)"set_checked_color", (char*)"(JJ)V", (void*)control_root_set_checked_color },
		{ (char*)"get_checked_color", (char*)"(J)J", (void*)control_root_get_checked_color },
		{ (char*)"set_mouse", (char*)"(JIII)V", (void*)control_root_set_mouse },
		{ (char*)"set_mouse_1", (char*)"(JFFI)V", (void*)control_root_set_mouse_1 },
		{ (char*)"get_mouse", (char*)"(J)J", (void*)control_root_get_mouse },
		{ (char*)"get_mouse_buttons", (char*)"(J)I", (void*)control_root_get_mouse_buttons },
		{ (char*)"get_mouse_x", (char*)"(J)F", (void*)control_root_get_mouse_x },
		{ (char*)"get_mouse_y", (char*)"(J)F", (void*)control_root_get_mouse_y },
		{ (char*)"set_mouse_axis", (char*)"(JIF)V", (void*)control_root_set_mouse_axis },
		{ (char*)"set_mouse_align", (char*)"(JIZ)V", (void*)control_root_set_mouse_align },
		{ (char*)"get_mouse_align", (char*)"(J)I", (void*)control_root_get_mouse_align },
		{ (char*)"has_mouse_align", (char*)"(JI)Z", (void*)control_root_has_mouse_align },
		{ (char*)"has_mouse_aligns", (char*)"(JI)Z", (void*)control_root_has_mouse_aligns },
		{ (char*)"set_keyboard_key", (char*)"(JIIZ)Z", (void*)control_root_set_keyboard_key },
		{ (char*)"get_keyboard_key", (char*)"(JIZ)Z", (void*)control_root_get_keyboard_key },
		{ (char*)"clear_current_control", (char*)"(J)V", (void*)control_root_clear_current_control },
		{ (char*)"set_current_control", (char*)"(JJZ)V", (void*)control_root_set_current_control },
		{ (char*)"get_current_control", (char*)"(J)J", (void*)control_root_get_current_control },
		{ (char*)"get_control_grab", (char*)"(J)Z", (void*)control_root_get_control_grab },
		{ (char*)"clear_focused_control", (char*)"(J)V", (void*)control_root_clear_focused_control },
		{ (char*)"set_focused_control", (char*)"(JJ)V", (void*)control_root_set_focused_control },
		{ (char*)"get_focused_control", (char*)"(J)J", (void*)control_root_get_focused_control },
		{ (char*)"is_focused_control", (char*)"(J)Z", (void*)control_root_is_focused_control },
		{ (char*)"clear_mouse_control", (char*)"(J)V", (void*)control_root_clear_mouse_control },
		{ (char*)"set_mouse_control", (char*)"(JJ)V", (void*)control_root_set_mouse_control },
		{ (char*)"get_mouse_control", (char*)"(J)J", (void*)control_root_get_mouse_control },
		{ (char*)"is_mouse_control", (char*)"(J)Z", (void*)control_root_is_mouse_control },
		{ (char*)"clear_input_control", (char*)"(J)V", (void*)control_root_clear_input_control },
		{ (char*)"set_input_control", (char*)"(JJ)V", (void*)control_root_set_input_control },
		{ (char*)"get_input_control", (char*)"(J)J", (void*)control_root_get_input_control },
		{ (char*)"is_input_control", (char*)"(J)Z", (void*)control_root_is_input_control },
		{ (char*)"clear_modal_control", (char*)"(J)V", (void*)control_root_clear_modal_control },
		{ (char*)"set_modal_control", (char*)"(JJ)V", (void*)control_root_set_modal_control },
		{ (char*)"get_modal_control", (char*)"(J)J", (void*)control_root_get_modal_control },
		{ (char*)"is_modal_control", (char*)"(J)Z", (void*)control_root_is_modal_control },
		{ (char*)"update_", (char*)"(JII)Z", (void*)control_root_update },
		{ (char*)"set_copy_text", (char*)"(JLjava/lang/String;)V", (void*)control_root_set_copy_text },
		{ (char*)"set_copy_text_1", (char*)"(JJ)V", (void*)control_root_set_copy_text_1 },
		{ (char*)"get_paste_text", (char*)"(J)Ljava/lang/String;", (void*)control_root_get_paste_text },
		{ (char*)"set_copy_callback", (char*)"(JL" TS_JNI_PREFIX "ControlRoot$CopyCallback;)V", (void*)control_root_set_copy_callback },
		{ (char*)"set_paste_callback", (char*)"(JL" TS_JNI_PREFIX "ControlRoot$PasteCallback;)V", (void*)control_root_set_paste_callback },
	};
	
	// Tellusim::ControlText
	static jlong control_text_new(TS_JNI_ARGS) {
		return newControlText();
	}
	static jlong control_text_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlText(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_text_new_2(TS_JNI_ARGS, jlongArray parent, jstring text) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlText(parent_.get(), text_);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_text_new_3(TS_JNI_ARGS, jlongArray parent, jlong text) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlText(parent_.get(), toString(text));
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_text_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlText*)self;
	}
	static jboolean control_text_equal_control_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlText(self).operator==(toControl(base));
	}
	static jlong control_text_cast_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControlText(toControl(self));
	}
	static jlong control_text_base_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControl(toControlText(self).getControl());
	}
	static void control_text_set_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toControlText(self).setMode((CanvasElement::Mode)mode);
	}
	static jint control_text_get_mode(TS_JNI_ARGS, jlong self) {
		return toControlText(self).getMode();
	}
	static void control_text_set_pipeline(TS_JNI_ARGS, jlong self, jlong pipeline) {
		toControlText(self).setPipeline(toPipeline(pipeline));
	}
	static void control_text_set_pipeline_1(TS_JNI_ARGS, jlong self, jlong pipeline, jobject func) {
		toControlText(self).setPipeline(toPipeline(pipeline), make_canvas_element_draw_callback(env, func));
	}
	static jlong control_text_get_pipeline(TS_JNI_ARGS, jlong self) {
		return newPipeline(toControlText(self).getPipeline());
	}
	static void control_text_set_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlText(self).setColor(toColor(color));
	}
	static void control_text_set_color_1(TS_JNI_ARGS, jlong self, jfloat r, jfloat g, jfloat b, jfloat a) {
		toControlText(self).setColor(r, g, b, a);
	}
	static jlong control_text_get_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlText(self).getColor());
	}
	static void control_text_set_filter(TS_JNI_ARGS, jlong self, jint filter) {
		toControlText(self).setFilter((Sampler::Filter)filter);
	}
	static jint control_text_get_filter(TS_JNI_ARGS, jlong self) {
		return toControlText(self).getFilter();
	}
	static void control_text_set_anisotropy(TS_JNI_ARGS, jlong self, jint anisotropy) {
		toControlText(self).setAnisotropy((uint32_t)anisotropy);
	}
	static jint control_text_get_anisotropy(TS_JNI_ARGS, jlong self) {
		return toControlText(self).getAnisotropy();
	}
	static void control_text_set_blend(TS_JNI_ARGS, jlong self, jint op, jint src, jint dest) {
		toControlText(self).setBlend((Pipeline::BlendOp)op, (Pipeline::BlendFunc)src, (Pipeline::BlendFunc)dest);
	}
	static jint control_text_get_blend_op(TS_JNI_ARGS, jlong self) {
		return toControlText(self).getBlendOp();
	}
	static jint control_text_get_blend_src_func(TS_JNI_ARGS, jlong self) {
		return toControlText(self).getBlendSrcFunc();
	}
	static jint control_text_get_blend_dest_func(TS_JNI_ARGS, jlong self) {
		return toControlText(self).getBlendDestFunc();
	}
	static void control_text_set_font_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toControlText(self).setFontName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void control_text_set_font_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toControlText(self).setFontName(toString(name));
	}
	static jstring control_text_get_font_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlText(self).getFontName().get());
	}
	static void control_text_set_font_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlText(self).setFontColor(toColor(color));
	}
	static jlong control_text_get_font_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlText(self).getFontColor());
	}
	static jboolean control_text_set_font_size(TS_JNI_ARGS, jlong self, jint size) {
		return toControlText(self).setFontSize((uint32_t)size);
	}
	static jint control_text_get_font_size(TS_JNI_ARGS, jlong self) {
		return toControlText(self).getFontSize();
	}
	static jboolean control_text_set_font_style(TS_JNI_ARGS, jlong self, jlong style) {
		return toControlText(self).setFontStyle(toFontStyle(style));
	}
	static jlong control_text_get_font_style_const(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toControlText(self).getFontStyleConst());
	}
	static jlong control_text_get_font_style(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toControlText(self).getFontStyle());
	}
	static jlong control_text_get_font_style_1(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toControlText(self).getFontStyle());
	}
	static void control_text_set_font_align(TS_JNI_ARGS, jlong self, jint align) {
		toControlText(self).setFontAlign((Control::Align)align);
	}
	static jint control_text_get_font_align(TS_JNI_ARGS, jlong self) {
		return toControlText(self).getFontAlign();
	}
	static jboolean control_text_has_font_align(TS_JNI_ARGS, jlong self, jint align) {
		return toControlText(self).hasFontAlign((Control::Align)align);
	}
	static jboolean control_text_has_font_aligns(TS_JNI_ARGS, jlong self, jint aligns) {
		return toControlText(self).hasFontAligns((Control::Align)aligns);
	}
	static void control_text_set_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlText(self).setText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_text_set_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toControlText(self).setText(toString(text));
	}
	static jstring control_text_get_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlText(self).getText().get());
	}
	static jlong control_text_get_canvas_text(TS_JNI_ARGS, jlong self) {
		return newCanvasText(toControlText(self).getCanvasText());
	}
	static const JNINativeMethod control_text_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_text_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_text_new_1 },
		{ (char*)"new_2", (char*)"([JLjava/lang/String;)J", (void*)control_text_new_2 },
		{ (char*)"new_3", (char*)"([JJ)J", (void*)control_text_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_text_delete },
		{ (char*)"equal_control_ptr", (char*)"(JJ)Z", (void*)control_text_equal_control_ptr },
		{ (char*)"cast_control_ptr", (char*)"(J)J", (void*)control_text_cast_control_ptr },
		{ (char*)"base_control_ptr", (char*)"(J)J", (void*)control_text_base_control_ptr },
		{ (char*)"set_mode", (char*)"(JI)V", (void*)control_text_set_mode },
		{ (char*)"get_mode", (char*)"(J)I", (void*)control_text_get_mode },
		{ (char*)"set_pipeline", (char*)"(JJ)V", (void*)control_text_set_pipeline },
		{ (char*)"set_pipeline_1", (char*)"(JJL" TS_JNI_PREFIX "CanvasElement$DrawCallback;)V", (void*)control_text_set_pipeline_1 },
		{ (char*)"get_pipeline", (char*)"(J)J", (void*)control_text_get_pipeline },
		{ (char*)"set_color", (char*)"(JJ)V", (void*)control_text_set_color },
		{ (char*)"set_color_1", (char*)"(JFFFF)V", (void*)control_text_set_color_1 },
		{ (char*)"get_color", (char*)"(J)J", (void*)control_text_get_color },
		{ (char*)"set_filter", (char*)"(JI)V", (void*)control_text_set_filter },
		{ (char*)"get_filter", (char*)"(J)I", (void*)control_text_get_filter },
		{ (char*)"set_anisotropy", (char*)"(JI)V", (void*)control_text_set_anisotropy },
		{ (char*)"get_anisotropy", (char*)"(J)I", (void*)control_text_get_anisotropy },
		{ (char*)"set_blend", (char*)"(JIII)V", (void*)control_text_set_blend },
		{ (char*)"get_blend_op", (char*)"(J)I", (void*)control_text_get_blend_op },
		{ (char*)"get_blend_src_func", (char*)"(J)I", (void*)control_text_get_blend_src_func },
		{ (char*)"get_blend_dest_func", (char*)"(J)I", (void*)control_text_get_blend_dest_func },
		{ (char*)"set_font_name", (char*)"(JLjava/lang/String;)V", (void*)control_text_set_font_name },
		{ (char*)"set_font_name_1", (char*)"(JJ)V", (void*)control_text_set_font_name_1 },
		{ (char*)"get_font_name", (char*)"(J)Ljava/lang/String;", (void*)control_text_get_font_name },
		{ (char*)"set_font_color", (char*)"(JJ)V", (void*)control_text_set_font_color },
		{ (char*)"get_font_color", (char*)"(J)J", (void*)control_text_get_font_color },
		{ (char*)"set_font_size", (char*)"(JI)Z", (void*)control_text_set_font_size },
		{ (char*)"get_font_size", (char*)"(J)I", (void*)control_text_get_font_size },
		{ (char*)"set_font_style", (char*)"(JJ)Z", (void*)control_text_set_font_style },
		{ (char*)"get_font_style_const", (char*)"(J)J", (void*)control_text_get_font_style_const },
		{ (char*)"get_font_style", (char*)"(J)J", (void*)control_text_get_font_style },
		{ (char*)"get_font_style_1", (char*)"(J)J", (void*)control_text_get_font_style_1 },
		{ (char*)"set_font_align", (char*)"(JI)V", (void*)control_text_set_font_align },
		{ (char*)"get_font_align", (char*)"(J)I", (void*)control_text_get_font_align },
		{ (char*)"has_font_align", (char*)"(JI)Z", (void*)control_text_has_font_align },
		{ (char*)"has_font_aligns", (char*)"(JI)Z", (void*)control_text_has_font_aligns },
		{ (char*)"set_text", (char*)"(JLjava/lang/String;)V", (void*)control_text_set_text },
		{ (char*)"set_text_1", (char*)"(JJ)V", (void*)control_text_set_text_1 },
		{ (char*)"get_text", (char*)"(J)Ljava/lang/String;", (void*)control_text_get_text },
		{ (char*)"get_canvas_text", (char*)"(J)J", (void*)control_text_get_canvas_text },
	};
	
	// Tellusim::ControlRect
	static void control_rect_pressed_callback_func(ControlRect a0, float32_t x, float32_t y, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlRect$PressedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JFF)V");
			if(!clazz) TS_LOGF(Error, "control_rect_pressed_callback_func(): can't find \"%s\" class\n", "ControlRect$PressedCallback");
			else if(!method_id) TS_LOGF(Error, "control_rect_pressed_callback_func(): can't get \"%s\" method\n", "(JFF)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlRect(a0), (jfloat)x, (jfloat)y);
		}
	}
	static ControlRect::PressedCallback make_control_rect_pressed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_rect_pressed_callback_func);
			ret.setArg3(env);
			ret.setArg4(func);
			return ret;
		}
		return ControlRect::PressedCallback();
	}
	static void control_rect_released_callback_func(ControlRect a0, float32_t x, float32_t y, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlRect$ReleasedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JFF)V");
			if(!clazz) TS_LOGF(Error, "control_rect_released_callback_func(): can't find \"%s\" class\n", "ControlRect$ReleasedCallback");
			else if(!method_id) TS_LOGF(Error, "control_rect_released_callback_func(): can't get \"%s\" method\n", "(JFF)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlRect(a0), (jfloat)x, (jfloat)y);
		}
	}
	static ControlRect::ReleasedCallback make_control_rect_released_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_rect_released_callback_func);
			ret.setArg3(env);
			ret.setArg4(func);
			return ret;
		}
		return ControlRect::ReleasedCallback();
	}
	static void control_rect_clicked_callback_func(ControlRect a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlRect$ClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_rect_clicked_callback_func(): can't find \"%s\" class\n", "ControlRect$ClickedCallback");
			else if(!method_id) TS_LOGF(Error, "control_rect_clicked_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlRect(a0));
		}
	}
	static ControlRect::ClickedCallback make_control_rect_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_rect_clicked_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlRect::ClickedCallback();
	}
	
	static jlong control_rect_new(TS_JNI_ARGS) {
		return newControlRect();
	}
	static jlong control_rect_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlRect(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_rect_new_2(TS_JNI_ARGS, jlongArray parent, jlong texture) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlRect(parent_.get(), toTexture(texture));
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_rect_new_3(TS_JNI_ARGS, jlongArray parent, jstring name) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newControlRect(parent_.get(), name_);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong control_rect_new_4(TS_JNI_ARGS, jlongArray parent, jint mode) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlRect(parent_.get(), (CanvasElement::Mode)mode);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_rect_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlRect*)self;
	}
	static jboolean control_rect_equal_control_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlRect(self).operator==(toControl(base));
	}
	static jlong control_rect_cast_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControlRect(toControl(self));
	}
	static jlong control_rect_base_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControl(toControlRect(self).getControl());
	}
	static void control_rect_set_callback(TS_JNI_ARGS, jlong self, jboolean callback) {
		toControlRect(self).setCallback((bool)callback);
	}
	static jboolean control_rect_get_callback(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getCallback();
	}
	static void control_rect_set_fullscreen(TS_JNI_ARGS, jlong self, jboolean fullscreen) {
		toControlRect(self).setFullscreen((bool)fullscreen);
	}
	static jboolean control_rect_is_fullscreen(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).isFullscreen();
	}
	static void control_rect_set_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toControlRect(self).setMode((CanvasElement::Mode)mode);
	}
	static jint control_rect_get_mode(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getMode();
	}
	static void control_rect_set_pipeline(TS_JNI_ARGS, jlong self, jlong pipeline) {
		toControlRect(self).setPipeline(toPipeline(pipeline));
	}
	static void control_rect_set_pipeline_1(TS_JNI_ARGS, jlong self, jlong pipeline, jobject func) {
		toControlRect(self).setPipeline(toPipeline(pipeline), make_canvas_element_draw_callback(env, func));
	}
	static jlong control_rect_get_pipeline(TS_JNI_ARGS, jlong self) {
		return newPipeline(toControlRect(self).getPipeline());
	}
	static void control_rect_set_radius(TS_JNI_ARGS, jlong self, jfloat radius) {
		toControlRect(self).setRadius(radius);
	}
	static jfloat control_rect_get_radius(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getRadius();
	}
	static void control_rect_set_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlRect(self).setColor(toColor(color));
	}
	static void control_rect_set_color_1(TS_JNI_ARGS, jlong self, jfloat r, jfloat g, jfloat b, jfloat a) {
		toControlRect(self).setColor(r, g, b, a);
	}
	static jlong control_rect_get_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlRect(self).getColor());
	}
	static void control_rect_set_stroke_style(TS_JNI_ARGS, jlong self, jlong style) {
		toControlRect(self).setStrokeStyle(toStrokeStyle(style));
	}
	static jlong control_rect_get_stroke_style_const(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toControlRect(self).getStrokeStyleConst());
	}
	static jlong control_rect_get_stroke_style(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toControlRect(self).getStrokeStyle());
	}
	static jlong control_rect_get_stroke_style_1(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toControlRect(self).getStrokeStyle());
	}
	static void control_rect_set_gradient_style(TS_JNI_ARGS, jlong self, jlong style) {
		toControlRect(self).setGradientStyle(toGradientStyle(style));
	}
	static jlong control_rect_get_gradient_style_const(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toControlRect(self).getGradientStyleConst());
	}
	static jlong control_rect_get_gradient_style(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toControlRect(self).getGradientStyle());
	}
	static jlong control_rect_get_gradient_style_1(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toControlRect(self).getGradientStyle());
	}
	static void control_rect_set_mipmap(TS_JNI_ARGS, jlong self, jfloat mipmap) {
		toControlRect(self).setMipmap(mipmap);
	}
	static jfloat control_rect_get_mipmap(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getMipmap();
	}
	static void control_rect_set_filter(TS_JNI_ARGS, jlong self, jint filter) {
		toControlRect(self).setFilter((Sampler::Filter)filter);
	}
	static jint control_rect_get_filter(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getFilter();
	}
	static void control_rect_set_anisotropy(TS_JNI_ARGS, jlong self, jint anisotropy) {
		toControlRect(self).setAnisotropy((uint32_t)anisotropy);
	}
	static jint control_rect_get_anisotropy(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getAnisotropy();
	}
	static void control_rect_set_wrap_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toControlRect(self).setWrapMode((Sampler::WrapMode)mode);
	}
	static jint control_rect_get_wrap_mode(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getWrapMode();
	}
	static void control_rect_set_blend(TS_JNI_ARGS, jlong self, jint op, jint src, jint dest) {
		toControlRect(self).setBlend((Pipeline::BlendOp)op, (Pipeline::BlendFunc)src, (Pipeline::BlendFunc)dest);
	}
	static jint control_rect_get_blend_op(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getBlendOp();
	}
	static jint control_rect_get_blend_src_func(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getBlendSrcFunc();
	}
	static jint control_rect_get_blend_dest_func(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getBlendDestFunc();
	}
	static void control_rect_set_texture(TS_JNI_ARGS, jlong self, jlong texture, jboolean linear) {
		toControlRect(self).setTexture(toTexture(texture), (bool)linear);
	}
	static jlong control_rect_get_texture(TS_JNI_ARGS, jlong self) {
		return newTexture(toControlRect(self).getTexture());
	}
	static jboolean control_rect_get_texture_linear(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getTextureLinear();
	}
	static void control_rect_set_texture_name(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toControlRect(self).setTextureName(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void control_rect_set_texture_name_1(TS_JNI_ARGS, jlong self, jlong name) {
		toControlRect(self).setTextureName(toString(name));
	}
	static jstring control_rect_get_texture_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlRect(self).getTextureName().get());
	}
	static void control_rect_set_texture_scale(TS_JNI_ARGS, jlong self, jfloat scale_x, jfloat scale_y) {
		toControlRect(self).setTextureScale(scale_x, scale_y);
	}
	static jfloat control_rect_get_texture_scale_x(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getTextureScaleX();
	}
	static jfloat control_rect_get_texture_scale_y(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getTextureScaleY();
	}
	static void control_rect_set_texture_flip(TS_JNI_ARGS, jlong self, jboolean flip_x, jboolean flip_y) {
		toControlRect(self).setTextureFlip((bool)flip_x, (bool)flip_y);
	}
	static jboolean control_rect_get_texture_flip_x(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getTextureFlipX();
	}
	static jboolean control_rect_get_texture_flip_y(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getTextureFlipY();
	}
	static void control_rect_set_texture_proj(TS_JNI_ARGS, jlong self, jboolean projection) {
		toControlRect(self).setTextureProj((bool)projection);
	}
	static jboolean control_rect_get_texture_proj(TS_JNI_ARGS, jlong self) {
		return toControlRect(self).getTextureProj();
	}
	static void control_rect_set_tex_coord(TS_JNI_ARGS, jlong self, jlong texcoord) {
		toControlRect(self).setTexCoord(toRect(texcoord));
	}
	static void control_rect_set_tex_coord_1(TS_JNI_ARGS, jlong self, jfloat left, jfloat right, jfloat bottom, jfloat top) {
		toControlRect(self).setTexCoord(left, right, bottom, top);
	}
	static jlong control_rect_get_tex_coord(TS_JNI_ARGS, jlong self) {
		return newRect(toControlRect(self).getTexCoord());
	}
	static void control_rect_set_pressed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlRect(self).setPressedCallback(make_control_rect_pressed_callback(env, func));
	}
	static void control_rect_set_released_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlRect(self).setReleasedCallback(make_control_rect_released_callback(env, func));
	}
	static void control_rect_set_clicked_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlRect(self).setClickedCallback(make_control_rect_clicked_callback(env, func));
	}
	static void control_rect_set_clicked2_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlRect(self).setClicked2Callback(make_control_rect_clicked_callback(env, func));
	}
	static void control_rect_set_clicked_right_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlRect(self).setClickedRightCallback(make_control_rect_clicked_callback(env, func));
	}
	static jlong control_rect_get_canvas_rect(TS_JNI_ARGS, jlong self) {
		return newCanvasRect(toControlRect(self).getCanvasRect());
	}
	static jlong control_rect_get_canvas_mesh(TS_JNI_ARGS, jlong self) {
		return newCanvasMesh(toControlRect(self).getCanvasMesh());
	}
	static const JNINativeMethod control_rect_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_rect_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_rect_new_1 },
		{ (char*)"new_2", (char*)"([JJ)J", (void*)control_rect_new_2 },
		{ (char*)"new_3", (char*)"([JLjava/lang/String;)J", (void*)control_rect_new_3 },
		{ (char*)"new_4", (char*)"([JI)J", (void*)control_rect_new_4 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_rect_delete },
		{ (char*)"equal_control_ptr", (char*)"(JJ)Z", (void*)control_rect_equal_control_ptr },
		{ (char*)"cast_control_ptr", (char*)"(J)J", (void*)control_rect_cast_control_ptr },
		{ (char*)"base_control_ptr", (char*)"(J)J", (void*)control_rect_base_control_ptr },
		{ (char*)"set_callback", (char*)"(JZ)V", (void*)control_rect_set_callback },
		{ (char*)"get_callback", (char*)"(J)Z", (void*)control_rect_get_callback },
		{ (char*)"set_fullscreen", (char*)"(JZ)V", (void*)control_rect_set_fullscreen },
		{ (char*)"is_fullscreen", (char*)"(J)Z", (void*)control_rect_is_fullscreen },
		{ (char*)"set_mode", (char*)"(JI)V", (void*)control_rect_set_mode },
		{ (char*)"get_mode", (char*)"(J)I", (void*)control_rect_get_mode },
		{ (char*)"set_pipeline", (char*)"(JJ)V", (void*)control_rect_set_pipeline },
		{ (char*)"set_pipeline_1", (char*)"(JJL" TS_JNI_PREFIX "CanvasElement$DrawCallback;)V", (void*)control_rect_set_pipeline_1 },
		{ (char*)"get_pipeline", (char*)"(J)J", (void*)control_rect_get_pipeline },
		{ (char*)"set_radius", (char*)"(JF)V", (void*)control_rect_set_radius },
		{ (char*)"get_radius", (char*)"(J)F", (void*)control_rect_get_radius },
		{ (char*)"set_color", (char*)"(JJ)V", (void*)control_rect_set_color },
		{ (char*)"set_color_1", (char*)"(JFFFF)V", (void*)control_rect_set_color_1 },
		{ (char*)"get_color", (char*)"(J)J", (void*)control_rect_get_color },
		{ (char*)"set_stroke_style", (char*)"(JJ)V", (void*)control_rect_set_stroke_style },
		{ (char*)"get_stroke_style_const", (char*)"(J)J", (void*)control_rect_get_stroke_style_const },
		{ (char*)"get_stroke_style", (char*)"(J)J", (void*)control_rect_get_stroke_style },
		{ (char*)"get_stroke_style_1", (char*)"(J)J", (void*)control_rect_get_stroke_style_1 },
		{ (char*)"set_gradient_style", (char*)"(JJ)V", (void*)control_rect_set_gradient_style },
		{ (char*)"get_gradient_style_const", (char*)"(J)J", (void*)control_rect_get_gradient_style_const },
		{ (char*)"get_gradient_style", (char*)"(J)J", (void*)control_rect_get_gradient_style },
		{ (char*)"get_gradient_style_1", (char*)"(J)J", (void*)control_rect_get_gradient_style_1 },
		{ (char*)"set_mipmap", (char*)"(JF)V", (void*)control_rect_set_mipmap },
		{ (char*)"get_mipmap", (char*)"(J)F", (void*)control_rect_get_mipmap },
		{ (char*)"set_filter", (char*)"(JI)V", (void*)control_rect_set_filter },
		{ (char*)"get_filter", (char*)"(J)I", (void*)control_rect_get_filter },
		{ (char*)"set_anisotropy", (char*)"(JI)V", (void*)control_rect_set_anisotropy },
		{ (char*)"get_anisotropy", (char*)"(J)I", (void*)control_rect_get_anisotropy },
		{ (char*)"set_wrap_mode", (char*)"(JI)V", (void*)control_rect_set_wrap_mode },
		{ (char*)"get_wrap_mode", (char*)"(J)I", (void*)control_rect_get_wrap_mode },
		{ (char*)"set_blend", (char*)"(JIII)V", (void*)control_rect_set_blend },
		{ (char*)"get_blend_op", (char*)"(J)I", (void*)control_rect_get_blend_op },
		{ (char*)"get_blend_src_func", (char*)"(J)I", (void*)control_rect_get_blend_src_func },
		{ (char*)"get_blend_dest_func", (char*)"(J)I", (void*)control_rect_get_blend_dest_func },
		{ (char*)"set_texture", (char*)"(JJZ)V", (void*)control_rect_set_texture },
		{ (char*)"get_texture", (char*)"(J)J", (void*)control_rect_get_texture },
		{ (char*)"get_texture_linear", (char*)"(J)Z", (void*)control_rect_get_texture_linear },
		{ (char*)"set_texture_name", (char*)"(JLjava/lang/String;)V", (void*)control_rect_set_texture_name },
		{ (char*)"set_texture_name_1", (char*)"(JJ)V", (void*)control_rect_set_texture_name_1 },
		{ (char*)"get_texture_name", (char*)"(J)Ljava/lang/String;", (void*)control_rect_get_texture_name },
		{ (char*)"set_texture_scale", (char*)"(JFF)V", (void*)control_rect_set_texture_scale },
		{ (char*)"get_texture_scale_x", (char*)"(J)F", (void*)control_rect_get_texture_scale_x },
		{ (char*)"get_texture_scale_y", (char*)"(J)F", (void*)control_rect_get_texture_scale_y },
		{ (char*)"set_texture_flip", (char*)"(JZZ)V", (void*)control_rect_set_texture_flip },
		{ (char*)"get_texture_flip_x", (char*)"(J)Z", (void*)control_rect_get_texture_flip_x },
		{ (char*)"get_texture_flip_y", (char*)"(J)Z", (void*)control_rect_get_texture_flip_y },
		{ (char*)"set_texture_proj", (char*)"(JZ)V", (void*)control_rect_set_texture_proj },
		{ (char*)"get_texture_proj", (char*)"(J)Z", (void*)control_rect_get_texture_proj },
		{ (char*)"set_tex_coord", (char*)"(JJ)V", (void*)control_rect_set_tex_coord },
		{ (char*)"set_tex_coord_1", (char*)"(JFFFF)V", (void*)control_rect_set_tex_coord_1 },
		{ (char*)"get_tex_coord", (char*)"(J)J", (void*)control_rect_get_tex_coord },
		{ (char*)"set_pressed_callback", (char*)"(JL" TS_JNI_PREFIX "ControlRect$PressedCallback;)V", (void*)control_rect_set_pressed_callback },
		{ (char*)"set_released_callback", (char*)"(JL" TS_JNI_PREFIX "ControlRect$ReleasedCallback;)V", (void*)control_rect_set_released_callback },
		{ (char*)"set_clicked_callback", (char*)"(JL" TS_JNI_PREFIX "ControlRect$ClickedCallback;)V", (void*)control_rect_set_clicked_callback },
		{ (char*)"set_clicked2_callback", (char*)"(JL" TS_JNI_PREFIX "ControlRect$ClickedCallback;)V", (void*)control_rect_set_clicked2_callback },
		{ (char*)"set_clicked_right_callback", (char*)"(JL" TS_JNI_PREFIX "ControlRect$ClickedCallback;)V", (void*)control_rect_set_clicked_right_callback },
		{ (char*)"get_canvas_rect", (char*)"(J)J", (void*)control_rect_get_canvas_rect },
		{ (char*)"get_canvas_mesh", (char*)"(J)J", (void*)control_rect_get_canvas_mesh },
	};
	
	// Tellusim::ControlGrid
	static jlong control_grid_new(TS_JNI_ARGS) {
		return newControlGrid();
	}
	static jlong control_grid_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlGrid(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_grid_new_2(TS_JNI_ARGS, jlongArray parent, jint columns) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlGrid(parent_.get(), (uint32_t)columns);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_grid_new_3(TS_JNI_ARGS, jlongArray parent, jint columns, jfloat x, jfloat y) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlGrid(parent_.get(), (uint32_t)columns, x, y);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_grid_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlGrid*)self;
	}
	static jboolean control_grid_equal_control_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlGrid(self).operator==(toControl(base));
	}
	static jlong control_grid_cast_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControlGrid(toControl(self));
	}
	static jlong control_grid_base_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControl(toControlGrid(self).getControl());
	}
	static void control_grid_set_columns(TS_JNI_ARGS, jlong self, jint columns) {
		toControlGrid(self).setColumns((uint32_t)columns);
	}
	static jint control_grid_get_columns(TS_JNI_ARGS, jlong self) {
		return toControlGrid(self).getColumns();
	}
	static void control_grid_set_spacing(TS_JNI_ARGS, jlong self, jlong spacing) {
		toControlGrid(self).setSpacing(toVector2f(spacing));
	}
	static void control_grid_set_spacing_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y) {
		toControlGrid(self).setSpacing(x, y);
	}
	static jlong control_grid_get_spacing(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlGrid(self).getSpacing());
	}
	static void control_grid_set_column_ratio(TS_JNI_ARGS, jlong self, jint index, jfloat ratio) {
		toControlGrid(self).setColumnRatio((uint32_t)index, ratio);
	}
	static jfloat control_grid_get_column_ratio(TS_JNI_ARGS, jlong self, jint index) {
		return toControlGrid(self).getColumnRatio((uint32_t)index);
	}
	static jlong control_grid_get_controls_size(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlGrid(self).getControlsSize());
	}
	static const JNINativeMethod control_grid_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_grid_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_grid_new_1 },
		{ (char*)"new_2", (char*)"([JI)J", (void*)control_grid_new_2 },
		{ (char*)"new_3", (char*)"([JIFF)J", (void*)control_grid_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_grid_delete },
		{ (char*)"equal_control_ptr", (char*)"(JJ)Z", (void*)control_grid_equal_control_ptr },
		{ (char*)"cast_control_ptr", (char*)"(J)J", (void*)control_grid_cast_control_ptr },
		{ (char*)"base_control_ptr", (char*)"(J)J", (void*)control_grid_base_control_ptr },
		{ (char*)"set_columns", (char*)"(JI)V", (void*)control_grid_set_columns },
		{ (char*)"get_columns", (char*)"(J)I", (void*)control_grid_get_columns },
		{ (char*)"set_spacing", (char*)"(JJ)V", (void*)control_grid_set_spacing },
		{ (char*)"set_spacing_1", (char*)"(JFF)V", (void*)control_grid_set_spacing_1 },
		{ (char*)"get_spacing", (char*)"(J)J", (void*)control_grid_get_spacing },
		{ (char*)"set_column_ratio", (char*)"(JIF)V", (void*)control_grid_set_column_ratio },
		{ (char*)"get_column_ratio", (char*)"(JI)F", (void*)control_grid_get_column_ratio },
		{ (char*)"get_controls_size", (char*)"(J)J", (void*)control_grid_get_controls_size },
	};
	
	// Tellusim::ControlGroup
	static void control_group_clicked_callback_func(ControlGroup a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlGroup$ClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_group_clicked_callback_func(): can't find \"%s\" class\n", "ControlGroup$ClickedCallback");
			else if(!method_id) TS_LOGF(Error, "control_group_clicked_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlGroup(a0));
		}
	}
	static ControlGroup::ClickedCallback make_control_group_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_group_clicked_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlGroup::ClickedCallback();
	}
	
	static jlong control_group_new(TS_JNI_ARGS) {
		return newControlGroup();
	}
	static jlong control_group_new_1(TS_JNI_ARGS, jlongArray parent, jboolean above) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlGroup(parent_.get(), (bool)above);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_group_new_2(TS_JNI_ARGS, jlongArray parent, jstring text, jboolean above) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlGroup(parent_.get(), text_, (bool)above);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_group_new_3(TS_JNI_ARGS, jlongArray parent, jlong text, jboolean above) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlGroup(parent_.get(), toString(text), (bool)above);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_group_new_4(TS_JNI_ARGS, jlongArray parent, jstring text, jint columns, jboolean above) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlGroup(parent_.get(), text_, (uint32_t)columns, (bool)above);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_group_new_5(TS_JNI_ARGS, jlongArray parent, jstring text, jint columns, jfloat x, jfloat y, jboolean above) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlGroup(parent_.get(), text_, (uint32_t)columns, x, y, (bool)above);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static void control_group_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlGroup*)self;
	}
	static jboolean control_group_equal_control_text_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlGroup(self).operator==(toControlText(base));
	}
	static jlong control_group_cast_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlGroup(toControlText(self));
	}
	static jlong control_group_base_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlText(toControlGroup(self).getControlText());
	}
	static void control_group_set_above(TS_JNI_ARGS, jlong self, jboolean above, jboolean text) {
		toControlGroup(self).setAbove((bool)above, (bool)text);
	}
	static jboolean control_group_is_above(TS_JNI_ARGS, jlong self) {
		return toControlGroup(self).isAbove();
	}
	static jboolean control_group_is_below(TS_JNI_ARGS, jlong self) {
		return toControlGroup(self).isBelow();
	}
	static void control_group_set_foldable(TS_JNI_ARGS, jlong self, jboolean foldable) {
		toControlGroup(self).setFoldable((bool)foldable);
	}
	static jboolean control_group_is_foldable(TS_JNI_ARGS, jlong self) {
		return toControlGroup(self).isFoldable();
	}
	static void control_group_set_expanded(TS_JNI_ARGS, jlong self, jboolean expanded) {
		toControlGroup(self).setExpanded((bool)expanded);
	}
	static jboolean control_group_is_expanded(TS_JNI_ARGS, jlong self) {
		return toControlGroup(self).isExpanded();
	}
	static void control_group_set_background(TS_JNI_ARGS, jlong self, jboolean background) {
		toControlGroup(self).setBackground((bool)background);
	}
	static jboolean control_group_get_background(TS_JNI_ARGS, jlong self) {
		return toControlGroup(self).getBackground();
	}
	static void control_group_set_group_radius(TS_JNI_ARGS, jlong self, jfloat radius) {
		toControlGroup(self).setGroupRadius(radius);
	}
	static jfloat control_group_get_group_radius(TS_JNI_ARGS, jlong self) {
		return toControlGroup(self).getGroupRadius();
	}
	static void control_group_set_group_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlGroup(self).setGroupColor(toColor(color));
	}
	static jlong control_group_get_group_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlGroup(self).getGroupColor());
	}
	static void control_group_set_stroke_style(TS_JNI_ARGS, jlong self, jlong style) {
		toControlGroup(self).setStrokeStyle(toStrokeStyle(style));
	}
	static jlong control_group_get_stroke_style_const(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toControlGroup(self).getStrokeStyleConst());
	}
	static jlong control_group_get_stroke_style(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toControlGroup(self).getStrokeStyle());
	}
	static jlong control_group_get_stroke_style_1(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toControlGroup(self).getStrokeStyle());
	}
	static void control_group_set_gradient_style(TS_JNI_ARGS, jlong self, jlong style) {
		toControlGroup(self).setGradientStyle(toGradientStyle(style));
	}
	static jlong control_group_get_gradient_style_const(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toControlGroup(self).getGradientStyleConst());
	}
	static jlong control_group_get_gradient_style(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toControlGroup(self).getGradientStyle());
	}
	static jlong control_group_get_gradient_style_1(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toControlGroup(self).getGradientStyle());
	}
	static void control_group_set_folded_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlGroup(self).setFoldedText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_group_set_folded_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toControlGroup(self).setFoldedText(toString(text));
	}
	static jstring control_group_get_folded_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlGroup(self).getFoldedText().get());
	}
	static void control_group_set_expanded_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlGroup(self).setExpandedText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_group_set_expanded_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toControlGroup(self).setExpandedText(toString(text));
	}
	static jstring control_group_get_expanded_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlGroup(self).getExpandedText().get());
	}
	static void control_group_set_columns(TS_JNI_ARGS, jlong self, jint columns) {
		toControlGroup(self).setColumns((uint32_t)columns);
	}
	static jint control_group_get_columns(TS_JNI_ARGS, jlong self) {
		return toControlGroup(self).getColumns();
	}
	static void control_group_set_spacing(TS_JNI_ARGS, jlong self, jlong spacing) {
		toControlGroup(self).setSpacing(toVector2f(spacing));
	}
	static void control_group_set_spacing_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y) {
		toControlGroup(self).setSpacing(x, y);
	}
	static jlong control_group_get_spacing(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlGroup(self).getSpacing());
	}
	static void control_group_set_column_ratio(TS_JNI_ARGS, jlong self, jint index, jfloat ratio) {
		toControlGroup(self).setColumnRatio((uint32_t)index, ratio);
	}
	static jfloat control_group_get_column_ratio(TS_JNI_ARGS, jlong self, jint index) {
		return toControlGroup(self).getColumnRatio((uint32_t)index);
	}
	static jlong control_group_get_controls_size(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlGroup(self).getControlsSize());
	}
	static void control_group_set_clicked_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlGroup(self).setClickedCallback(make_control_group_clicked_callback(env, func));
	}
	static jboolean control_group_is_clicked(TS_JNI_ARGS, jlong self) {
		return toControlGroup(self).isClicked();
	}
	static jlong control_group_get_canvas_rect(TS_JNI_ARGS, jlong self) {
		return newCanvasRect(toControlGroup(self).getCanvasRect());
	}
	static const JNINativeMethod control_group_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_group_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)control_group_new_1 },
		{ (char*)"new_2", (char*)"([JLjava/lang/String;Z)J", (void*)control_group_new_2 },
		{ (char*)"new_3", (char*)"([JJZ)J", (void*)control_group_new_3 },
		{ (char*)"new_4", (char*)"([JLjava/lang/String;IZ)J", (void*)control_group_new_4 },
		{ (char*)"new_5", (char*)"([JLjava/lang/String;IFFZ)J", (void*)control_group_new_5 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_group_delete },
		{ (char*)"equal_control_text_ptr", (char*)"(JJ)Z", (void*)control_group_equal_control_text_ptr },
		{ (char*)"cast_control_text_ptr", (char*)"(J)J", (void*)control_group_cast_control_text_ptr },
		{ (char*)"base_control_text_ptr", (char*)"(J)J", (void*)control_group_base_control_text_ptr },
		{ (char*)"set_above", (char*)"(JZZ)V", (void*)control_group_set_above },
		{ (char*)"is_above", (char*)"(J)Z", (void*)control_group_is_above },
		{ (char*)"is_below", (char*)"(J)Z", (void*)control_group_is_below },
		{ (char*)"set_foldable", (char*)"(JZ)V", (void*)control_group_set_foldable },
		{ (char*)"is_foldable", (char*)"(J)Z", (void*)control_group_is_foldable },
		{ (char*)"set_expanded", (char*)"(JZ)V", (void*)control_group_set_expanded },
		{ (char*)"is_expanded", (char*)"(J)Z", (void*)control_group_is_expanded },
		{ (char*)"set_background", (char*)"(JZ)V", (void*)control_group_set_background },
		{ (char*)"get_background", (char*)"(J)Z", (void*)control_group_get_background },
		{ (char*)"set_group_radius", (char*)"(JF)V", (void*)control_group_set_group_radius },
		{ (char*)"get_group_radius", (char*)"(J)F", (void*)control_group_get_group_radius },
		{ (char*)"set_group_color", (char*)"(JJ)V", (void*)control_group_set_group_color },
		{ (char*)"get_group_color", (char*)"(J)J", (void*)control_group_get_group_color },
		{ (char*)"set_stroke_style", (char*)"(JJ)V", (void*)control_group_set_stroke_style },
		{ (char*)"get_stroke_style_const", (char*)"(J)J", (void*)control_group_get_stroke_style_const },
		{ (char*)"get_stroke_style", (char*)"(J)J", (void*)control_group_get_stroke_style },
		{ (char*)"get_stroke_style_1", (char*)"(J)J", (void*)control_group_get_stroke_style_1 },
		{ (char*)"set_gradient_style", (char*)"(JJ)V", (void*)control_group_set_gradient_style },
		{ (char*)"get_gradient_style_const", (char*)"(J)J", (void*)control_group_get_gradient_style_const },
		{ (char*)"get_gradient_style", (char*)"(J)J", (void*)control_group_get_gradient_style },
		{ (char*)"get_gradient_style_1", (char*)"(J)J", (void*)control_group_get_gradient_style_1 },
		{ (char*)"set_folded_text", (char*)"(JLjava/lang/String;)V", (void*)control_group_set_folded_text },
		{ (char*)"set_folded_text_1", (char*)"(JJ)V", (void*)control_group_set_folded_text_1 },
		{ (char*)"get_folded_text", (char*)"(J)Ljava/lang/String;", (void*)control_group_get_folded_text },
		{ (char*)"set_expanded_text", (char*)"(JLjava/lang/String;)V", (void*)control_group_set_expanded_text },
		{ (char*)"set_expanded_text_1", (char*)"(JJ)V", (void*)control_group_set_expanded_text_1 },
		{ (char*)"get_expanded_text", (char*)"(J)Ljava/lang/String;", (void*)control_group_get_expanded_text },
		{ (char*)"set_columns", (char*)"(JI)V", (void*)control_group_set_columns },
		{ (char*)"get_columns", (char*)"(J)I", (void*)control_group_get_columns },
		{ (char*)"set_spacing", (char*)"(JJ)V", (void*)control_group_set_spacing },
		{ (char*)"set_spacing_1", (char*)"(JFF)V", (void*)control_group_set_spacing_1 },
		{ (char*)"get_spacing", (char*)"(J)J", (void*)control_group_get_spacing },
		{ (char*)"set_column_ratio", (char*)"(JIF)V", (void*)control_group_set_column_ratio },
		{ (char*)"get_column_ratio", (char*)"(JI)F", (void*)control_group_get_column_ratio },
		{ (char*)"get_controls_size", (char*)"(J)J", (void*)control_group_get_controls_size },
		{ (char*)"set_clicked_callback", (char*)"(JL" TS_JNI_PREFIX "ControlGroup$ClickedCallback;)V", (void*)control_group_set_clicked_callback },
		{ (char*)"is_clicked", (char*)"(J)Z", (void*)control_group_is_clicked },
		{ (char*)"get_canvas_rect", (char*)"(J)J", (void*)control_group_get_canvas_rect },
	};
	
	// Tellusim::ControlPanel
	static jlong control_panel_new(TS_JNI_ARGS) {
		return newControlPanel();
	}
	static jlong control_panel_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlPanel(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_panel_new_2(TS_JNI_ARGS, jlongArray parent, jint columns) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlPanel(parent_.get(), (uint32_t)columns);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_panel_new_3(TS_JNI_ARGS, jlongArray parent, jint columns, jfloat x, jfloat y) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlPanel(parent_.get(), (uint32_t)columns, x, y);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_panel_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlPanel*)self;
	}
	static jboolean control_panel_equal_control_rect_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlPanel(self).operator==(toControlRect(base));
	}
	static jlong control_panel_cast_control_rect_ptr(TS_JNI_ARGS, jlong self) {
		return newControlPanel(toControlRect(self));
	}
	static jlong control_panel_base_control_rect_ptr(TS_JNI_ARGS, jlong self) {
		return newControlRect(toControlPanel(self).getControlRect());
	}
	static void control_panel_set_columns(TS_JNI_ARGS, jlong self, jint columns) {
		toControlPanel(self).setColumns((uint32_t)columns);
	}
	static jint control_panel_get_columns(TS_JNI_ARGS, jlong self) {
		return toControlPanel(self).getColumns();
	}
	static void control_panel_set_spacing(TS_JNI_ARGS, jlong self, jlong spacing) {
		toControlPanel(self).setSpacing(toVector2f(spacing));
	}
	static void control_panel_set_spacing_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y) {
		toControlPanel(self).setSpacing(x, y);
	}
	static jlong control_panel_get_spacing(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlPanel(self).getSpacing());
	}
	static void control_panel_set_column_ratio(TS_JNI_ARGS, jlong self, jint index, jfloat ratio) {
		toControlPanel(self).setColumnRatio((uint32_t)index, ratio);
	}
	static jfloat control_panel_get_column_ratio(TS_JNI_ARGS, jlong self, jint index) {
		return toControlPanel(self).getColumnRatio((uint32_t)index);
	}
	static jlong control_panel_get_controls_size(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlPanel(self).getControlsSize());
	}
	static const JNINativeMethod control_panel_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_panel_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_panel_new_1 },
		{ (char*)"new_2", (char*)"([JI)J", (void*)control_panel_new_2 },
		{ (char*)"new_3", (char*)"([JIFF)J", (void*)control_panel_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_panel_delete },
		{ (char*)"equal_control_rect_ptr", (char*)"(JJ)Z", (void*)control_panel_equal_control_rect_ptr },
		{ (char*)"cast_control_rect_ptr", (char*)"(J)J", (void*)control_panel_cast_control_rect_ptr },
		{ (char*)"base_control_rect_ptr", (char*)"(J)J", (void*)control_panel_base_control_rect_ptr },
		{ (char*)"set_columns", (char*)"(JI)V", (void*)control_panel_set_columns },
		{ (char*)"get_columns", (char*)"(J)I", (void*)control_panel_get_columns },
		{ (char*)"set_spacing", (char*)"(JJ)V", (void*)control_panel_set_spacing },
		{ (char*)"set_spacing_1", (char*)"(JFF)V", (void*)control_panel_set_spacing_1 },
		{ (char*)"get_spacing", (char*)"(J)J", (void*)control_panel_get_spacing },
		{ (char*)"set_column_ratio", (char*)"(JIF)V", (void*)control_panel_set_column_ratio },
		{ (char*)"get_column_ratio", (char*)"(JI)F", (void*)control_panel_get_column_ratio },
		{ (char*)"get_controls_size", (char*)"(J)J", (void*)control_panel_get_controls_size },
	};
	
	// Tellusim::ControlDialog
	static void control_dialog_updated_callback_func(ControlDialog a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlDialog$UpdatedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_dialog_updated_callback_func(): can't find \"%s\" class\n", "ControlDialog$UpdatedCallback");
			else if(!method_id) TS_LOGF(Error, "control_dialog_updated_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlDialog(a0));
		}
	}
	static ControlDialog::UpdatedCallback make_control_dialog_updated_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_dialog_updated_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlDialog::UpdatedCallback();
	}
	
	static jlong control_dialog_new(TS_JNI_ARGS) {
		return newControlDialog();
	}
	static jlong control_dialog_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlDialog(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_dialog_new_2(TS_JNI_ARGS, jlongArray parent, jint columns) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlDialog(parent_.get(), (uint32_t)columns);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_dialog_new_3(TS_JNI_ARGS, jlongArray parent, jint columns, jfloat x, jfloat y) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlDialog(parent_.get(), (uint32_t)columns, x, y);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_dialog_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlDialog*)self;
	}
	static jboolean control_dialog_equal_control_panel_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlDialog(self).operator==(toControlPanel(base));
	}
	static jlong control_dialog_cast_control_panel_ptr(TS_JNI_ARGS, jlong self) {
		return newControlDialog(toControlPanel(self));
	}
	static jlong control_dialog_base_control_panel_ptr(TS_JNI_ARGS, jlong self) {
		return newControlPanel(toControlDialog(self).getControlPanel());
	}
	static void control_dialog_set_constrained(TS_JNI_ARGS, jlong self, jboolean contrained) {
		toControlDialog(self).setConstrained((bool)contrained);
	}
	static jboolean control_dialog_is_constrained(TS_JNI_ARGS, jlong self) {
		return toControlDialog(self).isConstrained();
	}
	static void control_dialog_set_resizable(TS_JNI_ARGS, jlong self, jboolean resizable) {
		toControlDialog(self).setResizable((bool)resizable);
	}
	static jboolean control_dialog_is_resizable(TS_JNI_ARGS, jlong self) {
		return toControlDialog(self).isResizable();
	}
	static void control_dialog_set_resize_area(TS_JNI_ARGS, jlong self, jfloat area) {
		toControlDialog(self).setResizeArea(area);
	}
	static jfloat control_dialog_get_resize_area(TS_JNI_ARGS, jlong self) {
		return toControlDialog(self).getResizeArea();
	}
	static jint control_dialog_get_resize_align(TS_JNI_ARGS, jlong self) {
		return toControlDialog(self).getResizeAlign();
	}
	static jboolean control_dialog_has_resize_align(TS_JNI_ARGS, jlong self, jint align) {
		return toControlDialog(self).hasResizeAlign((Control::Align)align);
	}
	static jboolean control_dialog_has_resize_aligns(TS_JNI_ARGS, jlong self, jint aligns) {
		return toControlDialog(self).hasResizeAligns((Control::Align)aligns);
	}
	static void control_dialog_set_mouse_position(TS_JNI_ARGS, jlong self, jlong position) {
		toControlDialog(self).setMousePosition(toVector2f(position));
	}
	static jlong control_dialog_get_mouse_position(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlDialog(self).getMousePosition());
	}
	static void control_dialog_set_updated_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlDialog(self).setUpdatedCallback(make_control_dialog_updated_callback(env, func));
	}
	static jboolean control_dialog_is_updated(TS_JNI_ARGS, jlong self) {
		return toControlDialog(self).isUpdated();
	}
	static const JNINativeMethod control_dialog_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_dialog_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_dialog_new_1 },
		{ (char*)"new_2", (char*)"([JI)J", (void*)control_dialog_new_2 },
		{ (char*)"new_3", (char*)"([JIFF)J", (void*)control_dialog_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_dialog_delete },
		{ (char*)"equal_control_panel_ptr", (char*)"(JJ)Z", (void*)control_dialog_equal_control_panel_ptr },
		{ (char*)"cast_control_panel_ptr", (char*)"(J)J", (void*)control_dialog_cast_control_panel_ptr },
		{ (char*)"base_control_panel_ptr", (char*)"(J)J", (void*)control_dialog_base_control_panel_ptr },
		{ (char*)"set_constrained", (char*)"(JZ)V", (void*)control_dialog_set_constrained },
		{ (char*)"is_constrained", (char*)"(J)Z", (void*)control_dialog_is_constrained },
		{ (char*)"set_resizable", (char*)"(JZ)V", (void*)control_dialog_set_resizable },
		{ (char*)"is_resizable", (char*)"(J)Z", (void*)control_dialog_is_resizable },
		{ (char*)"set_resize_area", (char*)"(JF)V", (void*)control_dialog_set_resize_area },
		{ (char*)"get_resize_area", (char*)"(J)F", (void*)control_dialog_get_resize_area },
		{ (char*)"get_resize_align", (char*)"(J)I", (void*)control_dialog_get_resize_align },
		{ (char*)"has_resize_align", (char*)"(JI)Z", (void*)control_dialog_has_resize_align },
		{ (char*)"has_resize_aligns", (char*)"(JI)Z", (void*)control_dialog_has_resize_aligns },
		{ (char*)"set_mouse_position", (char*)"(JJ)V", (void*)control_dialog_set_mouse_position },
		{ (char*)"get_mouse_position", (char*)"(J)J", (void*)control_dialog_get_mouse_position },
		{ (char*)"set_updated_callback", (char*)"(JL" TS_JNI_PREFIX "ControlDialog$UpdatedCallback;)V", (void*)control_dialog_set_updated_callback },
		{ (char*)"is_updated", (char*)"(J)Z", (void*)control_dialog_is_updated },
	};
	
	// Tellusim::ControlWindow
	static jlong control_window_new(TS_JNI_ARGS) {
		return newControlWindow();
	}
	static jlong control_window_new_1(TS_JNI_ARGS, jlongArray root, jlong parent, jlong window) {
		Array<ControlRoot> root_((uint32_t)env->GetArrayLength(root));
		jlong *root__ = env->GetLongArrayElements(root, nullptr);
		for(uint32_t i = 0; i < root_.size(); i++) root_[i] = toControlRoot(root__[i]);
		jlong ret_ = newControlWindow(root_.get(), toWindow(parent), toWindow(window));
		if(root__) env->ReleaseLongArrayElements(root, root__, 0);
		return ret_;
	}
	static jlong control_window_new_2(TS_JNI_ARGS, jlongArray root, jlong parent, jlong window, jint columns) {
		Array<ControlRoot> root_((uint32_t)env->GetArrayLength(root));
		jlong *root__ = env->GetLongArrayElements(root, nullptr);
		for(uint32_t i = 0; i < root_.size(); i++) root_[i] = toControlRoot(root__[i]);
		jlong ret_ = newControlWindow(root_.get(), toWindow(parent), toWindow(window), (uint32_t)columns);
		if(root__) env->ReleaseLongArrayElements(root, root__, 0);
		return ret_;
	}
	static jlong control_window_new_3(TS_JNI_ARGS, jlongArray root, jlong parent, jlong window, jint columns, jfloat x, jfloat y) {
		Array<ControlRoot> root_((uint32_t)env->GetArrayLength(root));
		jlong *root__ = env->GetLongArrayElements(root, nullptr);
		for(uint32_t i = 0; i < root_.size(); i++) root_[i] = toControlRoot(root__[i]);
		jlong ret_ = newControlWindow(root_.get(), toWindow(parent), toWindow(window), (uint32_t)columns, x, y);
		if(root__) env->ReleaseLongArrayElements(root, root__, 0);
		return ret_;
	}
	static void control_window_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlWindow*)self;
	}
	static jboolean control_window_equal_control_dialog_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlWindow(self).operator==(toControlDialog(base));
	}
	static jlong control_window_cast_control_dialog_ptr(TS_JNI_ARGS, jlong self) {
		return newControlWindow(toControlDialog(self));
	}
	static jlong control_window_base_control_dialog_ptr(TS_JNI_ARGS, jlong self) {
		return newControlDialog(toControlWindow(self).getControlDialog());
	}
	static jlong control_window_get_parent_window(TS_JNI_ARGS, jlong self) {
		return newWindow(toControlWindow(self).getParentWindow());
	}
	static jlong control_window_get_dialog_window(TS_JNI_ARGS, jlong self) {
		return newWindow(toControlWindow(self).getDialogWindow());
	}
	static const JNINativeMethod control_window_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_window_new },
		{ (char*)"new_1", (char*)"([JJJ)J", (void*)control_window_new_1 },
		{ (char*)"new_2", (char*)"([JJJI)J", (void*)control_window_new_2 },
		{ (char*)"new_3", (char*)"([JJJIFF)J", (void*)control_window_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_window_delete },
		{ (char*)"equal_control_dialog_ptr", (char*)"(JJ)Z", (void*)control_window_equal_control_dialog_ptr },
		{ (char*)"cast_control_dialog_ptr", (char*)"(J)J", (void*)control_window_cast_control_dialog_ptr },
		{ (char*)"base_control_dialog_ptr", (char*)"(J)J", (void*)control_window_base_control_dialog_ptr },
		{ (char*)"get_parent_window", (char*)"(J)J", (void*)control_window_get_parent_window },
		{ (char*)"get_dialog_window", (char*)"(J)J", (void*)control_window_get_dialog_window },
	};
	
	// Tellusim::ControlCheck
	static void control_check_clicked_callback_func(ControlCheck a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlCheck$ClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_check_clicked_callback_func(): can't find \"%s\" class\n", "ControlCheck$ClickedCallback");
			else if(!method_id) TS_LOGF(Error, "control_check_clicked_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlCheck(a0));
		}
	}
	static ControlCheck::ClickedCallback make_control_check_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_check_clicked_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlCheck::ClickedCallback();
	}
	
	static jlong control_check_new(TS_JNI_ARGS) {
		return newControlCheck();
	}
	static jlong control_check_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlCheck(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_check_new_2(TS_JNI_ARGS, jlongArray parent, jstring text) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlCheck(parent_.get(), text_);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_check_new_3(TS_JNI_ARGS, jlongArray parent, jlong text) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlCheck(parent_.get(), toString(text));
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_check_new_4(TS_JNI_ARGS, jlongArray parent, jstring text, jboolean checked) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlCheck(parent_.get(), text_, (bool)checked);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_check_new_5(TS_JNI_ARGS, jlongArray parent, jlong text, jboolean checked) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlCheck(parent_.get(), toString(text), (bool)checked);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_check_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlCheck*)self;
	}
	static jboolean control_check_equal_control_text_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlCheck(self).operator==(toControlText(base));
	}
	static jlong control_check_cast_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlCheck(toControlText(self));
	}
	static jlong control_check_base_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlText(toControlCheck(self).getControlText());
	}
	static void control_check_set_check_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlCheck(self).setCheckText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_check_set_check_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toControlCheck(self).setCheckText(toString(text));
	}
	static jstring control_check_get_check_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlCheck(self).getCheckText().get());
	}
	static void control_check_set_check_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlCheck(self).setCheckColor(toColor(color));
	}
	static jlong control_check_get_check_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlCheck(self).getCheckColor());
	}
	static void control_check_set_checked_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlCheck(self).setCheckedColor(toColor(color));
	}
	static jlong control_check_get_checked_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlCheck(self).getCheckedColor());
	}
	static jboolean control_check_switch_checked(TS_JNI_ARGS, jlong self, jboolean callback) {
		return toControlCheck(self).switchChecked((bool)callback);
	}
	static void control_check_set_checked(TS_JNI_ARGS, jlong self, jboolean checked, jboolean callback) {
		toControlCheck(self).setChecked((bool)checked, (bool)callback);
	}
	static jboolean control_check_is_checked(TS_JNI_ARGS, jlong self) {
		return toControlCheck(self).isChecked();
	}
	static void control_check_set_clicked_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlCheck(self).setClickedCallback(make_control_check_clicked_callback(env, func));
	}
	static jboolean control_check_is_clicked(TS_JNI_ARGS, jlong self) {
		return toControlCheck(self).isClicked();
	}
	static jlong control_check_get_canvas_mesh(TS_JNI_ARGS, jlong self) {
		return newCanvasMesh(toControlCheck(self).getCanvasMesh());
	}
	static const JNINativeMethod control_check_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_check_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_check_new_1 },
		{ (char*)"new_2", (char*)"([JLjava/lang/String;)J", (void*)control_check_new_2 },
		{ (char*)"new_3", (char*)"([JJ)J", (void*)control_check_new_3 },
		{ (char*)"new_4", (char*)"([JLjava/lang/String;Z)J", (void*)control_check_new_4 },
		{ (char*)"new_5", (char*)"([JJZ)J", (void*)control_check_new_5 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_check_delete },
		{ (char*)"equal_control_text_ptr", (char*)"(JJ)Z", (void*)control_check_equal_control_text_ptr },
		{ (char*)"cast_control_text_ptr", (char*)"(J)J", (void*)control_check_cast_control_text_ptr },
		{ (char*)"base_control_text_ptr", (char*)"(J)J", (void*)control_check_base_control_text_ptr },
		{ (char*)"set_check_text", (char*)"(JLjava/lang/String;)V", (void*)control_check_set_check_text },
		{ (char*)"set_check_text_1", (char*)"(JJ)V", (void*)control_check_set_check_text_1 },
		{ (char*)"get_check_text", (char*)"(J)Ljava/lang/String;", (void*)control_check_get_check_text },
		{ (char*)"set_check_color", (char*)"(JJ)V", (void*)control_check_set_check_color },
		{ (char*)"get_check_color", (char*)"(J)J", (void*)control_check_get_check_color },
		{ (char*)"set_checked_color", (char*)"(JJ)V", (void*)control_check_set_checked_color },
		{ (char*)"get_checked_color", (char*)"(J)J", (void*)control_check_get_checked_color },
		{ (char*)"switch_checked", (char*)"(JZ)Z", (void*)control_check_switch_checked },
		{ (char*)"set_checked", (char*)"(JZZ)V", (void*)control_check_set_checked },
		{ (char*)"is_checked", (char*)"(J)Z", (void*)control_check_is_checked },
		{ (char*)"set_clicked_callback", (char*)"(JL" TS_JNI_PREFIX "ControlCheck$ClickedCallback;)V", (void*)control_check_set_clicked_callback },
		{ (char*)"is_clicked", (char*)"(J)Z", (void*)control_check_is_clicked },
		{ (char*)"get_canvas_mesh", (char*)"(J)J", (void*)control_check_get_canvas_mesh },
	};
	
	// Tellusim::ControlCombo
	static void control_combo_clicked_callback_func(ControlCombo a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlCombo$ClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_combo_clicked_callback_func(): can't find \"%s\" class\n", "ControlCombo$ClickedCallback");
			else if(!method_id) TS_LOGF(Error, "control_combo_clicked_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlCombo(a0));
		}
	}
	static ControlCombo::ClickedCallback make_control_combo_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_combo_clicked_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlCombo::ClickedCallback();
	}
	static void control_combo_changed_callback_func(ControlCombo a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlCombo$ChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_combo_changed_callback_func(): can't find \"%s\" class\n", "ControlCombo$ChangedCallback");
			else if(!method_id) TS_LOGF(Error, "control_combo_changed_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlCombo(a0));
		}
	}
	static ControlCombo::ChangedCallback make_control_combo_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_combo_changed_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlCombo::ChangedCallback();
	}
	
	static jlong control_combo_new(TS_JNI_ARGS) {
		return newControlCombo();
	}
	static jlong control_combo_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlCombo(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_combo_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlCombo*)self;
	}
	static jboolean control_combo_equal_control_text_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlCombo(self).operator==(toControlText(base));
	}
	static jlong control_combo_cast_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlCombo(toControlText(self));
	}
	static jlong control_combo_base_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlText(toControlCombo(self).getControlText());
	}
	static void control_combo_set_multi_selection(TS_JNI_ARGS, jlong self, jboolean multi_selection) {
		toControlCombo(self).setMultiSelection((bool)multi_selection);
	}
	static jboolean control_combo_is_multi_selection(TS_JNI_ARGS, jlong self) {
		return toControlCombo(self).isMultiSelection();
	}
	static void control_combo_set_combo_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlCombo(self).setComboText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_combo_set_combo_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toControlCombo(self).setComboText(toString(text));
	}
	static jstring control_combo_get_combo_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlCombo(self).getComboText().get());
	}
	static void control_combo_set_combo_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlCombo(self).setComboColor(toColor(color));
	}
	static jlong control_combo_get_combo_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlCombo(self).getComboColor());
	}
	static void control_combo_set_items_spacing(TS_JNI_ARGS, jlong self, jfloat spacing) {
		toControlCombo(self).setItemsSpacing(spacing);
	}
	static jfloat control_combo_get_items_spacing(TS_JNI_ARGS, jlong self) {
		return toControlCombo(self).getItemsSpacing();
	}
	static void control_combo_clear_items(TS_JNI_ARGS, jlong self) {
		toControlCombo(self).clearItems();
	}
	static jint control_combo_add_item(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		uint32_t ret_ = toControlCombo(self).addItem(text_);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jint control_combo_add_item_1(TS_JNI_ARGS, jlong self, jlong text) {
		return toControlCombo(self).addItem(toString(text));
	}
	static void control_combo_add_item_2(TS_JNI_ARGS, jlong self, jint index, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlCombo(self).addItem((uint32_t)index, text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_combo_add_item_3(TS_JNI_ARGS, jlong self, jint index, jlong text) {
		toControlCombo(self).addItem((uint32_t)index, toString(text));
	}
	static void control_combo_remove_item(TS_JNI_ARGS, jlong self, jint index) {
		toControlCombo(self).removeItem((uint32_t)index);
	}
	static jint control_combo_get_num_items(TS_JNI_ARGS, jlong self) {
		return toControlCombo(self).getNumItems();
	}
	static jboolean control_combo_switch_item_selected(TS_JNI_ARGS, jlong self, jint index) {
		return toControlCombo(self).switchItemSelected((uint32_t)index);
	}
	static void control_combo_set_item_selected(TS_JNI_ARGS, jlong self, jint index, jboolean selected) {
		toControlCombo(self).setItemSelected((uint32_t)index, (bool)selected);
	}
	static jboolean control_combo_is_item_selected(TS_JNI_ARGS, jlong self, jint index) {
		return toControlCombo(self).isItemSelected((uint32_t)index);
	}
	static void control_combo_set_item_text(TS_JNI_ARGS, jlong self, jint index, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlCombo(self).setItemText((uint32_t)index, text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_combo_set_item_text_1(TS_JNI_ARGS, jlong self, jint index, jlong text) {
		toControlCombo(self).setItemText((uint32_t)index, toString(text));
	}
	static jstring control_combo_get_item_text(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toControlCombo(self).getItemText((uint32_t)index).get());
	}
	static jint control_combo_find_item_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		uint32_t ret_ = toControlCombo(self).findItemText(text_);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jint control_combo_find_item_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		return toControlCombo(self).findItemText(toString(text));
	}
	static void control_combo_set_item_color(TS_JNI_ARGS, jlong self, jint index, jlong color) {
		toControlCombo(self).setItemColor((uint32_t)index, toColor(color));
	}
	static jlong control_combo_get_item_color(TS_JNI_ARGS, jlong self, jint index) {
		return newColor(toControlCombo(self).getItemColor((uint32_t)index));
	}
	static void control_combo_set_current_index(TS_JNI_ARGS, jlong self, jint index, jboolean callback) {
		toControlCombo(self).setCurrentIndex((uint32_t)index, (bool)callback);
	}
	static void control_combo_set_current_text(TS_JNI_ARGS, jlong self, jstring text, jboolean callback) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlCombo(self).setCurrentText(text_, (bool)callback);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_combo_set_current_text_1(TS_JNI_ARGS, jlong self, jlong text, jboolean callback) {
		toControlCombo(self).setCurrentText(toString(text), (bool)callback);
	}
	static jint control_combo_get_current_index(TS_JNI_ARGS, jlong self) {
		return toControlCombo(self).getCurrentIndex();
	}
	static jstring control_combo_get_current_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlCombo(self).getCurrentText().get());
	}
	static void control_combo_set_clicked_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlCombo(self).setClickedCallback(make_control_combo_clicked_callback(env, func));
	}
	static jboolean control_combo_is_clicked(TS_JNI_ARGS, jlong self) {
		return toControlCombo(self).isClicked();
	}
	static void control_combo_set_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlCombo(self).setChangedCallback(make_control_combo_changed_callback(env, func));
	}
	static jboolean control_combo_is_changed(TS_JNI_ARGS, jlong self) {
		return toControlCombo(self).isChanged();
	}
	static jlong control_combo_get_canvas_mesh(TS_JNI_ARGS, jlong self) {
		return newCanvasMesh(toControlCombo(self).getCanvasMesh());
	}
	static const JNINativeMethod control_combo_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_combo_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_combo_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_combo_delete },
		{ (char*)"equal_control_text_ptr", (char*)"(JJ)Z", (void*)control_combo_equal_control_text_ptr },
		{ (char*)"cast_control_text_ptr", (char*)"(J)J", (void*)control_combo_cast_control_text_ptr },
		{ (char*)"base_control_text_ptr", (char*)"(J)J", (void*)control_combo_base_control_text_ptr },
		{ (char*)"set_multi_selection", (char*)"(JZ)V", (void*)control_combo_set_multi_selection },
		{ (char*)"is_multi_selection", (char*)"(J)Z", (void*)control_combo_is_multi_selection },
		{ (char*)"set_combo_text", (char*)"(JLjava/lang/String;)V", (void*)control_combo_set_combo_text },
		{ (char*)"set_combo_text_1", (char*)"(JJ)V", (void*)control_combo_set_combo_text_1 },
		{ (char*)"get_combo_text", (char*)"(J)Ljava/lang/String;", (void*)control_combo_get_combo_text },
		{ (char*)"set_combo_color", (char*)"(JJ)V", (void*)control_combo_set_combo_color },
		{ (char*)"get_combo_color", (char*)"(J)J", (void*)control_combo_get_combo_color },
		{ (char*)"set_items_spacing", (char*)"(JF)V", (void*)control_combo_set_items_spacing },
		{ (char*)"get_items_spacing", (char*)"(J)F", (void*)control_combo_get_items_spacing },
		{ (char*)"clear_items", (char*)"(J)V", (void*)control_combo_clear_items },
		{ (char*)"add_item", (char*)"(JLjava/lang/String;)I", (void*)control_combo_add_item },
		{ (char*)"add_item_1", (char*)"(JJ)I", (void*)control_combo_add_item_1 },
		{ (char*)"add_item_2", (char*)"(JILjava/lang/String;)V", (void*)control_combo_add_item_2 },
		{ (char*)"add_item_3", (char*)"(JIJ)V", (void*)control_combo_add_item_3 },
		{ (char*)"remove_item", (char*)"(JI)V", (void*)control_combo_remove_item },
		{ (char*)"get_num_items", (char*)"(J)I", (void*)control_combo_get_num_items },
		{ (char*)"switch_item_selected", (char*)"(JI)Z", (void*)control_combo_switch_item_selected },
		{ (char*)"set_item_selected", (char*)"(JIZ)V", (void*)control_combo_set_item_selected },
		{ (char*)"is_item_selected", (char*)"(JI)Z", (void*)control_combo_is_item_selected },
		{ (char*)"set_item_text", (char*)"(JILjava/lang/String;)V", (void*)control_combo_set_item_text },
		{ (char*)"set_item_text_1", (char*)"(JIJ)V", (void*)control_combo_set_item_text_1 },
		{ (char*)"get_item_text", (char*)"(JI)Ljava/lang/String;", (void*)control_combo_get_item_text },
		{ (char*)"find_item_text", (char*)"(JLjava/lang/String;)I", (void*)control_combo_find_item_text },
		{ (char*)"find_item_text_1", (char*)"(JJ)I", (void*)control_combo_find_item_text_1 },
		{ (char*)"set_item_color", (char*)"(JIJ)V", (void*)control_combo_set_item_color },
		{ (char*)"get_item_color", (char*)"(JI)J", (void*)control_combo_get_item_color },
		{ (char*)"set_current_index", (char*)"(JIZ)V", (void*)control_combo_set_current_index },
		{ (char*)"set_current_text", (char*)"(JLjava/lang/String;Z)V", (void*)control_combo_set_current_text },
		{ (char*)"set_current_text_1", (char*)"(JJZ)V", (void*)control_combo_set_current_text_1 },
		{ (char*)"get_current_index", (char*)"(J)I", (void*)control_combo_get_current_index },
		{ (char*)"get_current_text", (char*)"(J)Ljava/lang/String;", (void*)control_combo_get_current_text },
		{ (char*)"set_clicked_callback", (char*)"(JL" TS_JNI_PREFIX "ControlCombo$ClickedCallback;)V", (void*)control_combo_set_clicked_callback },
		{ (char*)"is_clicked", (char*)"(J)Z", (void*)control_combo_is_clicked },
		{ (char*)"set_changed_callback", (char*)"(JL" TS_JNI_PREFIX "ControlCombo$ChangedCallback;)V", (void*)control_combo_set_changed_callback },
		{ (char*)"is_changed", (char*)"(J)Z", (void*)control_combo_is_changed },
		{ (char*)"get_canvas_mesh", (char*)"(J)J", (void*)control_combo_get_canvas_mesh },
	};
	
	// Tellusim::ControlButton
	static void control_button_pressed_callback_func(ControlButton a0, float32_t x, float32_t y, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlButton$PressedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JFF)V");
			if(!clazz) TS_LOGF(Error, "control_button_pressed_callback_func(): can't find \"%s\" class\n", "ControlButton$PressedCallback");
			else if(!method_id) TS_LOGF(Error, "control_button_pressed_callback_func(): can't get \"%s\" method\n", "(JFF)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlButton(a0), (jfloat)x, (jfloat)y);
		}
	}
	static ControlButton::PressedCallback make_control_button_pressed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_button_pressed_callback_func);
			ret.setArg3(env);
			ret.setArg4(func);
			return ret;
		}
		return ControlButton::PressedCallback();
	}
	static void control_button_released_callback_func(ControlButton a0, float32_t x, float32_t y, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlButton$ReleasedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JFF)V");
			if(!clazz) TS_LOGF(Error, "control_button_released_callback_func(): can't find \"%s\" class\n", "ControlButton$ReleasedCallback");
			else if(!method_id) TS_LOGF(Error, "control_button_released_callback_func(): can't get \"%s\" method\n", "(JFF)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlButton(a0), (jfloat)x, (jfloat)y);
		}
	}
	static ControlButton::ReleasedCallback make_control_button_released_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_button_released_callback_func);
			ret.setArg3(env);
			ret.setArg4(func);
			return ret;
		}
		return ControlButton::ReleasedCallback();
	}
	static void control_button_clicked_callback_func(ControlButton a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlButton$ClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_button_clicked_callback_func(): can't find \"%s\" class\n", "ControlButton$ClickedCallback");
			else if(!method_id) TS_LOGF(Error, "control_button_clicked_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlButton(a0));
		}
	}
	static ControlButton::ClickedCallback make_control_button_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_button_clicked_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlButton::ClickedCallback();
	}
	
	static jlong control_button_new(TS_JNI_ARGS) {
		return newControlButton();
	}
	static jlong control_button_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlButton(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_button_new_2(TS_JNI_ARGS, jlongArray parent, jstring text) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlButton(parent_.get(), text_);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_button_new_3(TS_JNI_ARGS, jlongArray parent, jlong text) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlButton(parent_.get(), toString(text));
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_button_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlButton*)self;
	}
	static jboolean control_button_equal_control_text_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlButton(self).operator==(toControlText(base));
	}
	static jlong control_button_cast_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlButton(toControlText(self));
	}
	static jlong control_button_base_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlText(toControlButton(self).getControlText());
	}
	static void control_button_set_background(TS_JNI_ARGS, jlong self, jboolean background) {
		toControlButton(self).setBackground((bool)background);
	}
	static jboolean control_button_get_background(TS_JNI_ARGS, jlong self) {
		return toControlButton(self).getBackground();
	}
	static void control_button_set_button_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toControlButton(self).setButtonMode((CanvasElement::Mode)mode);
	}
	static jint control_button_get_button_mode(TS_JNI_ARGS, jlong self) {
		return toControlButton(self).getButtonMode();
	}
	static void control_button_set_button_radius(TS_JNI_ARGS, jlong self, jfloat radius) {
		toControlButton(self).setButtonRadius(radius);
	}
	static jfloat control_button_get_button_radius(TS_JNI_ARGS, jlong self) {
		return toControlButton(self).getButtonRadius();
	}
	static void control_button_set_button_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlButton(self).setButtonColor(toColor(color));
	}
	static jlong control_button_get_button_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlButton(self).getButtonColor());
	}
	static void control_button_set_stroke_style(TS_JNI_ARGS, jlong self, jlong style) {
		toControlButton(self).setStrokeStyle(toStrokeStyle(style));
	}
	static jlong control_button_get_stroke_style_const(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toControlButton(self).getStrokeStyleConst());
	}
	static jlong control_button_get_stroke_style(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toControlButton(self).getStrokeStyle());
	}
	static jlong control_button_get_stroke_style_1(TS_JNI_ARGS, jlong self) {
		return newStrokeStyle(toControlButton(self).getStrokeStyle());
	}
	static void control_button_set_gradient_style(TS_JNI_ARGS, jlong self, jlong style) {
		toControlButton(self).setGradientStyle(toGradientStyle(style));
	}
	static jlong control_button_get_gradient_style_const(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toControlButton(self).getGradientStyleConst());
	}
	static jlong control_button_get_gradient_style(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toControlButton(self).getGradientStyle());
	}
	static jlong control_button_get_gradient_style_1(TS_JNI_ARGS, jlong self) {
		return newGradientStyle(toControlButton(self).getGradientStyle());
	}
	static void control_button_set_pressed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlButton(self).setPressedCallback(make_control_button_pressed_callback(env, func));
	}
	static jboolean control_button_is_pressed(TS_JNI_ARGS, jlong self) {
		return toControlButton(self).isPressed();
	}
	static void control_button_set_released_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlButton(self).setReleasedCallback(make_control_button_released_callback(env, func));
	}
	static jboolean control_button_is_released(TS_JNI_ARGS, jlong self) {
		return toControlButton(self).isReleased();
	}
	static void control_button_set_clicked_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlButton(self).setClickedCallback(make_control_button_clicked_callback(env, func));
	}
	static jboolean control_button_is_clicked(TS_JNI_ARGS, jlong self) {
		return toControlButton(self).isClicked();
	}
	static jlong control_button_get_canvas_rect(TS_JNI_ARGS, jlong self) {
		return newCanvasRect(toControlButton(self).getCanvasRect());
	}
	static jlong control_button_get_canvas_mesh(TS_JNI_ARGS, jlong self) {
		return newCanvasMesh(toControlButton(self).getCanvasMesh());
	}
	static const JNINativeMethod control_button_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_button_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_button_new_1 },
		{ (char*)"new_2", (char*)"([JLjava/lang/String;)J", (void*)control_button_new_2 },
		{ (char*)"new_3", (char*)"([JJ)J", (void*)control_button_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_button_delete },
		{ (char*)"equal_control_text_ptr", (char*)"(JJ)Z", (void*)control_button_equal_control_text_ptr },
		{ (char*)"cast_control_text_ptr", (char*)"(J)J", (void*)control_button_cast_control_text_ptr },
		{ (char*)"base_control_text_ptr", (char*)"(J)J", (void*)control_button_base_control_text_ptr },
		{ (char*)"set_background", (char*)"(JZ)V", (void*)control_button_set_background },
		{ (char*)"get_background", (char*)"(J)Z", (void*)control_button_get_background },
		{ (char*)"set_button_mode", (char*)"(JI)V", (void*)control_button_set_button_mode },
		{ (char*)"get_button_mode", (char*)"(J)I", (void*)control_button_get_button_mode },
		{ (char*)"set_button_radius", (char*)"(JF)V", (void*)control_button_set_button_radius },
		{ (char*)"get_button_radius", (char*)"(J)F", (void*)control_button_get_button_radius },
		{ (char*)"set_button_color", (char*)"(JJ)V", (void*)control_button_set_button_color },
		{ (char*)"get_button_color", (char*)"(J)J", (void*)control_button_get_button_color },
		{ (char*)"set_stroke_style", (char*)"(JJ)V", (void*)control_button_set_stroke_style },
		{ (char*)"get_stroke_style_const", (char*)"(J)J", (void*)control_button_get_stroke_style_const },
		{ (char*)"get_stroke_style", (char*)"(J)J", (void*)control_button_get_stroke_style },
		{ (char*)"get_stroke_style_1", (char*)"(J)J", (void*)control_button_get_stroke_style_1 },
		{ (char*)"set_gradient_style", (char*)"(JJ)V", (void*)control_button_set_gradient_style },
		{ (char*)"get_gradient_style_const", (char*)"(J)J", (void*)control_button_get_gradient_style_const },
		{ (char*)"get_gradient_style", (char*)"(J)J", (void*)control_button_get_gradient_style },
		{ (char*)"get_gradient_style_1", (char*)"(J)J", (void*)control_button_get_gradient_style_1 },
		{ (char*)"set_pressed_callback", (char*)"(JL" TS_JNI_PREFIX "ControlButton$PressedCallback;)V", (void*)control_button_set_pressed_callback },
		{ (char*)"is_pressed", (char*)"(J)Z", (void*)control_button_is_pressed },
		{ (char*)"set_released_callback", (char*)"(JL" TS_JNI_PREFIX "ControlButton$ReleasedCallback;)V", (void*)control_button_set_released_callback },
		{ (char*)"is_released", (char*)"(J)Z", (void*)control_button_is_released },
		{ (char*)"set_clicked_callback", (char*)"(JL" TS_JNI_PREFIX "ControlButton$ClickedCallback;)V", (void*)control_button_set_clicked_callback },
		{ (char*)"is_clicked", (char*)"(J)Z", (void*)control_button_is_clicked },
		{ (char*)"get_canvas_rect", (char*)"(J)J", (void*)control_button_get_canvas_rect },
		{ (char*)"get_canvas_mesh", (char*)"(J)J", (void*)control_button_get_canvas_mesh },
	};
	
	// Tellusim::ControlSlider
	static String control_slider_format_callback_func(ControlSlider a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlSlider$FormatCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)Ljava/lang/String;");
			if(!clazz) TS_LOGF(Error, "control_slider_format_callback_func(): can't find \"%s\" class\n", "ControlSlider$FormatCallback");
			else if(!method_id) TS_LOGF(Error, "control_slider_format_callback_func(): can't get \"%s\" method\n", "(J)Ljava/lang/String;");
		}
		if(method_id) {
			jstring ret = (jstring)env->CallObjectMethod(func, method_id, newControlSlider(a0));
			if(ret) {
				const char *s = env->GetStringUTFChars(ret, nullptr);
				String ret_ = String(s);
				env->ReleaseStringUTFChars(ret, s);
				return ret_;
			}
		}
		return String::null;
	}
	static ControlSlider::FormatCallback make_control_slider_format_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_slider_format_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlSlider::FormatCallback();
	}
	static void control_slider_released_callback_func(ControlSlider a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlSlider$ReleasedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_slider_released_callback_func(): can't find \"%s\" class\n", "ControlSlider$ReleasedCallback");
			else if(!method_id) TS_LOGF(Error, "control_slider_released_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlSlider(a0));
		}
	}
	static ControlSlider::ReleasedCallback make_control_slider_released_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_slider_released_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlSlider::ReleasedCallback();
	}
	static void control_slider_clicked_callback_func(ControlSlider a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlSlider$ClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_slider_clicked_callback_func(): can't find \"%s\" class\n", "ControlSlider$ClickedCallback");
			else if(!method_id) TS_LOGF(Error, "control_slider_clicked_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlSlider(a0));
		}
	}
	static ControlSlider::ClickedCallback make_control_slider_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_slider_clicked_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlSlider::ClickedCallback();
	}
	static void control_slider_changed_callback_func(ControlSlider a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlSlider$ChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_slider_changed_callback_func(): can't find \"%s\" class\n", "ControlSlider$ChangedCallback");
			else if(!method_id) TS_LOGF(Error, "control_slider_changed_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlSlider(a0));
		}
	}
	static ControlSlider::ChangedCallback make_control_slider_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_slider_changed_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlSlider::ChangedCallback();
	}
	
	static jlong control_slider_new(TS_JNI_ARGS) {
		return newControlSlider();
	}
	static jlong control_slider_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlSlider(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_slider_new_2(TS_JNI_ARGS, jlongArray parent, jstring text) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlSlider(parent_.get(), text_);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_slider_new_3(TS_JNI_ARGS, jlongArray parent, jlong text) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlSlider(parent_.get(), toString(text));
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_slider_new_4(TS_JNI_ARGS, jlongArray parent, jstring text, jint digits) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlSlider(parent_.get(), text_, (uint32_t)digits);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_slider_new_5(TS_JNI_ARGS, jlongArray parent, jstring text, jint digits, jdouble value) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlSlider(parent_.get(), text_, (uint32_t)digits, value);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_slider_new_6(TS_JNI_ARGS, jlongArray parent, jstring text, jint digits, jdouble value, jdouble min, jdouble max) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlSlider(parent_.get(), text_, (uint32_t)digits, value, min, max);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_slider_new_7(TS_JNI_ARGS, jlongArray parent, jstring text, jdouble value, jdouble min, jdouble max) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlSlider(parent_.get(), text_, value, min, max);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_slider_new_8(TS_JNI_ARGS, jlongArray parent, jstring text, jint value, jint min, jint max) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlSlider(parent_.get(), text_, (uint32_t)value, (uint32_t)min, (uint32_t)max);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_slider_new_9(TS_JNI_ARGS, jlongArray parent, jstring text, jint value, jint min, jint max) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlSlider(parent_.get(), text_, value, min, max);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static void control_slider_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlSlider*)self;
	}
	static jboolean control_slider_equal_control_text_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlSlider(self).operator==(toControlText(base));
	}
	static jlong control_slider_cast_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlSlider(toControlText(self));
	}
	static jlong control_slider_base_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlText(toControlSlider(self).getControlText());
	}
	static void control_slider_set_slider_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlSlider(self).setSliderColor(toColor(color));
	}
	static jlong control_slider_get_slider_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlSlider(self).getSliderColor());
	}
	static void control_slider_set_digits(TS_JNI_ARGS, jlong self, jint digits) {
		toControlSlider(self).setDigits((uint32_t)digits);
	}
	static jint control_slider_get_digits(TS_JNI_ARGS, jlong self) {
		return toControlSlider(self).getDigits();
	}
	static void control_slider_set_text_enabled(TS_JNI_ARGS, jlong self, jboolean enabled) {
		toControlSlider(self).setTextEnabled((bool)enabled);
	}
	static jboolean control_slider_is_text_enabled(TS_JNI_ARGS, jlong self) {
		return toControlSlider(self).isTextEnabled();
	}
	static void control_slider_set_step(TS_JNI_ARGS, jlong self, jdouble step) {
		toControlSlider(self).setStep(step);
	}
	static jdouble control_slider_get_step(TS_JNI_ARGS, jlong self) {
		return toControlSlider(self).getStep();
	}
	static void control_slider_set_base(TS_JNI_ARGS, jlong self, jdouble base) {
		toControlSlider(self).setBase(base);
	}
	static jdouble control_slider_get_base(TS_JNI_ARGS, jlong self) {
		return toControlSlider(self).getBase();
	}
	static void control_slider_set_format(TS_JNI_ARGS, jlong self, jstring format) {
		const char *format_ = (format) ? env->GetStringUTFChars(format, nullptr) : nullptr;
		toControlSlider(self).setFormat(format_);
		env->ReleaseStringUTFChars(format, format_);
	}
	static void control_slider_set_format_1(TS_JNI_ARGS, jlong self, jlong format) {
		toControlSlider(self).setFormat(toString(format));
	}
	static jstring control_slider_get_format(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlSlider(self).getFormat().get());
	}
	static void control_slider_set_value(TS_JNI_ARGS, jlong self, jdouble value, jboolean callback, jboolean exponent) {
		toControlSlider(self).setValue(value, (bool)callback, (bool)exponent);
	}
	static jdouble control_slider_get_value(TS_JNI_ARGS, jlong self, jboolean exponent) {
		return toControlSlider(self).getValue((bool)exponent);
	}
	static jfloat control_slider_get_valuef32(TS_JNI_ARGS, jlong self, jboolean exponent) {
		return toControlSlider(self).getValuef32((bool)exponent);
	}
	static jint control_slider_get_valueu32(TS_JNI_ARGS, jlong self, jboolean exponent) {
		return toControlSlider(self).getValueu32((bool)exponent);
	}
	static jint control_slider_get_valuei32(TS_JNI_ARGS, jlong self, jboolean exponent) {
		return toControlSlider(self).getValuei32((bool)exponent);
	}
	static void control_slider_set_range(TS_JNI_ARGS, jlong self, jdouble min, jdouble max, jboolean exponent) {
		toControlSlider(self).setRange(min, max, (bool)exponent);
	}
	static jdouble control_slider_get_min_range(TS_JNI_ARGS, jlong self, jboolean exponent) {
		return toControlSlider(self).getMinRange((bool)exponent);
	}
	static jdouble control_slider_get_max_range(TS_JNI_ARGS, jlong self, jboolean exponent) {
		return toControlSlider(self).getMaxRange((bool)exponent);
	}
	static void control_slider_set_handle_size(TS_JNI_ARGS, jlong self, jfloat size) {
		toControlSlider(self).setHandleSize(size);
	}
	static jfloat control_slider_get_handle_size(TS_JNI_ARGS, jlong self) {
		return toControlSlider(self).getHandleSize();
	}
	static void control_slider_set_format_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlSlider(self).setFormatCallback(make_control_slider_format_callback(env, func));
	}
	static void control_slider_set_released_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlSlider(self).setReleasedCallback(make_control_slider_released_callback(env, func));
	}
	static jboolean control_slider_is_released(TS_JNI_ARGS, jlong self) {
		return toControlSlider(self).isReleased();
	}
	static void control_slider_set_clicked_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlSlider(self).setClickedCallback(make_control_slider_clicked_callback(env, func));
	}
	static jboolean control_slider_is_clicked(TS_JNI_ARGS, jlong self) {
		return toControlSlider(self).isClicked();
	}
	static void control_slider_set_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlSlider(self).setChangedCallback(make_control_slider_changed_callback(env, func));
	}
	static jboolean control_slider_is_changed(TS_JNI_ARGS, jlong self, jboolean clear) {
		return toControlSlider(self).isChanged((bool)clear);
	}
	static jlong control_slider_get_canvas_mesh(TS_JNI_ARGS, jlong self) {
		return newCanvasMesh(toControlSlider(self).getCanvasMesh());
	}
	static const JNINativeMethod control_slider_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_slider_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_slider_new_1 },
		{ (char*)"new_2", (char*)"([JLjava/lang/String;)J", (void*)control_slider_new_2 },
		{ (char*)"new_3", (char*)"([JJ)J", (void*)control_slider_new_3 },
		{ (char*)"new_4", (char*)"([JLjava/lang/String;I)J", (void*)control_slider_new_4 },
		{ (char*)"new_5", (char*)"([JLjava/lang/String;ID)J", (void*)control_slider_new_5 },
		{ (char*)"new_6", (char*)"([JLjava/lang/String;IDDD)J", (void*)control_slider_new_6 },
		{ (char*)"new_7", (char*)"([JLjava/lang/String;DDD)J", (void*)control_slider_new_7 },
		{ (char*)"new_8", (char*)"([JLjava/lang/String;III)J", (void*)control_slider_new_8 },
		{ (char*)"new_9", (char*)"([JLjava/lang/String;III)J", (void*)control_slider_new_9 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_slider_delete },
		{ (char*)"equal_control_text_ptr", (char*)"(JJ)Z", (void*)control_slider_equal_control_text_ptr },
		{ (char*)"cast_control_text_ptr", (char*)"(J)J", (void*)control_slider_cast_control_text_ptr },
		{ (char*)"base_control_text_ptr", (char*)"(J)J", (void*)control_slider_base_control_text_ptr },
		{ (char*)"set_slider_color", (char*)"(JJ)V", (void*)control_slider_set_slider_color },
		{ (char*)"get_slider_color", (char*)"(J)J", (void*)control_slider_get_slider_color },
		{ (char*)"set_digits", (char*)"(JI)V", (void*)control_slider_set_digits },
		{ (char*)"get_digits", (char*)"(J)I", (void*)control_slider_get_digits },
		{ (char*)"set_text_enabled", (char*)"(JZ)V", (void*)control_slider_set_text_enabled },
		{ (char*)"is_text_enabled", (char*)"(J)Z", (void*)control_slider_is_text_enabled },
		{ (char*)"set_step", (char*)"(JD)V", (void*)control_slider_set_step },
		{ (char*)"get_step", (char*)"(J)D", (void*)control_slider_get_step },
		{ (char*)"set_base", (char*)"(JD)V", (void*)control_slider_set_base },
		{ (char*)"get_base", (char*)"(J)D", (void*)control_slider_get_base },
		{ (char*)"set_format", (char*)"(JLjava/lang/String;)V", (void*)control_slider_set_format },
		{ (char*)"set_format_1", (char*)"(JJ)V", (void*)control_slider_set_format_1 },
		{ (char*)"get_format", (char*)"(J)Ljava/lang/String;", (void*)control_slider_get_format },
		{ (char*)"set_value", (char*)"(JDZZ)V", (void*)control_slider_set_value },
		{ (char*)"get_value", (char*)"(JZ)D", (void*)control_slider_get_value },
		{ (char*)"get_valuef32", (char*)"(JZ)F", (void*)control_slider_get_valuef32 },
		{ (char*)"get_valueu32", (char*)"(JZ)I", (void*)control_slider_get_valueu32 },
		{ (char*)"get_valuei32", (char*)"(JZ)I", (void*)control_slider_get_valuei32 },
		{ (char*)"set_range", (char*)"(JDDZ)V", (void*)control_slider_set_range },
		{ (char*)"get_min_range", (char*)"(JZ)D", (void*)control_slider_get_min_range },
		{ (char*)"get_max_range", (char*)"(JZ)D", (void*)control_slider_get_max_range },
		{ (char*)"set_handle_size", (char*)"(JF)V", (void*)control_slider_set_handle_size },
		{ (char*)"get_handle_size", (char*)"(J)F", (void*)control_slider_get_handle_size },
		{ (char*)"set_format_callback", (char*)"(JL" TS_JNI_PREFIX "ControlSlider$FormatCallback;)V", (void*)control_slider_set_format_callback },
		{ (char*)"set_released_callback", (char*)"(JL" TS_JNI_PREFIX "ControlSlider$ReleasedCallback;)V", (void*)control_slider_set_released_callback },
		{ (char*)"is_released", (char*)"(J)Z", (void*)control_slider_is_released },
		{ (char*)"set_clicked_callback", (char*)"(JL" TS_JNI_PREFIX "ControlSlider$ClickedCallback;)V", (void*)control_slider_set_clicked_callback },
		{ (char*)"is_clicked", (char*)"(J)Z", (void*)control_slider_is_clicked },
		{ (char*)"set_changed_callback", (char*)"(JL" TS_JNI_PREFIX "ControlSlider$ChangedCallback;)V", (void*)control_slider_set_changed_callback },
		{ (char*)"is_changed", (char*)"(JZ)Z", (void*)control_slider_is_changed },
		{ (char*)"get_canvas_mesh", (char*)"(J)J", (void*)control_slider_get_canvas_mesh },
	};
	
	// Tellusim::ControlScroll
	static void control_scroll_clicked_callback_func(ControlScroll a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlScroll$ClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_scroll_clicked_callback_func(): can't find \"%s\" class\n", "ControlScroll$ClickedCallback");
			else if(!method_id) TS_LOGF(Error, "control_scroll_clicked_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlScroll(a0));
		}
	}
	static ControlScroll::ClickedCallback make_control_scroll_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_scroll_clicked_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlScroll::ClickedCallback();
	}
	static void control_scroll_changed_callback_func(ControlScroll a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlScroll$ChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_scroll_changed_callback_func(): can't find \"%s\" class\n", "ControlScroll$ChangedCallback");
			else if(!method_id) TS_LOGF(Error, "control_scroll_changed_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlScroll(a0));
		}
	}
	static ControlScroll::ChangedCallback make_control_scroll_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_scroll_changed_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlScroll::ChangedCallback();
	}
	
	static jlong control_scroll_new(TS_JNI_ARGS) {
		return newControlScroll();
	}
	static jlong control_scroll_new_1(TS_JNI_ARGS, jlongArray parent, jboolean vertical) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlScroll(parent_.get(), (bool)vertical);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_scroll_new_2(TS_JNI_ARGS, jlongArray parent, jdouble value, jboolean vertical) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlScroll(parent_.get(), value, (bool)vertical);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_scroll_new_3(TS_JNI_ARGS, jlongArray parent, jdouble value, jdouble frame, jdouble range, jboolean vertical) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlScroll(parent_.get(), value, frame, range, (bool)vertical);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_scroll_new_4(TS_JNI_ARGS, jlongArray parent, jint value, jint frame, jint range, jboolean vertical) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlScroll(parent_.get(), (uint32_t)value, (uint32_t)frame, (uint32_t)range, (bool)vertical);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_scroll_new_5(TS_JNI_ARGS, jlongArray parent, jint value, jint frame, jint range, jboolean vertical) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlScroll(parent_.get(), value, frame, range, (bool)vertical);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_scroll_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlScroll*)self;
	}
	static jboolean control_scroll_equal_control_text_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlScroll(self).operator==(toControlText(base));
	}
	static jlong control_scroll_cast_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlScroll(toControlText(self));
	}
	static jlong control_scroll_base_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlText(toControlScroll(self).getControlText());
	}
	static void control_scroll_set_vertical(TS_JNI_ARGS, jlong self, jboolean vertical, jboolean text) {
		toControlScroll(self).setVertical((bool)vertical, (bool)text);
	}
	static jboolean control_scroll_is_horizontal(TS_JNI_ARGS, jlong self) {
		return toControlScroll(self).isHorizontal();
	}
	static jboolean control_scroll_is_vertical(TS_JNI_ARGS, jlong self) {
		return toControlScroll(self).isVertical();
	}
	static void control_scroll_set_prev_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlScroll(self).setPrevText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_scroll_set_prev_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toControlScroll(self).setPrevText(toString(text));
	}
	static jstring control_scroll_get_prev_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlScroll(self).getPrevText().get());
	}
	static void control_scroll_set_next_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlScroll(self).setNextText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_scroll_set_next_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toControlScroll(self).setNextText(toString(text));
	}
	static jstring control_scroll_get_next_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlScroll(self).getNextText().get());
	}
	static void control_scroll_set_scroll_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlScroll(self).setScrollColor(toColor(color));
	}
	static jlong control_scroll_get_scroll_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlScroll(self).getScrollColor());
	}
	static void control_scroll_set_step(TS_JNI_ARGS, jlong self, jdouble step) {
		toControlScroll(self).setStep(step);
	}
	static jdouble control_scroll_get_step(TS_JNI_ARGS, jlong self) {
		return toControlScroll(self).getStep();
	}
	static void control_scroll_set_value(TS_JNI_ARGS, jlong self, jdouble value, jboolean callback) {
		toControlScroll(self).setValue(value, (bool)callback);
	}
	static jdouble control_scroll_get_value(TS_JNI_ARGS, jlong self) {
		return toControlScroll(self).getValue();
	}
	static void control_scroll_set_frame(TS_JNI_ARGS, jlong self, jdouble frame) {
		toControlScroll(self).setFrame(frame);
	}
	static jdouble control_scroll_get_frame(TS_JNI_ARGS, jlong self) {
		return toControlScroll(self).getFrame();
	}
	static void control_scroll_set_range(TS_JNI_ARGS, jlong self, jdouble range) {
		toControlScroll(self).setRange(range);
	}
	static jdouble control_scroll_get_range(TS_JNI_ARGS, jlong self) {
		return toControlScroll(self).getRange();
	}
	static void control_scroll_set_frame_align(TS_JNI_ARGS, jlong self, jint align) {
		toControlScroll(self).setFrameAlign((Control::Align)align);
	}
	static jint control_scroll_get_frame_align(TS_JNI_ARGS, jlong self) {
		return toControlScroll(self).getFrameAlign();
	}
	static jboolean control_scroll_has_frame_align(TS_JNI_ARGS, jlong self, jint align) {
		return toControlScroll(self).hasFrameAlign((Control::Align)align);
	}
	static jboolean control_scroll_has_frame_aligns(TS_JNI_ARGS, jlong self, jint aligns) {
		return toControlScroll(self).hasFrameAligns((Control::Align)aligns);
	}
	static void control_scroll_set_clicked_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlScroll(self).setClickedCallback(make_control_scroll_clicked_callback(env, func));
	}
	static jboolean control_scroll_is_clicked(TS_JNI_ARGS, jlong self) {
		return toControlScroll(self).isClicked();
	}
	static void control_scroll_set_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlScroll(self).setChangedCallback(make_control_scroll_changed_callback(env, func));
	}
	static jboolean control_scroll_is_changed(TS_JNI_ARGS, jlong self, jboolean clear) {
		return toControlScroll(self).isChanged((bool)clear);
	}
	static jlong control_scroll_get_canvas_mesh(TS_JNI_ARGS, jlong self) {
		return newCanvasMesh(toControlScroll(self).getCanvasMesh());
	}
	static const JNINativeMethod control_scroll_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_scroll_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)control_scroll_new_1 },
		{ (char*)"new_2", (char*)"([JDZ)J", (void*)control_scroll_new_2 },
		{ (char*)"new_3", (char*)"([JDDDZ)J", (void*)control_scroll_new_3 },
		{ (char*)"new_4", (char*)"([JIIIZ)J", (void*)control_scroll_new_4 },
		{ (char*)"new_5", (char*)"([JIIIZ)J", (void*)control_scroll_new_5 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_scroll_delete },
		{ (char*)"equal_control_text_ptr", (char*)"(JJ)Z", (void*)control_scroll_equal_control_text_ptr },
		{ (char*)"cast_control_text_ptr", (char*)"(J)J", (void*)control_scroll_cast_control_text_ptr },
		{ (char*)"base_control_text_ptr", (char*)"(J)J", (void*)control_scroll_base_control_text_ptr },
		{ (char*)"set_vertical", (char*)"(JZZ)V", (void*)control_scroll_set_vertical },
		{ (char*)"is_horizontal", (char*)"(J)Z", (void*)control_scroll_is_horizontal },
		{ (char*)"is_vertical", (char*)"(J)Z", (void*)control_scroll_is_vertical },
		{ (char*)"set_prev_text", (char*)"(JLjava/lang/String;)V", (void*)control_scroll_set_prev_text },
		{ (char*)"set_prev_text_1", (char*)"(JJ)V", (void*)control_scroll_set_prev_text_1 },
		{ (char*)"get_prev_text", (char*)"(J)Ljava/lang/String;", (void*)control_scroll_get_prev_text },
		{ (char*)"set_next_text", (char*)"(JLjava/lang/String;)V", (void*)control_scroll_set_next_text },
		{ (char*)"set_next_text_1", (char*)"(JJ)V", (void*)control_scroll_set_next_text_1 },
		{ (char*)"get_next_text", (char*)"(J)Ljava/lang/String;", (void*)control_scroll_get_next_text },
		{ (char*)"set_scroll_color", (char*)"(JJ)V", (void*)control_scroll_set_scroll_color },
		{ (char*)"get_scroll_color", (char*)"(J)J", (void*)control_scroll_get_scroll_color },
		{ (char*)"set_step", (char*)"(JD)V", (void*)control_scroll_set_step },
		{ (char*)"get_step", (char*)"(J)D", (void*)control_scroll_get_step },
		{ (char*)"set_value", (char*)"(JDZ)V", (void*)control_scroll_set_value },
		{ (char*)"get_value", (char*)"(J)D", (void*)control_scroll_get_value },
		{ (char*)"set_frame", (char*)"(JD)V", (void*)control_scroll_set_frame },
		{ (char*)"get_frame", (char*)"(J)D", (void*)control_scroll_get_frame },
		{ (char*)"set_range", (char*)"(JD)V", (void*)control_scroll_set_range },
		{ (char*)"get_range", (char*)"(J)D", (void*)control_scroll_get_range },
		{ (char*)"set_frame_align", (char*)"(JI)V", (void*)control_scroll_set_frame_align },
		{ (char*)"get_frame_align", (char*)"(J)I", (void*)control_scroll_get_frame_align },
		{ (char*)"has_frame_align", (char*)"(JI)Z", (void*)control_scroll_has_frame_align },
		{ (char*)"has_frame_aligns", (char*)"(JI)Z", (void*)control_scroll_has_frame_aligns },
		{ (char*)"set_clicked_callback", (char*)"(JL" TS_JNI_PREFIX "ControlScroll$ClickedCallback;)V", (void*)control_scroll_set_clicked_callback },
		{ (char*)"is_clicked", (char*)"(J)Z", (void*)control_scroll_is_clicked },
		{ (char*)"set_changed_callback", (char*)"(JL" TS_JNI_PREFIX "ControlScroll$ChangedCallback;)V", (void*)control_scroll_set_changed_callback },
		{ (char*)"is_changed", (char*)"(JZ)Z", (void*)control_scroll_is_changed },
		{ (char*)"get_canvas_mesh", (char*)"(J)J", (void*)control_scroll_get_canvas_mesh },
	};
	
	// Tellusim::ControlSplit
	static jlong control_split_new(TS_JNI_ARGS) {
		return newControlSplit();
	}
	static jlong control_split_new_1(TS_JNI_ARGS, jlongArray parent, jboolean vertical) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlSplit(parent_.get(), (bool)vertical);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_split_new_2(TS_JNI_ARGS, jlongArray parent, jfloat value, jboolean vertical) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlSplit(parent_.get(), value, (bool)vertical);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_split_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlSplit*)self;
	}
	static jboolean control_split_equal_control_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlSplit(self).operator==(toControl(base));
	}
	static jlong control_split_cast_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControlSplit(toControl(self));
	}
	static jlong control_split_base_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControl(toControlSplit(self).getControl());
	}
	static void control_split_set_absolute(TS_JNI_ARGS, jlong self, jboolean absolute) {
		toControlSplit(self).setAbsolute((bool)absolute);
	}
	static jboolean control_split_is_absolute(TS_JNI_ARGS, jlong self) {
		return toControlSplit(self).isAbsolute();
	}
	static void control_split_set_vertical(TS_JNI_ARGS, jlong self, jboolean vertical) {
		toControlSplit(self).setVertical((bool)vertical);
	}
	static jboolean control_split_is_horizontal(TS_JNI_ARGS, jlong self) {
		return toControlSplit(self).isHorizontal();
	}
	static jboolean control_split_is_vertical(TS_JNI_ARGS, jlong self) {
		return toControlSplit(self).isVertical();
	}
	static void control_split_set_value(TS_JNI_ARGS, jlong self, jfloat value) {
		toControlSplit(self).setValue(value);
	}
	static jfloat control_split_get_value(TS_JNI_ARGS, jlong self) {
		return toControlSplit(self).getValue();
	}
	static void control_split_set_handle_size(TS_JNI_ARGS, jlong self, jfloat size) {
		toControlSplit(self).setHandleSize(size);
	}
	static jfloat control_split_get_handle_size(TS_JNI_ARGS, jlong self) {
		return toControlSplit(self).getHandleSize();
	}
	static jlong control_split_get_controls_size(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlSplit(self).getControlsSize());
	}
	static const JNINativeMethod control_split_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_split_new },
		{ (char*)"new_1", (char*)"([JZ)J", (void*)control_split_new_1 },
		{ (char*)"new_2", (char*)"([JFZ)J", (void*)control_split_new_2 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_split_delete },
		{ (char*)"equal_control_ptr", (char*)"(JJ)Z", (void*)control_split_equal_control_ptr },
		{ (char*)"cast_control_ptr", (char*)"(J)J", (void*)control_split_cast_control_ptr },
		{ (char*)"base_control_ptr", (char*)"(J)J", (void*)control_split_base_control_ptr },
		{ (char*)"set_absolute", (char*)"(JZ)V", (void*)control_split_set_absolute },
		{ (char*)"is_absolute", (char*)"(J)Z", (void*)control_split_is_absolute },
		{ (char*)"set_vertical", (char*)"(JZ)V", (void*)control_split_set_vertical },
		{ (char*)"is_horizontal", (char*)"(J)Z", (void*)control_split_is_horizontal },
		{ (char*)"is_vertical", (char*)"(J)Z", (void*)control_split_is_vertical },
		{ (char*)"set_value", (char*)"(JF)V", (void*)control_split_set_value },
		{ (char*)"get_value", (char*)"(J)F", (void*)control_split_get_value },
		{ (char*)"set_handle_size", (char*)"(JF)V", (void*)control_split_set_handle_size },
		{ (char*)"get_handle_size", (char*)"(J)F", (void*)control_split_get_handle_size },
		{ (char*)"get_controls_size", (char*)"(J)J", (void*)control_split_get_controls_size },
	};
	
	// Tellusim::ControlArea
	static jlong control_area_new(TS_JNI_ARGS) {
		return newControlArea();
	}
	static jlong control_area_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlArea(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_area_new_2(TS_JNI_ARGS, jlongArray parent, jint columns) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlArea(parent_.get(), (uint32_t)columns);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_area_new_3(TS_JNI_ARGS, jlongArray parent, jboolean horizontal, jboolean vertical) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlArea(parent_.get(), (bool)horizontal, (bool)vertical);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_area_new_4(TS_JNI_ARGS, jlongArray parent, jint columns, jfloat x, jfloat y) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlArea(parent_.get(), (uint32_t)columns, x, y);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_area_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlArea*)self;
	}
	static jboolean control_area_equal_control_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlArea(self).operator==(toControl(base));
	}
	static jlong control_area_cast_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControlArea(toControl(self));
	}
	static jlong control_area_base_control_ptr(TS_JNI_ARGS, jlong self) {
		return newControl(toControlArea(self).getControl());
	}
	static void control_area_set_absolute(TS_JNI_ARGS, jlong self, jboolean absolute) {
		toControlArea(self).setAbsolute((bool)absolute);
	}
	static jboolean control_area_is_absolute(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).isAbsolute();
	}
	static void control_area_set_scalable(TS_JNI_ARGS, jlong self, jboolean scalable) {
		toControlArea(self).setScalable((bool)scalable);
	}
	static jboolean control_area_is_scalable(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).isScalable();
	}
	static void control_area_set_scrollable(TS_JNI_ARGS, jlong self, jboolean scrollable) {
		toControlArea(self).setScrollable((bool)scrollable);
	}
	static jboolean control_area_is_scrollable(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).isScrollable();
	}
	static void control_area_set_scale(TS_JNI_ARGS, jlong self, jfloat scale) {
		toControlArea(self).setScale(scale);
	}
	static jfloat control_area_get_scale(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getScale();
	}
	static void control_area_set_scale_range(TS_JNI_ARGS, jlong self, jfloat min, jfloat max) {
		toControlArea(self).setScaleRange(min, max);
	}
	static jfloat control_area_get_min_scale(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getMinScale();
	}
	static jfloat control_area_get_max_scale(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getMaxScale();
	}
	static void control_area_set_horizontal_step(TS_JNI_ARGS, jlong self, jdouble step) {
		toControlArea(self).setHorizontalStep(step);
	}
	static void control_area_set_vertical_step(TS_JNI_ARGS, jlong self, jdouble step) {
		toControlArea(self).setVerticalStep(step);
	}
	static void control_area_set_step(TS_JNI_ARGS, jlong self, jdouble horizontal, jdouble vertical) {
		toControlArea(self).setStep(horizontal, vertical);
	}
	static jdouble control_area_get_horizontal_step(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getHorizontalStep();
	}
	static jdouble control_area_get_vertical_step(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getVerticalStep();
	}
	static void control_area_set_horizontal_value(TS_JNI_ARGS, jlong self, jdouble value) {
		toControlArea(self).setHorizontalValue(value);
	}
	static void control_area_set_vertical_value(TS_JNI_ARGS, jlong self, jdouble value) {
		toControlArea(self).setVerticalValue(value);
	}
	static void control_area_set_value(TS_JNI_ARGS, jlong self, jdouble horizontal, jdouble vertical) {
		toControlArea(self).setValue(horizontal, vertical);
	}
	static jdouble control_area_get_horizontal_value(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getHorizontalValue();
	}
	static jdouble control_area_get_vertical_value(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getVerticalValue();
	}
	static void control_area_set_frame_align(TS_JNI_ARGS, jlong self, jint align) {
		toControlArea(self).setFrameAlign((Control::Align)align);
	}
	static jint control_area_get_frame_align(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getFrameAlign();
	}
	static jdouble control_area_get_horizontal_frame(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getHorizontalFrame();
	}
	static jdouble control_area_get_vertical_frame(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getVerticalFrame();
	}
	static jdouble control_area_get_horizontal_range(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getHorizontalRange();
	}
	static jdouble control_area_get_vertical_range(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getVerticalRange();
	}
	static void control_area_set_horizontal_enabled(TS_JNI_ARGS, jlong self, jboolean enabled, jboolean dynamic) {
		toControlArea(self).setHorizontalEnabled((bool)enabled, (bool)dynamic);
	}
	static jboolean control_area_is_horizontal_enabled(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).isHorizontalEnabled();
	}
	static jboolean control_area_is_horizontal_dynamic(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).isHorizontalDynamic();
	}
	static jboolean control_area_is_horizontal_hidden(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).isHorizontalHidden();
	}
	static jlong control_area_get_horizontal_scroll(TS_JNI_ARGS, jlong self) {
		return newControlScroll(toControlArea(self).getHorizontalScroll());
	}
	static jlong control_area_get_horizontal_scroll_1(TS_JNI_ARGS, jlong self) {
		return newControlScroll(toControlArea(self).getHorizontalScroll());
	}
	static void control_area_set_vertical_enabled(TS_JNI_ARGS, jlong self, jboolean enabled, jboolean dynamic) {
		toControlArea(self).setVerticalEnabled((bool)enabled, (bool)dynamic);
	}
	static jboolean control_area_is_vertical_enabled(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).isVerticalEnabled();
	}
	static jboolean control_area_is_vertical_dynamic(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).isVerticalDynamic();
	}
	static jboolean control_area_is_vertical_hidden(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).isVerticalHidden();
	}
	static jlong control_area_get_vertical_scroll(TS_JNI_ARGS, jlong self) {
		return newControlScroll(toControlArea(self).getVerticalScroll());
	}
	static jlong control_area_get_vertical_scroll_1(TS_JNI_ARGS, jlong self) {
		return newControlScroll(toControlArea(self).getVerticalScroll());
	}
	static jboolean control_area_set_font_size(TS_JNI_ARGS, jlong self, jint size) {
		return toControlArea(self).setFontSize((uint32_t)size);
	}
	static jint control_area_get_font_size(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getFontSize();
	}
	static jboolean control_area_set_font_style(TS_JNI_ARGS, jlong self, jlong style) {
		return toControlArea(self).setFontStyle(toFontStyle(style));
	}
	static jlong control_area_get_font_style_const(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toControlArea(self).getFontStyleConst());
	}
	static jlong control_area_get_font_style(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toControlArea(self).getFontStyle());
	}
	static jlong control_area_get_font_style_1(TS_JNI_ARGS, jlong self) {
		return newFontStyle(toControlArea(self).getFontStyle());
	}
	static void control_area_set_columns(TS_JNI_ARGS, jlong self, jint columns) {
		toControlArea(self).setColumns((uint32_t)columns);
	}
	static jint control_area_get_columns(TS_JNI_ARGS, jlong self) {
		return toControlArea(self).getColumns();
	}
	static void control_area_set_spacing(TS_JNI_ARGS, jlong self, jlong spacing) {
		toControlArea(self).setSpacing(toVector2f(spacing));
	}
	static void control_area_set_spacing_1(TS_JNI_ARGS, jlong self, jfloat x, jfloat y) {
		toControlArea(self).setSpacing(x, y);
	}
	static jlong control_area_get_spacing(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlArea(self).getSpacing());
	}
	static void control_area_set_column_ratio(TS_JNI_ARGS, jlong self, jint index, jfloat ratio) {
		toControlArea(self).setColumnRatio((uint32_t)index, ratio);
	}
	static jfloat control_area_get_column_ratio(TS_JNI_ARGS, jlong self, jint index) {
		return toControlArea(self).getColumnRatio((uint32_t)index);
	}
	static jlong control_area_get_controls_size(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlArea(self).getControlsSize());
	}
	static jlong control_area_get_controls_offset(TS_JNI_ARGS, jlong self) {
		return newVector2f(toControlArea(self).getControlsOffset());
	}
	static jlong control_area_get_view_rect(TS_JNI_ARGS, jlong self) {
		return newRect(toControlArea(self).getViewRect());
	}
	static const JNINativeMethod control_area_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_area_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_area_new_1 },
		{ (char*)"new_2", (char*)"([JI)J", (void*)control_area_new_2 },
		{ (char*)"new_3", (char*)"([JZZ)J", (void*)control_area_new_3 },
		{ (char*)"new_4", (char*)"([JIFF)J", (void*)control_area_new_4 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_area_delete },
		{ (char*)"equal_control_ptr", (char*)"(JJ)Z", (void*)control_area_equal_control_ptr },
		{ (char*)"cast_control_ptr", (char*)"(J)J", (void*)control_area_cast_control_ptr },
		{ (char*)"base_control_ptr", (char*)"(J)J", (void*)control_area_base_control_ptr },
		{ (char*)"set_absolute", (char*)"(JZ)V", (void*)control_area_set_absolute },
		{ (char*)"is_absolute", (char*)"(J)Z", (void*)control_area_is_absolute },
		{ (char*)"set_scalable", (char*)"(JZ)V", (void*)control_area_set_scalable },
		{ (char*)"is_scalable", (char*)"(J)Z", (void*)control_area_is_scalable },
		{ (char*)"set_scrollable", (char*)"(JZ)V", (void*)control_area_set_scrollable },
		{ (char*)"is_scrollable", (char*)"(J)Z", (void*)control_area_is_scrollable },
		{ (char*)"set_scale", (char*)"(JF)V", (void*)control_area_set_scale },
		{ (char*)"get_scale", (char*)"(J)F", (void*)control_area_get_scale },
		{ (char*)"set_scale_range", (char*)"(JFF)V", (void*)control_area_set_scale_range },
		{ (char*)"get_min_scale", (char*)"(J)F", (void*)control_area_get_min_scale },
		{ (char*)"get_max_scale", (char*)"(J)F", (void*)control_area_get_max_scale },
		{ (char*)"set_horizontal_step", (char*)"(JD)V", (void*)control_area_set_horizontal_step },
		{ (char*)"set_vertical_step", (char*)"(JD)V", (void*)control_area_set_vertical_step },
		{ (char*)"set_step", (char*)"(JDD)V", (void*)control_area_set_step },
		{ (char*)"get_horizontal_step", (char*)"(J)D", (void*)control_area_get_horizontal_step },
		{ (char*)"get_vertical_step", (char*)"(J)D", (void*)control_area_get_vertical_step },
		{ (char*)"set_horizontal_value", (char*)"(JD)V", (void*)control_area_set_horizontal_value },
		{ (char*)"set_vertical_value", (char*)"(JD)V", (void*)control_area_set_vertical_value },
		{ (char*)"set_value", (char*)"(JDD)V", (void*)control_area_set_value },
		{ (char*)"get_horizontal_value", (char*)"(J)D", (void*)control_area_get_horizontal_value },
		{ (char*)"get_vertical_value", (char*)"(J)D", (void*)control_area_get_vertical_value },
		{ (char*)"set_frame_align", (char*)"(JI)V", (void*)control_area_set_frame_align },
		{ (char*)"get_frame_align", (char*)"(J)I", (void*)control_area_get_frame_align },
		{ (char*)"get_horizontal_frame", (char*)"(J)D", (void*)control_area_get_horizontal_frame },
		{ (char*)"get_vertical_frame", (char*)"(J)D", (void*)control_area_get_vertical_frame },
		{ (char*)"get_horizontal_range", (char*)"(J)D", (void*)control_area_get_horizontal_range },
		{ (char*)"get_vertical_range", (char*)"(J)D", (void*)control_area_get_vertical_range },
		{ (char*)"set_horizontal_enabled", (char*)"(JZZ)V", (void*)control_area_set_horizontal_enabled },
		{ (char*)"is_horizontal_enabled", (char*)"(J)Z", (void*)control_area_is_horizontal_enabled },
		{ (char*)"is_horizontal_dynamic", (char*)"(J)Z", (void*)control_area_is_horizontal_dynamic },
		{ (char*)"is_horizontal_hidden", (char*)"(J)Z", (void*)control_area_is_horizontal_hidden },
		{ (char*)"get_horizontal_scroll", (char*)"(J)J", (void*)control_area_get_horizontal_scroll },
		{ (char*)"get_horizontal_scroll_1", (char*)"(J)J", (void*)control_area_get_horizontal_scroll_1 },
		{ (char*)"set_vertical_enabled", (char*)"(JZZ)V", (void*)control_area_set_vertical_enabled },
		{ (char*)"is_vertical_enabled", (char*)"(J)Z", (void*)control_area_is_vertical_enabled },
		{ (char*)"is_vertical_dynamic", (char*)"(J)Z", (void*)control_area_is_vertical_dynamic },
		{ (char*)"is_vertical_hidden", (char*)"(J)Z", (void*)control_area_is_vertical_hidden },
		{ (char*)"get_vertical_scroll", (char*)"(J)J", (void*)control_area_get_vertical_scroll },
		{ (char*)"get_vertical_scroll_1", (char*)"(J)J", (void*)control_area_get_vertical_scroll_1 },
		{ (char*)"set_font_size", (char*)"(JI)Z", (void*)control_area_set_font_size },
		{ (char*)"get_font_size", (char*)"(J)I", (void*)control_area_get_font_size },
		{ (char*)"set_font_style", (char*)"(JJ)Z", (void*)control_area_set_font_style },
		{ (char*)"get_font_style_const", (char*)"(J)J", (void*)control_area_get_font_style_const },
		{ (char*)"get_font_style", (char*)"(J)J", (void*)control_area_get_font_style },
		{ (char*)"get_font_style_1", (char*)"(J)J", (void*)control_area_get_font_style_1 },
		{ (char*)"set_columns", (char*)"(JI)V", (void*)control_area_set_columns },
		{ (char*)"get_columns", (char*)"(J)I", (void*)control_area_get_columns },
		{ (char*)"set_spacing", (char*)"(JJ)V", (void*)control_area_set_spacing },
		{ (char*)"set_spacing_1", (char*)"(JFF)V", (void*)control_area_set_spacing_1 },
		{ (char*)"get_spacing", (char*)"(J)J", (void*)control_area_get_spacing },
		{ (char*)"set_column_ratio", (char*)"(JIF)V", (void*)control_area_set_column_ratio },
		{ (char*)"get_column_ratio", (char*)"(JI)F", (void*)control_area_get_column_ratio },
		{ (char*)"get_controls_size", (char*)"(J)J", (void*)control_area_get_controls_size },
		{ (char*)"get_controls_offset", (char*)"(J)J", (void*)control_area_get_controls_offset },
		{ (char*)"get_view_rect", (char*)"(J)J", (void*)control_area_get_view_rect },
	};
	
	// Tellusim::ControlTree
	static void control_tree_changed_callback_func(ControlTree a0, uint32_t item, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlTree$ChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JI)V");
			if(!clazz) TS_LOGF(Error, "control_tree_changed_callback_func(): can't find \"%s\" class\n", "ControlTree$ChangedCallback");
			else if(!method_id) TS_LOGF(Error, "control_tree_changed_callback_func(): can't get \"%s\" method\n", "(JI)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlTree(a0), (jint)item);
		}
	}
	static ControlTree::ChangedCallback make_control_tree_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_tree_changed_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return ControlTree::ChangedCallback();
	}
	static bool control_tree_dragged_callback_func(ControlTree a0, uint32_t item, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlTree$DraggedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JI)Z");
			if(!clazz) TS_LOGF(Error, "control_tree_dragged_callback_func(): can't find \"%s\" class\n", "ControlTree$DraggedCallback");
			else if(!method_id) TS_LOGF(Error, "control_tree_dragged_callback_func(): can't get \"%s\" method\n", "(JI)Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id, newControlTree(a0), (jint)item) != 0);
		}
		return false;
	}
	static ControlTree::DraggedCallback make_control_tree_dragged_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_tree_dragged_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return ControlTree::DraggedCallback();
	}
	static void control_tree_dropped_callback_func(ControlTree a0, uint32_t item, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlTree$DroppedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JI)V");
			if(!clazz) TS_LOGF(Error, "control_tree_dropped_callback_func(): can't find \"%s\" class\n", "ControlTree$DroppedCallback");
			else if(!method_id) TS_LOGF(Error, "control_tree_dropped_callback_func(): can't get \"%s\" method\n", "(JI)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlTree(a0), (jint)item);
		}
	}
	static ControlTree::DroppedCallback make_control_tree_dropped_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_tree_dropped_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return ControlTree::DroppedCallback();
	}
	static void control_tree_clicked_callback_func(ControlTree a0, uint32_t item, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlTree$ClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JI)V");
			if(!clazz) TS_LOGF(Error, "control_tree_clicked_callback_func(): can't find \"%s\" class\n", "ControlTree$ClickedCallback");
			else if(!method_id) TS_LOGF(Error, "control_tree_clicked_callback_func(): can't get \"%s\" method\n", "(JI)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlTree(a0), (jint)item);
		}
	}
	static ControlTree::ClickedCallback make_control_tree_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_tree_clicked_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return ControlTree::ClickedCallback();
	}
	static void control_tree_expanded_callback_func(ControlTree a0, uint32_t item, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlTree$ExpandedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JI)V");
			if(!clazz) TS_LOGF(Error, "control_tree_expanded_callback_func(): can't find \"%s\" class\n", "ControlTree$ExpandedCallback");
			else if(!method_id) TS_LOGF(Error, "control_tree_expanded_callback_func(): can't get \"%s\" method\n", "(JI)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlTree(a0), (jint)item);
		}
	}
	static ControlTree::ExpandedCallback make_control_tree_expanded_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_tree_expanded_callback_func);
			ret.setArg2(env);
			ret.setArg3(func);
			return ret;
		}
		return ControlTree::ExpandedCallback();
	}
	static void control_tree_selected_callback_func(ControlTree a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlTree$SelectedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_tree_selected_callback_func(): can't find \"%s\" class\n", "ControlTree$SelectedCallback");
			else if(!method_id) TS_LOGF(Error, "control_tree_selected_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlTree(a0));
		}
	}
	static ControlTree::SelectedCallback make_control_tree_selected_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_tree_selected_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlTree::SelectedCallback();
	}
	
	static jlong control_tree_new(TS_JNI_ARGS) {
		return newControlTree();
	}
	static jlong control_tree_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlTree(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_tree_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlTree*)self;
	}
	static jboolean control_tree_equal_control_text_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlTree(self).operator==(toControlText(base));
	}
	static jlong control_tree_cast_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlTree(toControlText(self));
	}
	static jlong control_tree_base_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlText(toControlTree(self).getControlText());
	}
	static void control_tree_set_selectable(TS_JNI_ARGS, jlong self, jboolean selectable) {
		toControlTree(self).setSelectable((bool)selectable);
	}
	static jboolean control_tree_is_selectable(TS_JNI_ARGS, jlong self) {
		return toControlTree(self).isSelectable();
	}
	static void control_tree_set_multi_selection(TS_JNI_ARGS, jlong self, jboolean multi_selection) {
		toControlTree(self).setMultiSelection((bool)multi_selection);
	}
	static jboolean control_tree_is_multi_selection(TS_JNI_ARGS, jlong self) {
		return toControlTree(self).isMultiSelection();
	}
	static void control_tree_set_folded_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlTree(self).setFoldedText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_tree_set_folded_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toControlTree(self).setFoldedText(toString(text));
	}
	static jstring control_tree_get_folded_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlTree(self).getFoldedText().get());
	}
	static void control_tree_set_expanded_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlTree(self).setExpandedText(text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_tree_set_expanded_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		toControlTree(self).setExpandedText(toString(text));
	}
	static jstring control_tree_get_expanded_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlTree(self).getExpandedText().get());
	}
	static void control_tree_set_texture(TS_JNI_ARGS, jlong self, jlong texture, jint rows, jint columns) {
		toControlTree(self).setTexture(toTexture(texture), (uint32_t)rows, (uint32_t)columns);
	}
	static jlong control_tree_get_texture(TS_JNI_ARGS, jlong self) {
		return newTexture(toControlTree(self).getTexture());
	}
	static void control_tree_set_texture_name(TS_JNI_ARGS, jlong self, jstring name, jint rows, jint columns) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toControlTree(self).setTextureName(name_, (uint32_t)rows, (uint32_t)columns);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void control_tree_set_texture_name_1(TS_JNI_ARGS, jlong self, jlong name, jint rows, jint columns) {
		toControlTree(self).setTextureName(toString(name), (uint32_t)rows, (uint32_t)columns);
	}
	static jstring control_tree_get_texture_name(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlTree(self).getTextureName().get());
	}
	static void control_tree_set_texture_grid(TS_JNI_ARGS, jlong self, jint rows, jint columns) {
		toControlTree(self).setTextureGrid((uint32_t)rows, (uint32_t)columns);
	}
	static jint control_tree_get_texture_rows(TS_JNI_ARGS, jlong self) {
		return toControlTree(self).getTextureRows();
	}
	static jint control_tree_get_texture_columns(TS_JNI_ARGS, jlong self) {
		return toControlTree(self).getTextureColumns();
	}
	static void control_tree_clear_items(TS_JNI_ARGS, jlong self) {
		toControlTree(self).clearItems();
	}
	static jint control_tree_add_item(TS_JNI_ARGS, jlong self, jstring text, jint parent, jboolean expanded) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		uint32_t ret_ = toControlTree(self).addItem(text_, (uint32_t)parent, (bool)expanded);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jint control_tree_add_item_1(TS_JNI_ARGS, jlong self, jlong text, jint parent, jboolean expanded) {
		return toControlTree(self).addItem(toString(text), (uint32_t)parent, (bool)expanded);
	}
	static void control_tree_remove_item(TS_JNI_ARGS, jlong self, jint item, jboolean children) {
		toControlTree(self).removeItem((uint32_t)item, (bool)children);
	}
	static void control_tree_view_item(TS_JNI_ARGS, jlong self, jint item) {
		toControlTree(self).viewItem((uint32_t)item);
	}
	static jint control_tree_get_num_items(TS_JNI_ARGS, jlong self) {
		return toControlTree(self).getNumItems();
	}
	static jint control_tree_get_item(TS_JNI_ARGS, jlong self, jint index) {
		return toControlTree(self).getItem((uint32_t)index);
	}
	static jboolean control_tree_switch_item_hidden(TS_JNI_ARGS, jlong self, jint item, jboolean children) {
		return toControlTree(self).switchItemHidden((uint32_t)item, (bool)children);
	}
	static void control_tree_set_item_hidden(TS_JNI_ARGS, jlong self, jint item, jboolean hidden, jboolean children) {
		toControlTree(self).setItemHidden((uint32_t)item, (bool)hidden, (bool)children);
	}
	static jboolean control_tree_is_item_hidden(TS_JNI_ARGS, jlong self, jint item) {
		return toControlTree(self).isItemHidden((uint32_t)item);
	}
	static jboolean control_tree_switch_item_expanded(TS_JNI_ARGS, jlong self, jint item, jboolean children) {
		return toControlTree(self).switchItemExpanded((uint32_t)item, (bool)children);
	}
	static void control_tree_set_item_expanded(TS_JNI_ARGS, jlong self, jint item, jboolean expanded, jboolean children) {
		toControlTree(self).setItemExpanded((uint32_t)item, (bool)expanded, (bool)children);
	}
	static jboolean control_tree_is_item_expanded(TS_JNI_ARGS, jlong self, jint item) {
		return toControlTree(self).isItemExpanded((uint32_t)item);
	}
	static jboolean control_tree_switch_item_selected(TS_JNI_ARGS, jlong self, jint item, jboolean children) {
		return toControlTree(self).switchItemSelected((uint32_t)item, (bool)children);
	}
	static void control_tree_set_item_selected(TS_JNI_ARGS, jlong self, jint item, jboolean selected, jboolean children) {
		toControlTree(self).setItemSelected((uint32_t)item, (bool)selected, (bool)children);
	}
	static jboolean control_tree_is_item_selected(TS_JNI_ARGS, jlong self, jint item) {
		return toControlTree(self).isItemSelected((uint32_t)item);
	}
	static void control_tree_set_item_parent(TS_JNI_ARGS, jlong self, jint item, jint parent) {
		toControlTree(self).setItemParent((uint32_t)item, (uint32_t)parent);
	}
	static jint control_tree_get_item_parent(TS_JNI_ARGS, jlong self, jint item) {
		return toControlTree(self).getItemParent((uint32_t)item);
	}
	static jboolean control_tree_is_item_parent(TS_JNI_ARGS, jlong self, jint item, jint parent, jboolean hierarchy) {
		return toControlTree(self).isItemParent((uint32_t)item, (uint32_t)parent, (bool)hierarchy);
	}
	static void control_tree_add_item_child(TS_JNI_ARGS, jlong self, jint item, jint child) {
		toControlTree(self).addItemChild((uint32_t)item, (uint32_t)child);
	}
	static void control_tree_remove_item_child(TS_JNI_ARGS, jlong self, jint item, jint child) {
		toControlTree(self).removeItemChild((uint32_t)item, (uint32_t)child);
	}
	static void control_tree_add_item_children(TS_JNI_ARGS, jlong self, jint item, jintArray children) {
		uint32_t *children__ = (uint32_t*)env->GetIntArrayElements(children, nullptr);
		Array<uint32_t> children_((uint32_t)env->GetArrayLength(children), children__);
		toControlTree(self).addItemChildren((uint32_t)item, children_);
		if(children_) env->ReleaseIntArrayElements(children, (jint*)children__, 0);
	}
	static void control_tree_remove_item_children(TS_JNI_ARGS, jlong self, jint item, jintArray children) {
		uint32_t *children__ = (uint32_t*)env->GetIntArrayElements(children, nullptr);
		Array<uint32_t> children_((uint32_t)env->GetArrayLength(children), children__);
		toControlTree(self).removeItemChildren((uint32_t)item, children_);
		if(children_) env->ReleaseIntArrayElements(children, (jint*)children__, 0);
	}
	static jint control_tree_find_item_child(TS_JNI_ARGS, jlong self, jint item, jint child) {
		return toControlTree(self).findItemChild((uint32_t)item, (uint32_t)child);
	}
	static jboolean control_tree_is_item_child(TS_JNI_ARGS, jlong self, jint item, jint child) {
		return toControlTree(self).isItemChild((uint32_t)item, (uint32_t)child);
	}
	static jint control_tree_get_num_item_children(TS_JNI_ARGS, jlong self, jint item) {
		return toControlTree(self).getNumItemChildren((uint32_t)item);
	}
	static jint control_tree_get_item_child(TS_JNI_ARGS, jlong self, jint item, jint index) {
		return toControlTree(self).getItemChild((uint32_t)item, (uint32_t)index);
	}
	static void control_tree_set_item_text(TS_JNI_ARGS, jlong self, jint item, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toControlTree(self).setItemText((uint32_t)item, text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void control_tree_set_item_text_1(TS_JNI_ARGS, jlong self, jint item, jlong text) {
		toControlTree(self).setItemText((uint32_t)item, toString(text));
	}
	static jstring control_tree_get_item_text(TS_JNI_ARGS, jlong self, jint item) {
		return env->NewStringUTF(toControlTree(self).getItemText((uint32_t)item).get());
	}
	static jint control_tree_find_item_text(TS_JNI_ARGS, jlong self, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		uint32_t ret_ = toControlTree(self).findItemText(text_);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jint control_tree_find_item_text_1(TS_JNI_ARGS, jlong self, jlong text) {
		return toControlTree(self).findItemText(toString(text));
	}
	static void control_tree_set_item_color(TS_JNI_ARGS, jlong self, jint item, jlong color) {
		toControlTree(self).setItemColor((uint32_t)item, toColor(color));
	}
	static jlong control_tree_get_item_color(TS_JNI_ARGS, jlong self, jint item) {
		return newColor(toControlTree(self).getItemColor((uint32_t)item));
	}
	static void control_tree_set_item_texture(TS_JNI_ARGS, jlong self, jint item, jint row, jint column) {
		toControlTree(self).setItemTexture((uint32_t)item, (uint32_t)row, (uint32_t)column);
	}
	static jint control_tree_get_item_texture_row(TS_JNI_ARGS, jlong self, jint item) {
		return toControlTree(self).getItemTextureRow((uint32_t)item);
	}
	static jint control_tree_get_item_texture_column(TS_JNI_ARGS, jlong self, jint item) {
		return toControlTree(self).getItemTextureColumn((uint32_t)item);
	}
	static void control_tree_set_item_user_data(TS_JNI_ARGS, jlong self, jint item, jlong data) {
		toControlTree(self).setItemUserData((uint32_t)item, (void*)data);
	}
	static jlong control_tree_get_item_user_data(TS_JNI_ARGS, jlong self, jint item) {
		return (jlong)toControlTree(self).getItemUserData((uint32_t)item);
	}
	static void control_tree_set_current_item(TS_JNI_ARGS, jlong self, jint item, jboolean select, jboolean view, jboolean callback) {
		toControlTree(self).setCurrentItem((uint32_t)item, (bool)select, (bool)view, (bool)callback);
	}
	static jint control_tree_get_current_item(TS_JNI_ARGS, jlong self) {
		return toControlTree(self).getCurrentItem();
	}
	static jstring control_tree_get_current_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlTree(self).getCurrentText().get());
	}
	static void control_tree_set_selection(TS_JNI_ARGS, jlong self) {
		toControlTree(self).setSelection();
	}
	static void control_tree_clear_selection(TS_JNI_ARGS, jlong self) {
		toControlTree(self).clearSelection();
	}
	static void control_tree_inverse_selection(TS_JNI_ARGS, jlong self) {
		toControlTree(self).inverseSelection();
	}
	static jint control_tree_get_num_selected_items(TS_JNI_ARGS, jlong self) {
		return toControlTree(self).getNumSelectedItems();
	}
	static jint control_tree_get_selected_item(TS_JNI_ARGS, jlong self, jint index) {
		return toControlTree(self).getSelectedItem((uint32_t)index);
	}
	static void control_tree_set_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlTree(self).setChangedCallback(make_control_tree_changed_callback(env, func));
	}
	static void control_tree_set_dragged_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlTree(self).setDraggedCallback(make_control_tree_dragged_callback(env, func));
	}
	static void control_tree_set_dropped_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlTree(self).setDroppedCallback(make_control_tree_dropped_callback(env, func));
	}
	static void control_tree_set_clicked_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlTree(self).setClickedCallback(make_control_tree_clicked_callback(env, func));
	}
	static void control_tree_set_clicked2_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlTree(self).setClicked2Callback(make_control_tree_clicked_callback(env, func));
	}
	static void control_tree_set_clicked_right_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlTree(self).setClickedRightCallback(make_control_tree_clicked_callback(env, func));
	}
	static void control_tree_set_expanded_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlTree(self).setExpandedCallback(make_control_tree_expanded_callback(env, func));
	}
	static void control_tree_set_selected_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlTree(self).setSelectedCallback(make_control_tree_selected_callback(env, func));
	}
	static const JNINativeMethod control_tree_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_tree_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_tree_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_tree_delete },
		{ (char*)"equal_control_text_ptr", (char*)"(JJ)Z", (void*)control_tree_equal_control_text_ptr },
		{ (char*)"cast_control_text_ptr", (char*)"(J)J", (void*)control_tree_cast_control_text_ptr },
		{ (char*)"base_control_text_ptr", (char*)"(J)J", (void*)control_tree_base_control_text_ptr },
		{ (char*)"set_selectable", (char*)"(JZ)V", (void*)control_tree_set_selectable },
		{ (char*)"is_selectable", (char*)"(J)Z", (void*)control_tree_is_selectable },
		{ (char*)"set_multi_selection", (char*)"(JZ)V", (void*)control_tree_set_multi_selection },
		{ (char*)"is_multi_selection", (char*)"(J)Z", (void*)control_tree_is_multi_selection },
		{ (char*)"set_folded_text", (char*)"(JLjava/lang/String;)V", (void*)control_tree_set_folded_text },
		{ (char*)"set_folded_text_1", (char*)"(JJ)V", (void*)control_tree_set_folded_text_1 },
		{ (char*)"get_folded_text", (char*)"(J)Ljava/lang/String;", (void*)control_tree_get_folded_text },
		{ (char*)"set_expanded_text", (char*)"(JLjava/lang/String;)V", (void*)control_tree_set_expanded_text },
		{ (char*)"set_expanded_text_1", (char*)"(JJ)V", (void*)control_tree_set_expanded_text_1 },
		{ (char*)"get_expanded_text", (char*)"(J)Ljava/lang/String;", (void*)control_tree_get_expanded_text },
		{ (char*)"set_texture", (char*)"(JJII)V", (void*)control_tree_set_texture },
		{ (char*)"get_texture", (char*)"(J)J", (void*)control_tree_get_texture },
		{ (char*)"set_texture_name", (char*)"(JLjava/lang/String;II)V", (void*)control_tree_set_texture_name },
		{ (char*)"set_texture_name_1", (char*)"(JJII)V", (void*)control_tree_set_texture_name_1 },
		{ (char*)"get_texture_name", (char*)"(J)Ljava/lang/String;", (void*)control_tree_get_texture_name },
		{ (char*)"set_texture_grid", (char*)"(JII)V", (void*)control_tree_set_texture_grid },
		{ (char*)"get_texture_rows", (char*)"(J)I", (void*)control_tree_get_texture_rows },
		{ (char*)"get_texture_columns", (char*)"(J)I", (void*)control_tree_get_texture_columns },
		{ (char*)"clear_items", (char*)"(J)V", (void*)control_tree_clear_items },
		{ (char*)"add_item", (char*)"(JLjava/lang/String;IZ)I", (void*)control_tree_add_item },
		{ (char*)"add_item_1", (char*)"(JJIZ)I", (void*)control_tree_add_item_1 },
		{ (char*)"remove_item", (char*)"(JIZ)V", (void*)control_tree_remove_item },
		{ (char*)"view_item", (char*)"(JI)V", (void*)control_tree_view_item },
		{ (char*)"get_num_items", (char*)"(J)I", (void*)control_tree_get_num_items },
		{ (char*)"get_item", (char*)"(JI)I", (void*)control_tree_get_item },
		{ (char*)"switch_item_hidden", (char*)"(JIZ)Z", (void*)control_tree_switch_item_hidden },
		{ (char*)"set_item_hidden", (char*)"(JIZZ)V", (void*)control_tree_set_item_hidden },
		{ (char*)"is_item_hidden", (char*)"(JI)Z", (void*)control_tree_is_item_hidden },
		{ (char*)"switch_item_expanded", (char*)"(JIZ)Z", (void*)control_tree_switch_item_expanded },
		{ (char*)"set_item_expanded", (char*)"(JIZZ)V", (void*)control_tree_set_item_expanded },
		{ (char*)"is_item_expanded", (char*)"(JI)Z", (void*)control_tree_is_item_expanded },
		{ (char*)"switch_item_selected", (char*)"(JIZ)Z", (void*)control_tree_switch_item_selected },
		{ (char*)"set_item_selected", (char*)"(JIZZ)V", (void*)control_tree_set_item_selected },
		{ (char*)"is_item_selected", (char*)"(JI)Z", (void*)control_tree_is_item_selected },
		{ (char*)"set_item_parent", (char*)"(JII)V", (void*)control_tree_set_item_parent },
		{ (char*)"get_item_parent", (char*)"(JI)I", (void*)control_tree_get_item_parent },
		{ (char*)"is_item_parent", (char*)"(JIIZ)Z", (void*)control_tree_is_item_parent },
		{ (char*)"add_item_child", (char*)"(JII)V", (void*)control_tree_add_item_child },
		{ (char*)"remove_item_child", (char*)"(JII)V", (void*)control_tree_remove_item_child },
		{ (char*)"add_item_children", (char*)"(JI[I)V", (void*)control_tree_add_item_children },
		{ (char*)"remove_item_children", (char*)"(JI[I)V", (void*)control_tree_remove_item_children },
		{ (char*)"find_item_child", (char*)"(JII)I", (void*)control_tree_find_item_child },
		{ (char*)"is_item_child", (char*)"(JII)Z", (void*)control_tree_is_item_child },
		{ (char*)"get_num_item_children", (char*)"(JI)I", (void*)control_tree_get_num_item_children },
		{ (char*)"get_item_child", (char*)"(JII)I", (void*)control_tree_get_item_child },
		{ (char*)"set_item_text", (char*)"(JILjava/lang/String;)V", (void*)control_tree_set_item_text },
		{ (char*)"set_item_text_1", (char*)"(JIJ)V", (void*)control_tree_set_item_text_1 },
		{ (char*)"get_item_text", (char*)"(JI)Ljava/lang/String;", (void*)control_tree_get_item_text },
		{ (char*)"find_item_text", (char*)"(JLjava/lang/String;)I", (void*)control_tree_find_item_text },
		{ (char*)"find_item_text_1", (char*)"(JJ)I", (void*)control_tree_find_item_text_1 },
		{ (char*)"set_item_color", (char*)"(JIJ)V", (void*)control_tree_set_item_color },
		{ (char*)"get_item_color", (char*)"(JI)J", (void*)control_tree_get_item_color },
		{ (char*)"set_item_texture", (char*)"(JIII)V", (void*)control_tree_set_item_texture },
		{ (char*)"get_item_texture_row", (char*)"(JI)I", (void*)control_tree_get_item_texture_row },
		{ (char*)"get_item_texture_column", (char*)"(JI)I", (void*)control_tree_get_item_texture_column },
		{ (char*)"set_item_user_data", (char*)"(JIJ)V", (void*)control_tree_set_item_user_data },
		{ (char*)"get_item_user_data", (char*)"(JI)J", (void*)control_tree_get_item_user_data },
		{ (char*)"set_current_item", (char*)"(JIZZZ)V", (void*)control_tree_set_current_item },
		{ (char*)"get_current_item", (char*)"(J)I", (void*)control_tree_get_current_item },
		{ (char*)"get_current_text", (char*)"(J)Ljava/lang/String;", (void*)control_tree_get_current_text },
		{ (char*)"set_selection", (char*)"(J)V", (void*)control_tree_set_selection },
		{ (char*)"clear_selection", (char*)"(J)V", (void*)control_tree_clear_selection },
		{ (char*)"inverse_selection", (char*)"(J)V", (void*)control_tree_inverse_selection },
		{ (char*)"get_num_selected_items", (char*)"(J)I", (void*)control_tree_get_num_selected_items },
		{ (char*)"get_selected_item", (char*)"(JI)I", (void*)control_tree_get_selected_item },
		{ (char*)"set_changed_callback", (char*)"(JL" TS_JNI_PREFIX "ControlTree$ChangedCallback;)V", (void*)control_tree_set_changed_callback },
		{ (char*)"set_dragged_callback", (char*)"(JL" TS_JNI_PREFIX "ControlTree$DraggedCallback;)V", (void*)control_tree_set_dragged_callback },
		{ (char*)"set_dropped_callback", (char*)"(JL" TS_JNI_PREFIX "ControlTree$DroppedCallback;)V", (void*)control_tree_set_dropped_callback },
		{ (char*)"set_clicked_callback", (char*)"(JL" TS_JNI_PREFIX "ControlTree$ClickedCallback;)V", (void*)control_tree_set_clicked_callback },
		{ (char*)"set_clicked2_callback", (char*)"(JL" TS_JNI_PREFIX "ControlTree$ClickedCallback;)V", (void*)control_tree_set_clicked2_callback },
		{ (char*)"set_clicked_right_callback", (char*)"(JL" TS_JNI_PREFIX "ControlTree$ClickedCallback;)V", (void*)control_tree_set_clicked_right_callback },
		{ (char*)"set_expanded_callback", (char*)"(JL" TS_JNI_PREFIX "ControlTree$ExpandedCallback;)V", (void*)control_tree_set_expanded_callback },
		{ (char*)"set_selected_callback", (char*)"(JL" TS_JNI_PREFIX "ControlTree$SelectedCallback;)V", (void*)control_tree_set_selected_callback },
	};
	
	// Tellusim::ControlEdit
	static void control_edit_clicked_callback_func(ControlEdit a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlEdit$ClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_edit_clicked_callback_func(): can't find \"%s\" class\n", "ControlEdit$ClickedCallback");
			else if(!method_id) TS_LOGF(Error, "control_edit_clicked_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlEdit(a0));
		}
	}
	static ControlEdit::ClickedCallback make_control_edit_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_edit_clicked_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlEdit::ClickedCallback();
	}
	static void control_edit_changed_callback_func(ControlEdit a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlEdit$ChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_edit_changed_callback_func(): can't find \"%s\" class\n", "ControlEdit$ChangedCallback");
			else if(!method_id) TS_LOGF(Error, "control_edit_changed_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlEdit(a0));
		}
	}
	static ControlEdit::ChangedCallback make_control_edit_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_edit_changed_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlEdit::ChangedCallback();
	}
	static void control_edit_returned_callback_func(ControlEdit a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "ControlEdit$ReturnedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "control_edit_returned_callback_func(): can't find \"%s\" class\n", "ControlEdit$ReturnedCallback");
			else if(!method_id) TS_LOGF(Error, "control_edit_returned_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newControlEdit(a0));
		}
	}
	static ControlEdit::ReturnedCallback make_control_edit_returned_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(control_edit_returned_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return ControlEdit::ReturnedCallback();
	}
	
	static jlong control_edit_new(TS_JNI_ARGS) {
		return newControlEdit();
	}
	static jlong control_edit_new_1(TS_JNI_ARGS, jlongArray parent) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlEdit(parent_.get());
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static jlong control_edit_new_2(TS_JNI_ARGS, jlongArray parent, jstring text) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		jlong ret_ = newControlEdit(parent_.get(), text_);
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		env->ReleaseStringUTFChars(text, text_);
		return ret_;
	}
	static jlong control_edit_new_3(TS_JNI_ARGS, jlongArray parent, jlong text) {
		Array<Control> parent_((uint32_t)env->GetArrayLength(parent));
		jlong *parent__ = env->GetLongArrayElements(parent, nullptr);
		for(uint32_t i = 0; i < parent_.size(); i++) parent_[i] = toControl(parent__[i]);
		jlong ret_ = newControlEdit(parent_.get(), toString(text));
		if(parent__) env->ReleaseLongArrayElements(parent, parent__, 0);
		return ret_;
	}
	static void control_edit_delete(TS_JNI_ARGS, jlong self) {
		delete (ControlEdit*)self;
	}
	static jboolean control_edit_equal_control_text_ptr(TS_JNI_ARGS, jlong self, jlong base) {
		return toControlEdit(self).operator==(toControlText(base));
	}
	static jlong control_edit_cast_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlEdit(toControlText(self));
	}
	static jlong control_edit_base_control_text_ptr(TS_JNI_ARGS, jlong self) {
		return newControlText(toControlEdit(self).getControlText());
	}
	static void control_edit_set_frame(TS_JNI_ARGS, jlong self, jboolean frame) {
		toControlEdit(self).setFrame((bool)frame);
	}
	static jboolean control_edit_get_frame(TS_JNI_ARGS, jlong self) {
		return toControlEdit(self).getFrame();
	}
	static void control_edit_set_background(TS_JNI_ARGS, jlong self, jboolean background) {
		toControlEdit(self).setBackground((bool)background);
	}
	static jboolean control_edit_get_background(TS_JNI_ARGS, jlong self) {
		return toControlEdit(self).getBackground();
	}
	static void control_edit_set_edit_color(TS_JNI_ARGS, jlong self, jlong color) {
		toControlEdit(self).setEditColor(toColor(color));
	}
	static jlong control_edit_get_edit_color(TS_JNI_ARGS, jlong self) {
		return newColor(toControlEdit(self).getEditColor());
	}
	static void control_edit_set_edit_mode(TS_JNI_ARGS, jlong self, jint mode) {
		toControlEdit(self).setEditMode((ControlEdit::EditMode)mode);
	}
	static jint control_edit_get_edit_mode(TS_JNI_ARGS, jlong self) {
		return toControlEdit(self).getEditMode();
	}
	static void control_edit_set_password_code(TS_JNI_ARGS, jlong self, jint code) {
		toControlEdit(self).setPasswordCode((uint32_t)code);
	}
	static jint control_edit_get_password_code(TS_JNI_ARGS, jlong self) {
		return toControlEdit(self).getPasswordCode();
	}
	static jint control_edit_get_num_codes(TS_JNI_ARGS, jlong self) {
		return toControlEdit(self).getNumCodes();
	}
	static jlong control_edit_get_codes(TS_JNI_ARGS, jlong self) {
		return (jlong)toControlEdit(self).getCodes();
	}
	static void control_edit_set_current_index(TS_JNI_ARGS, jlong self, jint index, jint selection_index) {
		toControlEdit(self).setCurrentIndex((uint32_t)index, (uint32_t)selection_index);
	}
	static jint control_edit_get_current_index(TS_JNI_ARGS, jlong self) {
		return toControlEdit(self).getCurrentIndex();
	}
	static jint control_edit_get_selection_index(TS_JNI_ARGS, jlong self) {
		return toControlEdit(self).getSelectionIndex();
	}
	static void control_edit_set_selection(TS_JNI_ARGS, jlong self, jboolean current) {
		toControlEdit(self).setSelection((bool)current);
	}
	static void control_edit_clear_selection(TS_JNI_ARGS, jlong self) {
		toControlEdit(self).clearSelection();
	}
	static jstring control_edit_get_selected_text(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toControlEdit(self).getSelectedText().get());
	}
	static void control_edit_set_clicked_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlEdit(self).setClickedCallback(make_control_edit_clicked_callback(env, func));
	}
	static jboolean control_edit_is_clicked(TS_JNI_ARGS, jlong self) {
		return toControlEdit(self).isClicked();
	}
	static void control_edit_set_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlEdit(self).setChangedCallback(make_control_edit_changed_callback(env, func));
	}
	static jboolean control_edit_is_changed(TS_JNI_ARGS, jlong self) {
		return toControlEdit(self).isChanged();
	}
	static void control_edit_set_returned_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toControlEdit(self).setReturnedCallback(make_control_edit_returned_callback(env, func));
	}
	static jboolean control_edit_is_returned(TS_JNI_ARGS, jlong self) {
		return toControlEdit(self).isReturned();
	}
	static jlong control_edit_get_canvas_mesh(TS_JNI_ARGS, jlong self) {
		return newCanvasMesh(toControlEdit(self).getCanvasMesh());
	}
	static const JNINativeMethod control_edit_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)control_edit_new },
		{ (char*)"new_1", (char*)"([J)J", (void*)control_edit_new_1 },
		{ (char*)"new_2", (char*)"([JLjava/lang/String;)J", (void*)control_edit_new_2 },
		{ (char*)"new_3", (char*)"([JJ)J", (void*)control_edit_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)control_edit_delete },
		{ (char*)"equal_control_text_ptr", (char*)"(JJ)Z", (void*)control_edit_equal_control_text_ptr },
		{ (char*)"cast_control_text_ptr", (char*)"(J)J", (void*)control_edit_cast_control_text_ptr },
		{ (char*)"base_control_text_ptr", (char*)"(J)J", (void*)control_edit_base_control_text_ptr },
		{ (char*)"set_frame", (char*)"(JZ)V", (void*)control_edit_set_frame },
		{ (char*)"get_frame", (char*)"(J)Z", (void*)control_edit_get_frame },
		{ (char*)"set_background", (char*)"(JZ)V", (void*)control_edit_set_background },
		{ (char*)"get_background", (char*)"(J)Z", (void*)control_edit_get_background },
		{ (char*)"set_edit_color", (char*)"(JJ)V", (void*)control_edit_set_edit_color },
		{ (char*)"get_edit_color", (char*)"(J)J", (void*)control_edit_get_edit_color },
		{ (char*)"set_edit_mode", (char*)"(JI)V", (void*)control_edit_set_edit_mode },
		{ (char*)"get_edit_mode", (char*)"(J)I", (void*)control_edit_get_edit_mode },
		{ (char*)"set_password_code", (char*)"(JI)V", (void*)control_edit_set_password_code },
		{ (char*)"get_password_code", (char*)"(J)I", (void*)control_edit_get_password_code },
		{ (char*)"get_num_codes", (char*)"(J)I", (void*)control_edit_get_num_codes },
		{ (char*)"get_codes", (char*)"(J)J", (void*)control_edit_get_codes },
		{ (char*)"set_current_index", (char*)"(JII)V", (void*)control_edit_set_current_index },
		{ (char*)"get_current_index", (char*)"(J)I", (void*)control_edit_get_current_index },
		{ (char*)"get_selection_index", (char*)"(J)I", (void*)control_edit_get_selection_index },
		{ (char*)"set_selection", (char*)"(JZ)V", (void*)control_edit_set_selection },
		{ (char*)"clear_selection", (char*)"(J)V", (void*)control_edit_clear_selection },
		{ (char*)"get_selected_text", (char*)"(J)Ljava/lang/String;", (void*)control_edit_get_selected_text },
		{ (char*)"set_clicked_callback", (char*)"(JL" TS_JNI_PREFIX "ControlEdit$ClickedCallback;)V", (void*)control_edit_set_clicked_callback },
		{ (char*)"is_clicked", (char*)"(J)Z", (void*)control_edit_is_clicked },
		{ (char*)"set_changed_callback", (char*)"(JL" TS_JNI_PREFIX "ControlEdit$ChangedCallback;)V", (void*)control_edit_set_changed_callback },
		{ (char*)"is_changed", (char*)"(J)Z", (void*)control_edit_is_changed },
		{ (char*)"set_returned_callback", (char*)"(JL" TS_JNI_PREFIX "ControlEdit$ReturnedCallback;)V", (void*)control_edit_set_returned_callback },
		{ (char*)"is_returned", (char*)"(J)Z", (void*)control_edit_is_returned },
		{ (char*)"get_canvas_mesh", (char*)"(J)J", (void*)control_edit_get_canvas_mesh },
	};
	
	// Tellusim::DialogMessage
	static bool dialog_message_update_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "DialogMessage$UpdateCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()Z");
			if(!clazz) TS_LOGF(Error, "dialog_message_update_callback_func(): can't find \"%s\" class\n", "DialogMessage$UpdateCallback");
			else if(!method_id) TS_LOGF(Error, "dialog_message_update_callback_func(): can't get \"%s\" method\n", "()Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id) != 0);
		}
		return false;
	}
	static DialogMessage::UpdateCallback make_dialog_message_update_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(dialog_message_update_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return DialogMessage::UpdateCallback();
	}
	
	static jlong dialog_message_new(TS_JNI_ARGS, jstring title, jstring message) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		const char *message_ = (message) ? env->GetStringUTFChars(message, nullptr) : nullptr;
		jlong ret_ = newDialogMessage(title_, message_);
		env->ReleaseStringUTFChars(title, title_);
		env->ReleaseStringUTFChars(message, message_);
		return ret_;
	}
	static jlong dialog_message_new_1(TS_JNI_ARGS, jlong title, jstring message) {
		const char *message_ = (message) ? env->GetStringUTFChars(message, nullptr) : nullptr;
		jlong ret_ = newDialogMessage(toString(title), message_);
		env->ReleaseStringUTFChars(message, message_);
		return ret_;
	}
	static jlong dialog_message_new_2(TS_JNI_ARGS, jstring title, jlong message) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		jlong ret_ = newDialogMessage(title_, toString(message));
		env->ReleaseStringUTFChars(title, title_);
		return ret_;
	}
	static jlong dialog_message_new_3(TS_JNI_ARGS, jlong title, jlong message) {
		return newDialogMessage(toString(title), toString(message));
	}
	static void dialog_message_delete(TS_JNI_ARGS, jlong self) {
		delete (DialogMessage*)self;
	}
	static jboolean dialog_message_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDialogMessage(self) == toDialogMessage(ptr));
	}
	static jlong dialog_message_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDialogMessage(toDialogMessage(self).clonePtr());
	}
	static void dialog_message_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDialogMessage(self).clearPtr();
	}
	static void dialog_message_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDialogMessage(self).destroyPtr();
	}
	static void dialog_message_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogMessage(self).acquirePtr();
	}
	static void dialog_message_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogMessage(self).unacquirePtr();
	}
	static jboolean dialog_message_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogMessage(self).isValidPtr();
	}
	static jboolean dialog_message_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogMessage(self).isOwnerPtr();
	}
	static jboolean dialog_message_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogMessage(self).isConstPtr();
	}
	static jint dialog_message_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogMessage(self).getCountPtr();
	}
	static jlong dialog_message_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDialogMessage(self).getInternalPtr();
	}
	static void dialog_message_set_position(TS_JNI_ARGS, jlong self, jint x, jint y) {
		toDialogMessage(self).setPosition(x, y);
	}
	static jint dialog_message_get_position_x(TS_JNI_ARGS, jlong self) {
		return toDialogMessage(self).getPositionX();
	}
	static jint dialog_message_get_position_y(TS_JNI_ARGS, jlong self) {
		return toDialogMessage(self).getPositionY();
	}
	static void dialog_message_set_title(TS_JNI_ARGS, jlong self, jstring title) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		toDialogMessage(self).setTitle(title_);
		env->ReleaseStringUTFChars(title, title_);
	}
	static void dialog_message_set_title_1(TS_JNI_ARGS, jlong self, jlong title) {
		toDialogMessage(self).setTitle(toString(title));
	}
	static jstring dialog_message_get_title(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogMessage(self).getTitle().get());
	}
	static void dialog_message_set_message(TS_JNI_ARGS, jlong self, jstring message) {
		const char *message_ = (message) ? env->GetStringUTFChars(message, nullptr) : nullptr;
		toDialogMessage(self).setMessage(message_);
		env->ReleaseStringUTFChars(message, message_);
	}
	static void dialog_message_set_message_1(TS_JNI_ARGS, jlong self, jlong message) {
		toDialogMessage(self).setMessage(toString(message));
	}
	static jstring dialog_message_get_message(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogMessage(self).getMessage().get());
	}
	static void dialog_message_set_update_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toDialogMessage(self).setUpdateCallback(make_dialog_message_update_callback(env, func));
	}
	static jint dialog_message_run(TS_JNI_ARGS, jlong self, jint flags) {
		return toDialogMessage(self).run((DialogMessage::Flags)flags);
	}
	static const JNINativeMethod dialog_message_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;Ljava/lang/String;)J", (void*)dialog_message_new },
		{ (char*)"new_1", (char*)"(JLjava/lang/String;)J", (void*)dialog_message_new_1 },
		{ (char*)"new_2", (char*)"(Ljava/lang/String;J)J", (void*)dialog_message_new_2 },
		{ (char*)"new_3", (char*)"(JJ)J", (void*)dialog_message_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)dialog_message_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)dialog_message_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)dialog_message_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)dialog_message_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)dialog_message_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)dialog_message_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)dialog_message_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)dialog_message_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)dialog_message_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)dialog_message_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)dialog_message_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)dialog_message_get_internal_ptr },
		{ (char*)"set_position", (char*)"(JII)V", (void*)dialog_message_set_position },
		{ (char*)"get_position_x", (char*)"(J)I", (void*)dialog_message_get_position_x },
		{ (char*)"get_position_y", (char*)"(J)I", (void*)dialog_message_get_position_y },
		{ (char*)"set_title", (char*)"(JLjava/lang/String;)V", (void*)dialog_message_set_title },
		{ (char*)"set_title_1", (char*)"(JJ)V", (void*)dialog_message_set_title_1 },
		{ (char*)"get_title", (char*)"(J)Ljava/lang/String;", (void*)dialog_message_get_title },
		{ (char*)"set_message", (char*)"(JLjava/lang/String;)V", (void*)dialog_message_set_message },
		{ (char*)"set_message_1", (char*)"(JJ)V", (void*)dialog_message_set_message_1 },
		{ (char*)"get_message", (char*)"(J)Ljava/lang/String;", (void*)dialog_message_get_message },
		{ (char*)"set_update_callback", (char*)"(JL" TS_JNI_PREFIX "DialogMessage$UpdateCallback;)V", (void*)dialog_message_set_update_callback },
		{ (char*)"run_", (char*)"(JI)I", (void*)dialog_message_run },
	};
	
	// Tellusim::DialogFileOpen
	static bool dialog_file_open_update_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "DialogFileOpen$UpdateCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()Z");
			if(!clazz) TS_LOGF(Error, "dialog_file_open_update_callback_func(): can't find \"%s\" class\n", "DialogFileOpen$UpdateCallback");
			else if(!method_id) TS_LOGF(Error, "dialog_file_open_update_callback_func(): can't get \"%s\" method\n", "()Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id) != 0);
		}
		return false;
	}
	static DialogFileOpen::UpdateCallback make_dialog_file_open_update_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(dialog_file_open_update_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return DialogFileOpen::UpdateCallback();
	}
	
	static jlong dialog_file_open_new(TS_JNI_ARGS, jstring title, jstring name) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newDialogFileOpen(title_, name_);
		env->ReleaseStringUTFChars(title, title_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong dialog_file_open_new_1(TS_JNI_ARGS, jlong title, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newDialogFileOpen(toString(title), name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong dialog_file_open_new_2(TS_JNI_ARGS, jstring title, jlong name) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		jlong ret_ = newDialogFileOpen(title_, toString(name));
		env->ReleaseStringUTFChars(title, title_);
		return ret_;
	}
	static jlong dialog_file_open_new_3(TS_JNI_ARGS, jlong title, jlong name) {
		return newDialogFileOpen(toString(title), toString(name));
	}
	static void dialog_file_open_delete(TS_JNI_ARGS, jlong self) {
		delete (DialogFileOpen*)self;
	}
	static jboolean dialog_file_open_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDialogFileOpen(self) == toDialogFileOpen(ptr));
	}
	static jlong dialog_file_open_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDialogFileOpen(toDialogFileOpen(self).clonePtr());
	}
	static void dialog_file_open_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDialogFileOpen(self).clearPtr();
	}
	static void dialog_file_open_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDialogFileOpen(self).destroyPtr();
	}
	static void dialog_file_open_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogFileOpen(self).acquirePtr();
	}
	static void dialog_file_open_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogFileOpen(self).unacquirePtr();
	}
	static jboolean dialog_file_open_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogFileOpen(self).isValidPtr();
	}
	static jboolean dialog_file_open_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogFileOpen(self).isOwnerPtr();
	}
	static jboolean dialog_file_open_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogFileOpen(self).isConstPtr();
	}
	static jint dialog_file_open_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogFileOpen(self).getCountPtr();
	}
	static jlong dialog_file_open_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDialogFileOpen(self).getInternalPtr();
	}
	static void dialog_file_open_set_position(TS_JNI_ARGS, jlong self, jint x, jint y) {
		toDialogFileOpen(self).setPosition(x, y);
	}
	static jint dialog_file_open_get_position_x(TS_JNI_ARGS, jlong self) {
		return toDialogFileOpen(self).getPositionX();
	}
	static jint dialog_file_open_get_position_y(TS_JNI_ARGS, jlong self) {
		return toDialogFileOpen(self).getPositionY();
	}
	static void dialog_file_open_set_title(TS_JNI_ARGS, jlong self, jstring title) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		toDialogFileOpen(self).setTitle(title_);
		env->ReleaseStringUTFChars(title, title_);
	}
	static void dialog_file_open_set_title_1(TS_JNI_ARGS, jlong self, jlong title) {
		toDialogFileOpen(self).setTitle(toString(title));
	}
	static jstring dialog_file_open_get_title(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogFileOpen(self).getTitle().get());
	}
	static void dialog_file_open_set_filter(TS_JNI_ARGS, jlong self, jstring filter) {
		const char *filter_ = (filter) ? env->GetStringUTFChars(filter, nullptr) : nullptr;
		toDialogFileOpen(self).setFilter(filter_);
		env->ReleaseStringUTFChars(filter, filter_);
	}
	static void dialog_file_open_set_filter_1(TS_JNI_ARGS, jlong self, jlong filter) {
		toDialogFileOpen(self).setFilter(toString(filter));
	}
	static jstring dialog_file_open_get_filter(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogFileOpen(self).getFilter().get());
	}
	static void dialog_file_open_set_file(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toDialogFileOpen(self).setFile(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void dialog_file_open_set_file_1(TS_JNI_ARGS, jlong self, jlong name) {
		toDialogFileOpen(self).setFile(toString(name));
	}
	static jstring dialog_file_open_get_file(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogFileOpen(self).getFile().get());
	}
	static void dialog_file_open_set_update_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toDialogFileOpen(self).setUpdateCallback(make_dialog_file_open_update_callback(env, func));
	}
	static jint dialog_file_open_run(TS_JNI_ARGS, jlong self, jint flags) {
		return toDialogFileOpen(self).run((DialogFileOpen::Flags)flags);
	}
	static const JNINativeMethod dialog_file_open_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;Ljava/lang/String;)J", (void*)dialog_file_open_new },
		{ (char*)"new_1", (char*)"(JLjava/lang/String;)J", (void*)dialog_file_open_new_1 },
		{ (char*)"new_2", (char*)"(Ljava/lang/String;J)J", (void*)dialog_file_open_new_2 },
		{ (char*)"new_3", (char*)"(JJ)J", (void*)dialog_file_open_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)dialog_file_open_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)dialog_file_open_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)dialog_file_open_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)dialog_file_open_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)dialog_file_open_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)dialog_file_open_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)dialog_file_open_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)dialog_file_open_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)dialog_file_open_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)dialog_file_open_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)dialog_file_open_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)dialog_file_open_get_internal_ptr },
		{ (char*)"set_position", (char*)"(JII)V", (void*)dialog_file_open_set_position },
		{ (char*)"get_position_x", (char*)"(J)I", (void*)dialog_file_open_get_position_x },
		{ (char*)"get_position_y", (char*)"(J)I", (void*)dialog_file_open_get_position_y },
		{ (char*)"set_title", (char*)"(JLjava/lang/String;)V", (void*)dialog_file_open_set_title },
		{ (char*)"set_title_1", (char*)"(JJ)V", (void*)dialog_file_open_set_title_1 },
		{ (char*)"get_title", (char*)"(J)Ljava/lang/String;", (void*)dialog_file_open_get_title },
		{ (char*)"set_filter", (char*)"(JLjava/lang/String;)V", (void*)dialog_file_open_set_filter },
		{ (char*)"set_filter_1", (char*)"(JJ)V", (void*)dialog_file_open_set_filter_1 },
		{ (char*)"get_filter", (char*)"(J)Ljava/lang/String;", (void*)dialog_file_open_get_filter },
		{ (char*)"set_file", (char*)"(JLjava/lang/String;)V", (void*)dialog_file_open_set_file },
		{ (char*)"set_file_1", (char*)"(JJ)V", (void*)dialog_file_open_set_file_1 },
		{ (char*)"get_file", (char*)"(J)Ljava/lang/String;", (void*)dialog_file_open_get_file },
		{ (char*)"set_update_callback", (char*)"(JL" TS_JNI_PREFIX "DialogFileOpen$UpdateCallback;)V", (void*)dialog_file_open_set_update_callback },
		{ (char*)"run_", (char*)"(JI)I", (void*)dialog_file_open_run },
	};
	
	// Tellusim::DialogFileSave
	static bool dialog_file_save_update_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "DialogFileSave$UpdateCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()Z");
			if(!clazz) TS_LOGF(Error, "dialog_file_save_update_callback_func(): can't find \"%s\" class\n", "DialogFileSave$UpdateCallback");
			else if(!method_id) TS_LOGF(Error, "dialog_file_save_update_callback_func(): can't get \"%s\" method\n", "()Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id) != 0);
		}
		return false;
	}
	static DialogFileSave::UpdateCallback make_dialog_file_save_update_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(dialog_file_save_update_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return DialogFileSave::UpdateCallback();
	}
	
	static jlong dialog_file_save_new(TS_JNI_ARGS, jstring title, jstring name) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newDialogFileSave(title_, name_);
		env->ReleaseStringUTFChars(title, title_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong dialog_file_save_new_1(TS_JNI_ARGS, jlong title, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newDialogFileSave(toString(title), name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong dialog_file_save_new_2(TS_JNI_ARGS, jstring title, jlong name) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		jlong ret_ = newDialogFileSave(title_, toString(name));
		env->ReleaseStringUTFChars(title, title_);
		return ret_;
	}
	static jlong dialog_file_save_new_3(TS_JNI_ARGS, jlong title, jlong name) {
		return newDialogFileSave(toString(title), toString(name));
	}
	static void dialog_file_save_delete(TS_JNI_ARGS, jlong self) {
		delete (DialogFileSave*)self;
	}
	static jboolean dialog_file_save_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDialogFileSave(self) == toDialogFileSave(ptr));
	}
	static jlong dialog_file_save_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDialogFileSave(toDialogFileSave(self).clonePtr());
	}
	static void dialog_file_save_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDialogFileSave(self).clearPtr();
	}
	static void dialog_file_save_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDialogFileSave(self).destroyPtr();
	}
	static void dialog_file_save_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogFileSave(self).acquirePtr();
	}
	static void dialog_file_save_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogFileSave(self).unacquirePtr();
	}
	static jboolean dialog_file_save_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogFileSave(self).isValidPtr();
	}
	static jboolean dialog_file_save_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogFileSave(self).isOwnerPtr();
	}
	static jboolean dialog_file_save_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogFileSave(self).isConstPtr();
	}
	static jint dialog_file_save_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogFileSave(self).getCountPtr();
	}
	static jlong dialog_file_save_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDialogFileSave(self).getInternalPtr();
	}
	static void dialog_file_save_set_position(TS_JNI_ARGS, jlong self, jint x, jint y) {
		toDialogFileSave(self).setPosition(x, y);
	}
	static jint dialog_file_save_get_position_x(TS_JNI_ARGS, jlong self) {
		return toDialogFileSave(self).getPositionX();
	}
	static jint dialog_file_save_get_position_y(TS_JNI_ARGS, jlong self) {
		return toDialogFileSave(self).getPositionY();
	}
	static void dialog_file_save_set_title(TS_JNI_ARGS, jlong self, jstring title) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		toDialogFileSave(self).setTitle(title_);
		env->ReleaseStringUTFChars(title, title_);
	}
	static void dialog_file_save_set_title_1(TS_JNI_ARGS, jlong self, jlong title) {
		toDialogFileSave(self).setTitle(toString(title));
	}
	static jstring dialog_file_save_get_title(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogFileSave(self).getTitle().get());
	}
	static void dialog_file_save_set_filter(TS_JNI_ARGS, jlong self, jstring filter) {
		const char *filter_ = (filter) ? env->GetStringUTFChars(filter, nullptr) : nullptr;
		toDialogFileSave(self).setFilter(filter_);
		env->ReleaseStringUTFChars(filter, filter_);
	}
	static void dialog_file_save_set_filter_1(TS_JNI_ARGS, jlong self, jlong filter) {
		toDialogFileSave(self).setFilter(toString(filter));
	}
	static jstring dialog_file_save_get_filter(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogFileSave(self).getFilter().get());
	}
	static void dialog_file_save_set_file(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toDialogFileSave(self).setFile(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void dialog_file_save_set_file_1(TS_JNI_ARGS, jlong self, jlong name) {
		toDialogFileSave(self).setFile(toString(name));
	}
	static jstring dialog_file_save_get_file(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogFileSave(self).getFile().get());
	}
	static void dialog_file_save_set_update_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toDialogFileSave(self).setUpdateCallback(make_dialog_file_save_update_callback(env, func));
	}
	static jint dialog_file_save_run(TS_JNI_ARGS, jlong self, jint flags) {
		return toDialogFileSave(self).run((DialogFileSave::Flags)flags);
	}
	static const JNINativeMethod dialog_file_save_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;Ljava/lang/String;)J", (void*)dialog_file_save_new },
		{ (char*)"new_1", (char*)"(JLjava/lang/String;)J", (void*)dialog_file_save_new_1 },
		{ (char*)"new_2", (char*)"(Ljava/lang/String;J)J", (void*)dialog_file_save_new_2 },
		{ (char*)"new_3", (char*)"(JJ)J", (void*)dialog_file_save_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)dialog_file_save_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)dialog_file_save_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)dialog_file_save_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)dialog_file_save_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)dialog_file_save_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)dialog_file_save_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)dialog_file_save_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)dialog_file_save_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)dialog_file_save_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)dialog_file_save_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)dialog_file_save_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)dialog_file_save_get_internal_ptr },
		{ (char*)"set_position", (char*)"(JII)V", (void*)dialog_file_save_set_position },
		{ (char*)"get_position_x", (char*)"(J)I", (void*)dialog_file_save_get_position_x },
		{ (char*)"get_position_y", (char*)"(J)I", (void*)dialog_file_save_get_position_y },
		{ (char*)"set_title", (char*)"(JLjava/lang/String;)V", (void*)dialog_file_save_set_title },
		{ (char*)"set_title_1", (char*)"(JJ)V", (void*)dialog_file_save_set_title_1 },
		{ (char*)"get_title", (char*)"(J)Ljava/lang/String;", (void*)dialog_file_save_get_title },
		{ (char*)"set_filter", (char*)"(JLjava/lang/String;)V", (void*)dialog_file_save_set_filter },
		{ (char*)"set_filter_1", (char*)"(JJ)V", (void*)dialog_file_save_set_filter_1 },
		{ (char*)"get_filter", (char*)"(J)Ljava/lang/String;", (void*)dialog_file_save_get_filter },
		{ (char*)"set_file", (char*)"(JLjava/lang/String;)V", (void*)dialog_file_save_set_file },
		{ (char*)"set_file_1", (char*)"(JJ)V", (void*)dialog_file_save_set_file_1 },
		{ (char*)"get_file", (char*)"(J)Ljava/lang/String;", (void*)dialog_file_save_get_file },
		{ (char*)"set_update_callback", (char*)"(JL" TS_JNI_PREFIX "DialogFileSave$UpdateCallback;)V", (void*)dialog_file_save_set_update_callback },
		{ (char*)"run_", (char*)"(JI)I", (void*)dialog_file_save_run },
	};
	
	// Tellusim::DialogDirectory
	static bool dialog_directory_update_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "DialogDirectory$UpdateCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()Z");
			if(!clazz) TS_LOGF(Error, "dialog_directory_update_callback_func(): can't find \"%s\" class\n", "DialogDirectory$UpdateCallback");
			else if(!method_id) TS_LOGF(Error, "dialog_directory_update_callback_func(): can't get \"%s\" method\n", "()Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id) != 0);
		}
		return false;
	}
	static DialogDirectory::UpdateCallback make_dialog_directory_update_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(dialog_directory_update_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return DialogDirectory::UpdateCallback();
	}
	
	static jlong dialog_directory_new(TS_JNI_ARGS, jstring title, jstring name) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newDialogDirectory(title_, name_);
		env->ReleaseStringUTFChars(title, title_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong dialog_directory_new_1(TS_JNI_ARGS, jlong title, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		jlong ret_ = newDialogDirectory(toString(title), name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jlong dialog_directory_new_2(TS_JNI_ARGS, jstring title, jlong name) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		jlong ret_ = newDialogDirectory(title_, toString(name));
		env->ReleaseStringUTFChars(title, title_);
		return ret_;
	}
	static jlong dialog_directory_new_3(TS_JNI_ARGS, jlong title, jlong name) {
		return newDialogDirectory(toString(title), toString(name));
	}
	static void dialog_directory_delete(TS_JNI_ARGS, jlong self) {
		delete (DialogDirectory*)self;
	}
	static jboolean dialog_directory_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDialogDirectory(self) == toDialogDirectory(ptr));
	}
	static jlong dialog_directory_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDialogDirectory(toDialogDirectory(self).clonePtr());
	}
	static void dialog_directory_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDialogDirectory(self).clearPtr();
	}
	static void dialog_directory_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDialogDirectory(self).destroyPtr();
	}
	static void dialog_directory_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogDirectory(self).acquirePtr();
	}
	static void dialog_directory_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogDirectory(self).unacquirePtr();
	}
	static jboolean dialog_directory_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogDirectory(self).isValidPtr();
	}
	static jboolean dialog_directory_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogDirectory(self).isOwnerPtr();
	}
	static jboolean dialog_directory_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogDirectory(self).isConstPtr();
	}
	static jint dialog_directory_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogDirectory(self).getCountPtr();
	}
	static jlong dialog_directory_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDialogDirectory(self).getInternalPtr();
	}
	static void dialog_directory_set_position(TS_JNI_ARGS, jlong self, jint x, jint y) {
		toDialogDirectory(self).setPosition(x, y);
	}
	static jint dialog_directory_get_position_x(TS_JNI_ARGS, jlong self) {
		return toDialogDirectory(self).getPositionX();
	}
	static jint dialog_directory_get_position_y(TS_JNI_ARGS, jlong self) {
		return toDialogDirectory(self).getPositionY();
	}
	static void dialog_directory_set_title(TS_JNI_ARGS, jlong self, jstring title) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		toDialogDirectory(self).setTitle(title_);
		env->ReleaseStringUTFChars(title, title_);
	}
	static void dialog_directory_set_title_1(TS_JNI_ARGS, jlong self, jlong title) {
		toDialogDirectory(self).setTitle(toString(title));
	}
	static jstring dialog_directory_get_title(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogDirectory(self).getTitle().get());
	}
	static void dialog_directory_set_directory(TS_JNI_ARGS, jlong self, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		toDialogDirectory(self).setDirectory(name_);
		env->ReleaseStringUTFChars(name, name_);
	}
	static void dialog_directory_set_directory_1(TS_JNI_ARGS, jlong self, jlong name) {
		toDialogDirectory(self).setDirectory(toString(name));
	}
	static jstring dialog_directory_get_directory(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogDirectory(self).getDirectory().get());
	}
	static void dialog_directory_set_update_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toDialogDirectory(self).setUpdateCallback(make_dialog_directory_update_callback(env, func));
	}
	static jint dialog_directory_run(TS_JNI_ARGS, jlong self, jint flags) {
		return toDialogDirectory(self).run((DialogDirectory::Flags)flags);
	}
	static const JNINativeMethod dialog_directory_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;Ljava/lang/String;)J", (void*)dialog_directory_new },
		{ (char*)"new_1", (char*)"(JLjava/lang/String;)J", (void*)dialog_directory_new_1 },
		{ (char*)"new_2", (char*)"(Ljava/lang/String;J)J", (void*)dialog_directory_new_2 },
		{ (char*)"new_3", (char*)"(JJ)J", (void*)dialog_directory_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)dialog_directory_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)dialog_directory_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)dialog_directory_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)dialog_directory_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)dialog_directory_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)dialog_directory_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)dialog_directory_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)dialog_directory_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)dialog_directory_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)dialog_directory_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)dialog_directory_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)dialog_directory_get_internal_ptr },
		{ (char*)"set_position", (char*)"(JII)V", (void*)dialog_directory_set_position },
		{ (char*)"get_position_x", (char*)"(J)I", (void*)dialog_directory_get_position_x },
		{ (char*)"get_position_y", (char*)"(J)I", (void*)dialog_directory_get_position_y },
		{ (char*)"set_title", (char*)"(JLjava/lang/String;)V", (void*)dialog_directory_set_title },
		{ (char*)"set_title_1", (char*)"(JJ)V", (void*)dialog_directory_set_title_1 },
		{ (char*)"get_title", (char*)"(J)Ljava/lang/String;", (void*)dialog_directory_get_title },
		{ (char*)"set_directory", (char*)"(JLjava/lang/String;)V", (void*)dialog_directory_set_directory },
		{ (char*)"set_directory_1", (char*)"(JJ)V", (void*)dialog_directory_set_directory_1 },
		{ (char*)"get_directory", (char*)"(J)Ljava/lang/String;", (void*)dialog_directory_get_directory },
		{ (char*)"set_update_callback", (char*)"(JL" TS_JNI_PREFIX "DialogDirectory$UpdateCallback;)V", (void*)dialog_directory_set_update_callback },
		{ (char*)"run_", (char*)"(JI)I", (void*)dialog_directory_run },
	};
	
	// Tellusim::DialogProgress
	static jlong dialog_progress_new(TS_JNI_ARGS, jstring title, jstring message) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		const char *message_ = (message) ? env->GetStringUTFChars(message, nullptr) : nullptr;
		jlong ret_ = newDialogProgress(title_, message_);
		env->ReleaseStringUTFChars(title, title_);
		env->ReleaseStringUTFChars(message, message_);
		return ret_;
	}
	static jlong dialog_progress_new_1(TS_JNI_ARGS, jlong title, jstring message) {
		const char *message_ = (message) ? env->GetStringUTFChars(message, nullptr) : nullptr;
		jlong ret_ = newDialogProgress(toString(title), message_);
		env->ReleaseStringUTFChars(message, message_);
		return ret_;
	}
	static jlong dialog_progress_new_2(TS_JNI_ARGS, jstring title, jlong message) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		jlong ret_ = newDialogProgress(title_, toString(message));
		env->ReleaseStringUTFChars(title, title_);
		return ret_;
	}
	static jlong dialog_progress_new_3(TS_JNI_ARGS, jlong title, jlong message) {
		return newDialogProgress(toString(title), toString(message));
	}
	static void dialog_progress_delete(TS_JNI_ARGS, jlong self) {
		delete (DialogProgress*)self;
	}
	static jboolean dialog_progress_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDialogProgress(self) == toDialogProgress(ptr));
	}
	static jlong dialog_progress_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDialogProgress(toDialogProgress(self).clonePtr());
	}
	static void dialog_progress_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDialogProgress(self).clearPtr();
	}
	static void dialog_progress_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDialogProgress(self).destroyPtr();
	}
	static void dialog_progress_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogProgress(self).acquirePtr();
	}
	static void dialog_progress_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogProgress(self).unacquirePtr();
	}
	static jboolean dialog_progress_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogProgress(self).isValidPtr();
	}
	static jboolean dialog_progress_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogProgress(self).isOwnerPtr();
	}
	static jboolean dialog_progress_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogProgress(self).isConstPtr();
	}
	static jint dialog_progress_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogProgress(self).getCountPtr();
	}
	static jlong dialog_progress_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDialogProgress(self).getInternalPtr();
	}
	static void dialog_progress_set_position(TS_JNI_ARGS, jlong self, jint x, jint y) {
		toDialogProgress(self).setPosition(x, y);
	}
	static jint dialog_progress_get_position_x(TS_JNI_ARGS, jlong self) {
		return toDialogProgress(self).getPositionX();
	}
	static jint dialog_progress_get_position_y(TS_JNI_ARGS, jlong self) {
		return toDialogProgress(self).getPositionY();
	}
	static void dialog_progress_set_title(TS_JNI_ARGS, jlong self, jstring title) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		toDialogProgress(self).setTitle(title_);
		env->ReleaseStringUTFChars(title, title_);
	}
	static void dialog_progress_set_title_1(TS_JNI_ARGS, jlong self, jlong title) {
		toDialogProgress(self).setTitle(toString(title));
	}
	static jstring dialog_progress_get_title(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogProgress(self).getTitle().get());
	}
	static void dialog_progress_set_message(TS_JNI_ARGS, jlong self, jstring message) {
		const char *message_ = (message) ? env->GetStringUTFChars(message, nullptr) : nullptr;
		toDialogProgress(self).setMessage(message_);
		env->ReleaseStringUTFChars(message, message_);
	}
	static void dialog_progress_set_message_1(TS_JNI_ARGS, jlong self, jlong message) {
		toDialogProgress(self).setMessage(toString(message));
	}
	static jstring dialog_progress_get_message(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogProgress(self).getMessage().get());
	}
	static void dialog_progress_set_progress(TS_JNI_ARGS, jlong self, jint progress) {
		toDialogProgress(self).setProgress((uint32_t)progress);
	}
	static jint dialog_progress_get_progress(TS_JNI_ARGS, jlong self) {
		return toDialogProgress(self).getProgress();
	}
	static jint dialog_progress_run(TS_JNI_ARGS, jlong self, jint flags) {
		return toDialogProgress(self).run((DialogProgress::Flags)flags);
	}
	static void dialog_progress_close(TS_JNI_ARGS, jlong self) {
		toDialogProgress(self).close();
	}
	static const JNINativeMethod dialog_progress_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;Ljava/lang/String;)J", (void*)dialog_progress_new },
		{ (char*)"new_1", (char*)"(JLjava/lang/String;)J", (void*)dialog_progress_new_1 },
		{ (char*)"new_2", (char*)"(Ljava/lang/String;J)J", (void*)dialog_progress_new_2 },
		{ (char*)"new_3", (char*)"(JJ)J", (void*)dialog_progress_new_3 },
		{ (char*)"delete_", (char*)"(J)V", (void*)dialog_progress_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)dialog_progress_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)dialog_progress_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)dialog_progress_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)dialog_progress_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)dialog_progress_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)dialog_progress_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)dialog_progress_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)dialog_progress_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)dialog_progress_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)dialog_progress_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)dialog_progress_get_internal_ptr },
		{ (char*)"set_position", (char*)"(JII)V", (void*)dialog_progress_set_position },
		{ (char*)"get_position_x", (char*)"(J)I", (void*)dialog_progress_get_position_x },
		{ (char*)"get_position_y", (char*)"(J)I", (void*)dialog_progress_get_position_y },
		{ (char*)"set_title", (char*)"(JLjava/lang/String;)V", (void*)dialog_progress_set_title },
		{ (char*)"set_title_1", (char*)"(JJ)V", (void*)dialog_progress_set_title_1 },
		{ (char*)"get_title", (char*)"(J)Ljava/lang/String;", (void*)dialog_progress_get_title },
		{ (char*)"set_message", (char*)"(JLjava/lang/String;)V", (void*)dialog_progress_set_message },
		{ (char*)"set_message_1", (char*)"(JJ)V", (void*)dialog_progress_set_message_1 },
		{ (char*)"get_message", (char*)"(J)Ljava/lang/String;", (void*)dialog_progress_get_message },
		{ (char*)"set_progress", (char*)"(JI)V", (void*)dialog_progress_set_progress },
		{ (char*)"get_progress", (char*)"(J)I", (void*)dialog_progress_get_progress },
		{ (char*)"run_", (char*)"(JI)I", (void*)dialog_progress_run },
		{ (char*)"close_", (char*)"(J)V", (void*)dialog_progress_close },
	};
	
	// Tellusim::DialogColor
	static void dialog_color_changed_callback_func(Color a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "DialogColor$ChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(J)V");
			if(!clazz) TS_LOGF(Error, "dialog_color_changed_callback_func(): can't find \"%s\" class\n", "DialogColor$ChangedCallback");
			else if(!method_id) TS_LOGF(Error, "dialog_color_changed_callback_func(): can't get \"%s\" method\n", "(J)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, newColor(a0));
		}
	}
	static DialogColor::ChangedCallback make_dialog_color_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(dialog_color_changed_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return DialogColor::ChangedCallback();
	}
	static bool dialog_color_update_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "DialogColor$UpdateCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()Z");
			if(!clazz) TS_LOGF(Error, "dialog_color_update_callback_func(): can't find \"%s\" class\n", "DialogColor$UpdateCallback");
			else if(!method_id) TS_LOGF(Error, "dialog_color_update_callback_func(): can't get \"%s\" method\n", "()Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id) != 0);
		}
		return false;
	}
	static DialogColor::UpdateCallback make_dialog_color_update_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(dialog_color_update_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return DialogColor::UpdateCallback();
	}
	
	static jlong dialog_color_new(TS_JNI_ARGS, jstring title, jlong color) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		jlong ret_ = newDialogColor(title_, toColor(color));
		env->ReleaseStringUTFChars(title, title_);
		return ret_;
	}
	static jlong dialog_color_new_1(TS_JNI_ARGS, jlong title, jlong color) {
		return newDialogColor(toString(title), toColor(color));
	}
	static void dialog_color_delete(TS_JNI_ARGS, jlong self) {
		delete (DialogColor*)self;
	}
	static jboolean dialog_color_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDialogColor(self) == toDialogColor(ptr));
	}
	static jlong dialog_color_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDialogColor(toDialogColor(self).clonePtr());
	}
	static void dialog_color_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDialogColor(self).clearPtr();
	}
	static void dialog_color_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDialogColor(self).destroyPtr();
	}
	static void dialog_color_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogColor(self).acquirePtr();
	}
	static void dialog_color_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogColor(self).unacquirePtr();
	}
	static jboolean dialog_color_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogColor(self).isValidPtr();
	}
	static jboolean dialog_color_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogColor(self).isOwnerPtr();
	}
	static jboolean dialog_color_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogColor(self).isConstPtr();
	}
	static jint dialog_color_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogColor(self).getCountPtr();
	}
	static jlong dialog_color_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDialogColor(self).getInternalPtr();
	}
	static void dialog_color_set_position(TS_JNI_ARGS, jlong self, jint x, jint y) {
		toDialogColor(self).setPosition(x, y);
	}
	static jint dialog_color_get_position_x(TS_JNI_ARGS, jlong self) {
		return toDialogColor(self).getPositionX();
	}
	static jint dialog_color_get_position_y(TS_JNI_ARGS, jlong self) {
		return toDialogColor(self).getPositionY();
	}
	static void dialog_color_set_title(TS_JNI_ARGS, jlong self, jstring title) {
		const char *title_ = (title) ? env->GetStringUTFChars(title, nullptr) : nullptr;
		toDialogColor(self).setTitle(title_);
		env->ReleaseStringUTFChars(title, title_);
	}
	static void dialog_color_set_title_1(TS_JNI_ARGS, jlong self, jlong title) {
		toDialogColor(self).setTitle(toString(title));
	}
	static jstring dialog_color_get_title(TS_JNI_ARGS, jlong self) {
		return env->NewStringUTF(toDialogColor(self).getTitle().get());
	}
	static void dialog_color_set_color(TS_JNI_ARGS, jlong self, jlong color, jboolean callback) {
		toDialogColor(self).setColor(toColor(color), (bool)callback);
	}
	static jlong dialog_color_get_color(TS_JNI_ARGS, jlong self) {
		return newColor(toDialogColor(self).getColor());
	}
	static void dialog_color_set_changed_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toDialogColor(self).setChangedCallback(make_dialog_color_changed_callback(env, func));
	}
	static void dialog_color_set_update_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toDialogColor(self).setUpdateCallback(make_dialog_color_update_callback(env, func));
	}
	static jint dialog_color_run(TS_JNI_ARGS, jlong self, jint flags) {
		return toDialogColor(self).run((DialogColor::Flags)flags);
	}
	static const JNINativeMethod dialog_color_methods[] = {
		{ (char*)"new_", (char*)"(Ljava/lang/String;J)J", (void*)dialog_color_new },
		{ (char*)"new_1", (char*)"(JJ)J", (void*)dialog_color_new_1 },
		{ (char*)"delete_", (char*)"(J)V", (void*)dialog_color_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)dialog_color_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)dialog_color_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)dialog_color_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)dialog_color_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)dialog_color_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)dialog_color_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)dialog_color_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)dialog_color_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)dialog_color_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)dialog_color_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)dialog_color_get_internal_ptr },
		{ (char*)"set_position", (char*)"(JII)V", (void*)dialog_color_set_position },
		{ (char*)"get_position_x", (char*)"(J)I", (void*)dialog_color_get_position_x },
		{ (char*)"get_position_y", (char*)"(J)I", (void*)dialog_color_get_position_y },
		{ (char*)"set_title", (char*)"(JLjava/lang/String;)V", (void*)dialog_color_set_title },
		{ (char*)"set_title_1", (char*)"(JJ)V", (void*)dialog_color_set_title_1 },
		{ (char*)"get_title", (char*)"(J)Ljava/lang/String;", (void*)dialog_color_get_title },
		{ (char*)"set_color", (char*)"(JJZ)V", (void*)dialog_color_set_color },
		{ (char*)"get_color", (char*)"(J)J", (void*)dialog_color_get_color },
		{ (char*)"set_changed_callback", (char*)"(JL" TS_JNI_PREFIX "DialogColor$ChangedCallback;)V", (void*)dialog_color_set_changed_callback },
		{ (char*)"set_update_callback", (char*)"(JL" TS_JNI_PREFIX "DialogColor$UpdateCallback;)V", (void*)dialog_color_set_update_callback },
		{ (char*)"run_", (char*)"(JI)I", (void*)dialog_color_run },
	};
	
	// Tellusim::DialogMenu
	static void dialog_menu_clicked_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "DialogMenu$ClickedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()V");
			if(!clazz) TS_LOGF(Error, "dialog_menu_clicked_callback_func(): can't find \"%s\" class\n", "DialogMenu$ClickedCallback");
			else if(!method_id) TS_LOGF(Error, "dialog_menu_clicked_callback_func(): can't get \"%s\" method\n", "()V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id);
		}
	}
	static DialogMenu::ClickedCallback make_dialog_menu_clicked_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(dialog_menu_clicked_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return DialogMenu::ClickedCallback();
	}
	static void dialog_menu_changed_callback_func(bool a0, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "DialogMenu$ChangedCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(Z)V");
			if(!clazz) TS_LOGF(Error, "dialog_menu_changed_callback_func(): can't find \"%s\" class\n", "DialogMenu$ChangedCallback");
			else if(!method_id) TS_LOGF(Error, "dialog_menu_changed_callback_func(): can't get \"%s\" method\n", "(Z)V");
		}
		if(method_id) {
			env->CallVoidMethod(func, method_id, (jboolean)a0);
		}
	}
	static DialogMenu::ChangedCallback make_dialog_menu_changed_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(dialog_menu_changed_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return DialogMenu::ChangedCallback();
	}
	static bool dialog_menu_update_callback_func(JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "DialogMenu$UpdateCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "()Z");
			if(!clazz) TS_LOGF(Error, "dialog_menu_update_callback_func(): can't find \"%s\" class\n", "DialogMenu$UpdateCallback");
			else if(!method_id) TS_LOGF(Error, "dialog_menu_update_callback_func(): can't get \"%s\" method\n", "()Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id) != 0);
		}
		return false;
	}
	static DialogMenu::UpdateCallback make_dialog_menu_update_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(dialog_menu_update_callback_func);
			ret.setArg0(env);
			ret.setArg1(func);
			return ret;
		}
		return DialogMenu::UpdateCallback();
	}
	
	static jlong dialog_menu_new(TS_JNI_ARGS) {
		return newDialogMenu();
	}
	static void dialog_menu_delete(TS_JNI_ARGS, jlong self) {
		delete (DialogMenu*)self;
	}
	static jboolean dialog_menu_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDialogMenu(self) == toDialogMenu(ptr));
	}
	static jlong dialog_menu_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDialogMenu(toDialogMenu(self).clonePtr());
	}
	static void dialog_menu_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDialogMenu(self).clearPtr();
	}
	static void dialog_menu_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDialogMenu(self).destroyPtr();
	}
	static void dialog_menu_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogMenu(self).acquirePtr();
	}
	static void dialog_menu_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDialogMenu(self).unacquirePtr();
	}
	static jboolean dialog_menu_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogMenu(self).isValidPtr();
	}
	static jboolean dialog_menu_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogMenu(self).isOwnerPtr();
	}
	static jboolean dialog_menu_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogMenu(self).isConstPtr();
	}
	static jint dialog_menu_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDialogMenu(self).getCountPtr();
	}
	static jlong dialog_menu_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDialogMenu(self).getInternalPtr();
	}
	static void dialog_menu_set_position(TS_JNI_ARGS, jlong self, jint x, jint y) {
		toDialogMenu(self).setPosition(x, y);
	}
	static jint dialog_menu_get_position_x(TS_JNI_ARGS, jlong self) {
		return toDialogMenu(self).getPositionX();
	}
	static jint dialog_menu_get_position_y(TS_JNI_ARGS, jlong self) {
		return toDialogMenu(self).getPositionY();
	}
	static jint dialog_menu_get_num_items(TS_JNI_ARGS, jlong self) {
		return toDialogMenu(self).getNumItems();
	}
	static void dialog_menu_set_item_text(TS_JNI_ARGS, jlong self, jint index, jstring text) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		toDialogMenu(self).setItemText((uint32_t)index, text_);
		env->ReleaseStringUTFChars(text, text_);
	}
	static void dialog_menu_set_item_text_1(TS_JNI_ARGS, jlong self, jint index, jlong text) {
		toDialogMenu(self).setItemText((uint32_t)index, toString(text));
	}
	static jstring dialog_menu_get_item_text(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toDialogMenu(self).getItemText((uint32_t)index).get());
	}
	static void dialog_menu_set_item_key(TS_JNI_ARGS, jlong self, jint index, jstring key) {
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		toDialogMenu(self).setItemKey((uint32_t)index, key_);
		env->ReleaseStringUTFChars(key, key_);
	}
	static jstring dialog_menu_get_item_key(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toDialogMenu(self).getItemKey((uint32_t)index).get());
	}
	static void dialog_menu_set_item_image(TS_JNI_ARGS, jlong self, jint index, jlong image) {
		toDialogMenu(self).setItemImage((uint32_t)index, toImage(image));
	}
	static jlong dialog_menu_get_item_image(TS_JNI_ARGS, jlong self, jint index) {
		return newImage(toDialogMenu(self).getItemImage((uint32_t)index));
	}
	static void dialog_menu_set_item_checked(TS_JNI_ARGS, jlong self, jint index, jboolean checked, jboolean callback) {
		toDialogMenu(self).setItemChecked((uint32_t)index, (bool)checked, (bool)callback);
	}
	static jboolean dialog_menu_is_item_checked(TS_JNI_ARGS, jlong self, jint index) {
		return toDialogMenu(self).isItemChecked((uint32_t)index);
	}
	static void dialog_menu_set_item_enabled(TS_JNI_ARGS, jlong self, jint index, jboolean enabled) {
		toDialogMenu(self).setItemEnabled((uint32_t)index, (bool)enabled);
	}
	static jboolean dialog_menu_is_item_enabled(TS_JNI_ARGS, jlong self, jint index) {
		return toDialogMenu(self).isItemEnabled((uint32_t)index);
	}
	static void dialog_menu_set_item_hidden(TS_JNI_ARGS, jlong self, jint index, jboolean hidden) {
		toDialogMenu(self).setItemHidden((uint32_t)index, (bool)hidden);
	}
	static jboolean dialog_menu_is_item_hidden(TS_JNI_ARGS, jlong self, jint index) {
		return toDialogMenu(self).isItemHidden((uint32_t)index);
	}
	static void dialog_menu_set_items_group(TS_JNI_ARGS, jlong self, jint index, jint size) {
		toDialogMenu(self).setItemsGroup((uint32_t)index, (uint32_t)size);
	}
	static jint dialog_menu_get_item_group_index(TS_JNI_ARGS, jlong self, jint index) {
		return toDialogMenu(self).getItemGroupIndex((uint32_t)index);
	}
	static jint dialog_menu_get_item_group_size(TS_JNI_ARGS, jlong self, jint index) {
		return toDialogMenu(self).getItemGroupSize((uint32_t)index);
	}
	static jint dialog_menu_add_item(TS_JNI_ARGS, jlong self, jstring text, jstring key) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(text_, key_);
		env->ReleaseStringUTFChars(text, text_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_1(TS_JNI_ARGS, jlong self, jlong text, jstring key) {
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(toString(text), key_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_2(TS_JNI_ARGS, jlong self, jstring text, jlong image, jstring key) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(text_, toImage(image), key_);
		env->ReleaseStringUTFChars(text, text_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_3(TS_JNI_ARGS, jlong self, jlong text, jlong image, jstring key) {
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(toString(text), toImage(image), key_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_4(TS_JNI_ARGS, jlong self, jstring text, jobject func, jstring key) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(text_, make_dialog_menu_clicked_callback(env, func), key_);
		env->ReleaseStringUTFChars(text, text_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_5(TS_JNI_ARGS, jlong self, jlong text, jobject func, jstring key) {
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(toString(text), make_dialog_menu_clicked_callback(env, func), key_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_6(TS_JNI_ARGS, jlong self, jstring text, jlong image, jobject func, jstring key) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(text_, toImage(image), make_dialog_menu_clicked_callback(env, func), key_);
		env->ReleaseStringUTFChars(text, text_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_7(TS_JNI_ARGS, jlong self, jlong text, jlong image, jobject func, jstring key) {
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(toString(text), toImage(image), make_dialog_menu_clicked_callback(env, func), key_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_8(TS_JNI_ARGS, jlong self, jstring text, jboolean checked, jobject func, jstring key) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(text_, (bool)checked, make_dialog_menu_changed_callback(env, func), key_);
		env->ReleaseStringUTFChars(text, text_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_9(TS_JNI_ARGS, jlong self, jlong text, jboolean checked, jobject func, jstring key) {
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(toString(text), (bool)checked, make_dialog_menu_changed_callback(env, func), key_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_10(TS_JNI_ARGS, jlong self, jstring text, jlong image, jboolean checked, jobject func, jstring key) {
		const char *text_ = (text) ? env->GetStringUTFChars(text, nullptr) : nullptr;
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(text_, toImage(image), (bool)checked, make_dialog_menu_changed_callback(env, func), key_);
		env->ReleaseStringUTFChars(text, text_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static jint dialog_menu_add_item_11(TS_JNI_ARGS, jlong self, jlong text, jlong image, jboolean checked, jobject func, jstring key) {
		const char *key_ = (key) ? env->GetStringUTFChars(key, nullptr) : nullptr;
		uint32_t ret_ = toDialogMenu(self).addItem(toString(text), toImage(image), (bool)checked, make_dialog_menu_changed_callback(env, func), key_);
		env->ReleaseStringUTFChars(key, key_);
		return ret_;
	}
	static void dialog_menu_set_update_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toDialogMenu(self).setUpdateCallback(make_dialog_menu_update_callback(env, func));
	}
	static jint dialog_menu_run(TS_JNI_ARGS, jlong self, jint flags) {
		return toDialogMenu(self).run((DialogMenu::Flags)flags);
	}
	static const JNINativeMethod dialog_menu_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)dialog_menu_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)dialog_menu_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)dialog_menu_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)dialog_menu_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)dialog_menu_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)dialog_menu_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)dialog_menu_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)dialog_menu_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)dialog_menu_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)dialog_menu_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)dialog_menu_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)dialog_menu_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)dialog_menu_get_internal_ptr },
		{ (char*)"set_position", (char*)"(JII)V", (void*)dialog_menu_set_position },
		{ (char*)"get_position_x", (char*)"(J)I", (void*)dialog_menu_get_position_x },
		{ (char*)"get_position_y", (char*)"(J)I", (void*)dialog_menu_get_position_y },
		{ (char*)"get_num_items", (char*)"(J)I", (void*)dialog_menu_get_num_items },
		{ (char*)"set_item_text", (char*)"(JILjava/lang/String;)V", (void*)dialog_menu_set_item_text },
		{ (char*)"set_item_text_1", (char*)"(JIJ)V", (void*)dialog_menu_set_item_text_1 },
		{ (char*)"get_item_text", (char*)"(JI)Ljava/lang/String;", (void*)dialog_menu_get_item_text },
		{ (char*)"set_item_key", (char*)"(JILjava/lang/String;)V", (void*)dialog_menu_set_item_key },
		{ (char*)"get_item_key", (char*)"(JI)Ljava/lang/String;", (void*)dialog_menu_get_item_key },
		{ (char*)"set_item_image", (char*)"(JIJ)V", (void*)dialog_menu_set_item_image },
		{ (char*)"get_item_image", (char*)"(JI)J", (void*)dialog_menu_get_item_image },
		{ (char*)"set_item_checked", (char*)"(JIZZ)V", (void*)dialog_menu_set_item_checked },
		{ (char*)"is_item_checked", (char*)"(JI)Z", (void*)dialog_menu_is_item_checked },
		{ (char*)"set_item_enabled", (char*)"(JIZ)V", (void*)dialog_menu_set_item_enabled },
		{ (char*)"is_item_enabled", (char*)"(JI)Z", (void*)dialog_menu_is_item_enabled },
		{ (char*)"set_item_hidden", (char*)"(JIZ)V", (void*)dialog_menu_set_item_hidden },
		{ (char*)"is_item_hidden", (char*)"(JI)Z", (void*)dialog_menu_is_item_hidden },
		{ (char*)"set_items_group", (char*)"(JII)V", (void*)dialog_menu_set_items_group },
		{ (char*)"get_item_group_index", (char*)"(JI)I", (void*)dialog_menu_get_item_group_index },
		{ (char*)"get_item_group_size", (char*)"(JI)I", (void*)dialog_menu_get_item_group_size },
		{ (char*)"add_item", (char*)"(JLjava/lang/String;Ljava/lang/String;)I", (void*)dialog_menu_add_item },
		{ (char*)"add_item_1", (char*)"(JJLjava/lang/String;)I", (void*)dialog_menu_add_item_1 },
		{ (char*)"add_item_2", (char*)"(JLjava/lang/String;JLjava/lang/String;)I", (void*)dialog_menu_add_item_2 },
		{ (char*)"add_item_3", (char*)"(JJJLjava/lang/String;)I", (void*)dialog_menu_add_item_3 },
		{ (char*)"add_item_4", (char*)"(JLjava/lang/String;L" TS_JNI_PREFIX "DialogMenu$ClickedCallback;Ljava/lang/String;)I", (void*)dialog_menu_add_item_4 },
		{ (char*)"add_item_5", (char*)"(JJL" TS_JNI_PREFIX "DialogMenu$ClickedCallback;Ljava/lang/String;)I", (void*)dialog_menu_add_item_5 },
		{ (char*)"add_item_6", (char*)"(JLjava/lang/String;JL" TS_JNI_PREFIX "DialogMenu$ClickedCallback;Ljava/lang/String;)I", (void*)dialog_menu_add_item_6 },
		{ (char*)"add_item_7", (char*)"(JJJL" TS_JNI_PREFIX "DialogMenu$ClickedCallback;Ljava/lang/String;)I", (void*)dialog_menu_add_item_7 },
		{ (char*)"add_item_8", (char*)"(JLjava/lang/String;ZL" TS_JNI_PREFIX "DialogMenu$ChangedCallback;Ljava/lang/String;)I", (void*)dialog_menu_add_item_8 },
		{ (char*)"add_item_9", (char*)"(JJZL" TS_JNI_PREFIX "DialogMenu$ChangedCallback;Ljava/lang/String;)I", (void*)dialog_menu_add_item_9 },
		{ (char*)"add_item_10", (char*)"(JLjava/lang/String;JZL" TS_JNI_PREFIX "DialogMenu$ChangedCallback;Ljava/lang/String;)I", (void*)dialog_menu_add_item_10 },
		{ (char*)"add_item_11", (char*)"(JJJZL" TS_JNI_PREFIX "DialogMenu$ChangedCallback;Ljava/lang/String;)I", (void*)dialog_menu_add_item_11 },
		{ (char*)"set_update_callback", (char*)"(JL" TS_JNI_PREFIX "DialogMenu$UpdateCallback;)V", (void*)dialog_menu_set_update_callback },
		{ (char*)"run_", (char*)"(JI)I", (void*)dialog_menu_run },
	};
	
	// Tellusim::CubeFilter
	static jlong cube_filter_new(TS_JNI_ARGS) {
		return newCubeFilter();
	}
	static void cube_filter_delete(TS_JNI_ARGS, jlong self) {
		delete (CubeFilter*)self;
	}
	static jboolean cube_filter_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toCubeFilter(self) == toCubeFilter(ptr));
	}
	static jlong cube_filter_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newCubeFilter(toCubeFilter(self).clonePtr());
	}
	static void cube_filter_clear_ptr(TS_JNI_ARGS, jlong self) {
		toCubeFilter(self).clearPtr();
	}
	static void cube_filter_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toCubeFilter(self).destroyPtr();
	}
	static void cube_filter_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toCubeFilter(self).acquirePtr();
	}
	static void cube_filter_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toCubeFilter(self).unacquirePtr();
	}
	static jboolean cube_filter_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toCubeFilter(self).isValidPtr();
	}
	static jboolean cube_filter_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toCubeFilter(self).isOwnerPtr();
	}
	static jboolean cube_filter_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toCubeFilter(self).isConstPtr();
	}
	static jint cube_filter_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toCubeFilter(self).getCountPtr();
	}
	static jlong cube_filter_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toCubeFilter(self).getInternalPtr();
	}
	static void cube_filter_clear(TS_JNI_ARGS, jlong self) {
		toCubeFilter(self).clear();
	}
	static jboolean cube_filter_is_created(TS_JNI_ARGS, jlong self, jint mode) {
		return toCubeFilter(self).isCreated((CubeFilter::Mode)mode);
	}
	static jint cube_filter_get_group_size(TS_JNI_ARGS, jlong self) {
		return toCubeFilter(self).getGroupSize();
	}
	static jint cube_filter_get_max_order(TS_JNI_ARGS, jlong self) {
		return toCubeFilter(self).getMaxOrder();
	}
	static jint cube_filter_get_max_size(TS_JNI_ARGS, jlong self) {
		return toCubeFilter(self).getMaxSize();
	}
	static jint cube_filter_get_harmonics(TS_JNI_ARGS, jlong self) {
		return toCubeFilter(self).getHarmonics();
	}
	static jboolean cube_filter_create(TS_JNI_ARGS, jlong self, jlong device, jint mode, jint order, jint size, jint groups) {
		return toCubeFilter(self).create(toDevice(device), (CubeFilter::Mode)mode, (uint32_t)order, (uint32_t)size, (uint32_t)groups);
	}
	static jboolean cube_filter_create_1(TS_JNI_ARGS, jlong self, jlong device, jint flags, jint order, jint size, jint groups) {
		return toCubeFilter(self).create(toDevice(device), (CubeFilter::Flags)flags, (uint32_t)order, (uint32_t)size, (uint32_t)groups);
	}
	static jboolean cube_filter_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jlong buffer, jint offset, jlong texture, jlong slice) {
		return toCubeFilter(self).dispatch(toCompute(compute), toBuffer(buffer), (uint32_t)offset, toTexture(texture), toSlice(slice));
	}
	static jboolean cube_filter_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jlong buffer, jint offset, jlong texture) {
		return toCubeFilter(self).dispatch(toCompute(compute), toBuffer(buffer), (uint32_t)offset, toTexture(texture));
	}
	static jboolean cube_filter_dispatch_2(TS_JNI_ARGS, jlong self, jlong compute, jlong texture, jlong slice, jlong buffer, jint offset) {
		return toCubeFilter(self).dispatch(toCompute(compute), toTexture(texture), toSlice(slice), toBuffer(buffer), (uint32_t)offset);
	}
	static jboolean cube_filter_dispatch_3(TS_JNI_ARGS, jlong self, jlong compute, jlong texture, jlong buffer, jint offset) {
		return toCubeFilter(self).dispatch(toCompute(compute), toTexture(texture), toBuffer(buffer), (uint32_t)offset);
	}
	static const JNINativeMethod cube_filter_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)cube_filter_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)cube_filter_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)cube_filter_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)cube_filter_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)cube_filter_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)cube_filter_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)cube_filter_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)cube_filter_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)cube_filter_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)cube_filter_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)cube_filter_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)cube_filter_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)cube_filter_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)cube_filter_clear },
		{ (char*)"is_created", (char*)"(JI)Z", (void*)cube_filter_is_created },
		{ (char*)"get_group_size", (char*)"(J)I", (void*)cube_filter_get_group_size },
		{ (char*)"get_max_order", (char*)"(J)I", (void*)cube_filter_get_max_order },
		{ (char*)"get_max_size", (char*)"(J)I", (void*)cube_filter_get_max_size },
		{ (char*)"get_harmonics", (char*)"(J)I", (void*)cube_filter_get_harmonics },
		{ (char*)"create_", (char*)"(JJIIII)Z", (void*)cube_filter_create },
		{ (char*)"create_1", (char*)"(JJIIII)Z", (void*)cube_filter_create_1 },
		{ (char*)"dispatch_", (char*)"(JJJIJJ)Z", (void*)cube_filter_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJJIJ)Z", (void*)cube_filter_dispatch_1 },
		{ (char*)"dispatch_2", (char*)"(JJJJJI)Z", (void*)cube_filter_dispatch_2 },
		{ (char*)"dispatch_3", (char*)"(JJJJI)Z", (void*)cube_filter_dispatch_3 },
	};
	
	// Tellusim::DecoderJPEG
	static jlong decoder_jpeg_new(TS_JNI_ARGS) {
		return newDecoderJPEG();
	}
	static void decoder_jpeg_delete(TS_JNI_ARGS, jlong self) {
		delete (DecoderJPEG*)self;
	}
	static jboolean decoder_jpeg_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDecoderJPEG(self) == toDecoderJPEG(ptr));
	}
	static jlong decoder_jpeg_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDecoderJPEG(toDecoderJPEG(self).clonePtr());
	}
	static void decoder_jpeg_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDecoderJPEG(self).clearPtr();
	}
	static void decoder_jpeg_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDecoderJPEG(self).destroyPtr();
	}
	static void decoder_jpeg_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDecoderJPEG(self).acquirePtr();
	}
	static void decoder_jpeg_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDecoderJPEG(self).unacquirePtr();
	}
	static jboolean decoder_jpeg_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDecoderJPEG(self).isValidPtr();
	}
	static jboolean decoder_jpeg_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDecoderJPEG(self).isOwnerPtr();
	}
	static jboolean decoder_jpeg_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDecoderJPEG(self).isConstPtr();
	}
	static jint decoder_jpeg_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDecoderJPEG(self).getCountPtr();
	}
	static jlong decoder_jpeg_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDecoderJPEG(self).getInternalPtr();
	}
	static void decoder_jpeg_clear(TS_JNI_ARGS, jlong self) {
		toDecoderJPEG(self).clear();
	}
	static jboolean decoder_jpeg_is_created(TS_JNI_ARGS, jlong self, jint mode) {
		return toDecoderJPEG(self).isCreated((DecoderJPEG::Mode)mode);
	}
	static jboolean decoder_jpeg_is_yuv(TS_JNI_ARGS, jint mode) {
		return DecoderJPEG::isYUV((DecoderJPEG::Mode)mode);
	}
	static jboolean decoder_jpeg_create(TS_JNI_ARGS, jlong self, jlong device, jint mode) {
		return toDecoderJPEG(self).create(toDevice(device), (DecoderJPEG::Mode)mode);
	}
	static jboolean decoder_jpeg_create_1(TS_JNI_ARGS, jlong self, jlong device, jint flags) {
		return toDecoderJPEG(self).create(toDevice(device), (DecoderJPEG::Flags)flags);
	}
	static jboolean decoder_jpeg_load(TS_JNI_ARGS, jstring name, jlong image, jint mode, jlong size) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = DecoderJPEG::load(name_, toImage(image), (DecoderJPEG::Mode&)mode, toSize(size));
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean decoder_jpeg_load_1(TS_JNI_ARGS, jlong stream, jlong image, jint mode, jlong size) {
		return DecoderJPEG::load(toStream(stream), toImage(image), (DecoderJPEG::Mode&)mode, toSize(size));
	}
	static jlong decoder_jpeg_load_texture(TS_JNI_ARGS, jlong self, jlong device, jstring name, jint flags) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Texture ret_ = toDecoderJPEG(self).loadTexture(toDevice(device), name_, (Texture::Flags)flags);
		env->ReleaseStringUTFChars(name, name_);
		return newTexture(ret_);
	}
	static jlong decoder_jpeg_load_texture_1(TS_JNI_ARGS, jlong self, jlong device, jlong stream, jint flags) {
		return newTexture(toDecoderJPEG(self).loadTexture(toDevice(device), toStream(stream), (Texture::Flags)flags));
	}
	static jboolean decoder_jpeg_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jlong dest_slice, jlong src_slice) {
		return toDecoderJPEG(self).dispatch(toCompute(compute), (DecoderJPEG::Mode)mode, toTexture(dest), toTexture(src), toSlice(dest_slice), toSlice(src_slice));
	}
	static jboolean decoder_jpeg_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jlong src_slice) {
		return toDecoderJPEG(self).dispatch(toCompute(compute), (DecoderJPEG::Mode)mode, toTexture(dest), toTexture(src), toSlice(src_slice));
	}
	static jboolean decoder_jpeg_dispatch_2(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src) {
		return toDecoderJPEG(self).dispatch(toCompute(compute), (DecoderJPEG::Mode)mode, toTexture(dest), toTexture(src));
	}
	static jboolean decoder_jpeg_dispatch_yuv(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jlong dest_slice, jlong src_slice) {
		return toDecoderJPEG(self).dispatchYUV(toCompute(compute), (DecoderJPEG::Mode)mode, toTexture(dest), toTexture(src), toSlice(dest_slice), toSlice(src_slice));
	}
	static jboolean decoder_jpeg_dispatch_yuv_1(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jlong src_slice) {
		return toDecoderJPEG(self).dispatchYUV(toCompute(compute), (DecoderJPEG::Mode)mode, toTexture(dest), toTexture(src), toSlice(src_slice));
	}
	static jboolean decoder_jpeg_dispatch_yuv_2(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src) {
		return toDecoderJPEG(self).dispatchYUV(toCompute(compute), (DecoderJPEG::Mode)mode, toTexture(dest), toTexture(src));
	}
	static const JNINativeMethod decoder_jpeg_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)decoder_jpeg_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)decoder_jpeg_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)decoder_jpeg_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)decoder_jpeg_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)decoder_jpeg_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)decoder_jpeg_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)decoder_jpeg_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)decoder_jpeg_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)decoder_jpeg_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)decoder_jpeg_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)decoder_jpeg_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)decoder_jpeg_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)decoder_jpeg_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)decoder_jpeg_clear },
		{ (char*)"is_created", (char*)"(JI)Z", (void*)decoder_jpeg_is_created },
		{ (char*)"is_yuv", (char*)"(I)Z", (void*)decoder_jpeg_is_yuv },
		{ (char*)"create_", (char*)"(JJI)Z", (void*)decoder_jpeg_create },
		{ (char*)"create_1", (char*)"(JJI)Z", (void*)decoder_jpeg_create_1 },
		{ (char*)"load_", (char*)"(Ljava/lang/String;JIJ)Z", (void*)decoder_jpeg_load },
		{ (char*)"load_1", (char*)"(JJIJ)Z", (void*)decoder_jpeg_load_1 },
		{ (char*)"load_texture", (char*)"(JJLjava/lang/String;I)J", (void*)decoder_jpeg_load_texture },
		{ (char*)"load_texture_1", (char*)"(JJJI)J", (void*)decoder_jpeg_load_texture_1 },
		{ (char*)"dispatch_", (char*)"(JJIJJJJ)Z", (void*)decoder_jpeg_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJIJJJ)Z", (void*)decoder_jpeg_dispatch_1 },
		{ (char*)"dispatch_2", (char*)"(JJIJJ)Z", (void*)decoder_jpeg_dispatch_2 },
		{ (char*)"dispatch_yuv", (char*)"(JJIJJJJ)Z", (void*)decoder_jpeg_dispatch_yuv },
		{ (char*)"dispatch_yuv_1", (char*)"(JJIJJJ)Z", (void*)decoder_jpeg_dispatch_yuv_1 },
		{ (char*)"dispatch_yuv_2", (char*)"(JJIJJ)Z", (void*)decoder_jpeg_dispatch_yuv_2 },
	};
	
	// Tellusim::EncoderBC15
	static jlong encoder_bc15_new(TS_JNI_ARGS) {
		return newEncoderBC15();
	}
	static void encoder_bc15_delete(TS_JNI_ARGS, jlong self) {
		delete (EncoderBC15*)self;
	}
	static jboolean encoder_bc15_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toEncoderBC15(self) == toEncoderBC15(ptr));
	}
	static jlong encoder_bc15_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newEncoderBC15(toEncoderBC15(self).clonePtr());
	}
	static void encoder_bc15_clear_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderBC15(self).clearPtr();
	}
	static void encoder_bc15_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderBC15(self).destroyPtr();
	}
	static void encoder_bc15_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderBC15(self).acquirePtr();
	}
	static void encoder_bc15_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderBC15(self).unacquirePtr();
	}
	static jboolean encoder_bc15_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderBC15(self).isValidPtr();
	}
	static jboolean encoder_bc15_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderBC15(self).isOwnerPtr();
	}
	static jboolean encoder_bc15_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderBC15(self).isConstPtr();
	}
	static jint encoder_bc15_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderBC15(self).getCountPtr();
	}
	static jlong encoder_bc15_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toEncoderBC15(self).getInternalPtr();
	}
	static void encoder_bc15_clear(TS_JNI_ARGS, jlong self) {
		toEncoderBC15(self).clear();
	}
	static jboolean encoder_bc15_is_created(TS_JNI_ARGS, jlong self, jint mode) {
		return toEncoderBC15(self).isCreated((EncoderBC15::Mode)mode);
	}
	static jboolean encoder_bc15_create(TS_JNI_ARGS, jlong self, jlong device, jint mode) {
		return toEncoderBC15(self).create(toDevice(device), (EncoderBC15::Mode)mode);
	}
	static jboolean encoder_bc15_create_1(TS_JNI_ARGS, jlong self, jlong device, jint flags) {
		return toEncoderBC15(self).create(toDevice(device), (EncoderBC15::Flags)flags);
	}
	static jboolean encoder_bc15_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jlong dest_slice, jlong src_slice) {
		return toEncoderBC15(self).dispatch(toCompute(compute), (EncoderBC15::Mode)mode, toTexture(dest), toTexture(src), toSlice(dest_slice), toSlice(src_slice));
	}
	static jboolean encoder_bc15_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jlong src_slice) {
		return toEncoderBC15(self).dispatch(toCompute(compute), (EncoderBC15::Mode)mode, toTexture(dest), toTexture(src), toSlice(src_slice));
	}
	static jboolean encoder_bc15_dispatch_2(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src) {
		return toEncoderBC15(self).dispatch(toCompute(compute), (EncoderBC15::Mode)mode, toTexture(dest), toTexture(src));
	}
	static const JNINativeMethod encoder_bc15_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)encoder_bc15_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)encoder_bc15_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)encoder_bc15_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)encoder_bc15_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)encoder_bc15_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)encoder_bc15_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)encoder_bc15_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)encoder_bc15_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)encoder_bc15_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)encoder_bc15_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)encoder_bc15_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)encoder_bc15_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)encoder_bc15_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)encoder_bc15_clear },
		{ (char*)"is_created", (char*)"(JI)Z", (void*)encoder_bc15_is_created },
		{ (char*)"create_", (char*)"(JJI)Z", (void*)encoder_bc15_create },
		{ (char*)"create_1", (char*)"(JJI)Z", (void*)encoder_bc15_create_1 },
		{ (char*)"dispatch_", (char*)"(JJIJJJJ)Z", (void*)encoder_bc15_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJIJJJ)Z", (void*)encoder_bc15_dispatch_1 },
		{ (char*)"dispatch_2", (char*)"(JJIJJ)Z", (void*)encoder_bc15_dispatch_2 },
	};
	
	// Tellusim::EncoderBC67
	static jlong encoder_bc67_new(TS_JNI_ARGS) {
		return newEncoderBC67();
	}
	static void encoder_bc67_delete(TS_JNI_ARGS, jlong self) {
		delete (EncoderBC67*)self;
	}
	static jboolean encoder_bc67_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toEncoderBC67(self) == toEncoderBC67(ptr));
	}
	static jlong encoder_bc67_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newEncoderBC67(toEncoderBC67(self).clonePtr());
	}
	static void encoder_bc67_clear_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderBC67(self).clearPtr();
	}
	static void encoder_bc67_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderBC67(self).destroyPtr();
	}
	static void encoder_bc67_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderBC67(self).acquirePtr();
	}
	static void encoder_bc67_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderBC67(self).unacquirePtr();
	}
	static jboolean encoder_bc67_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderBC67(self).isValidPtr();
	}
	static jboolean encoder_bc67_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderBC67(self).isOwnerPtr();
	}
	static jboolean encoder_bc67_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderBC67(self).isConstPtr();
	}
	static jint encoder_bc67_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderBC67(self).getCountPtr();
	}
	static jlong encoder_bc67_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toEncoderBC67(self).getInternalPtr();
	}
	static void encoder_bc67_clear(TS_JNI_ARGS, jlong self) {
		toEncoderBC67(self).clear();
	}
	static jboolean encoder_bc67_is_created(TS_JNI_ARGS, jlong self, jint mode) {
		return toEncoderBC67(self).isCreated((EncoderBC67::Mode)mode);
	}
	static jboolean encoder_bc67_create(TS_JNI_ARGS, jlong self, jlong device, jint mode) {
		return toEncoderBC67(self).create(toDevice(device), (EncoderBC67::Mode)mode);
	}
	static jboolean encoder_bc67_create_1(TS_JNI_ARGS, jlong self, jlong device, jint flags) {
		return toEncoderBC67(self).create(toDevice(device), (EncoderBC67::Flags)flags);
	}
	static jboolean encoder_bc67_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jlong dest_slice, jlong src_slice, jint components) {
		return toEncoderBC67(self).dispatch(toCompute(compute), (EncoderBC67::Mode)mode, toTexture(dest), toTexture(src), toSlice(dest_slice), toSlice(src_slice), (uint32_t)components);
	}
	static jboolean encoder_bc67_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jlong src_slice, jint components) {
		return toEncoderBC67(self).dispatch(toCompute(compute), (EncoderBC67::Mode)mode, toTexture(dest), toTexture(src), toSlice(src_slice), (uint32_t)components);
	}
	static jboolean encoder_bc67_dispatch_2(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jint components) {
		return toEncoderBC67(self).dispatch(toCompute(compute), (EncoderBC67::Mode)mode, toTexture(dest), toTexture(src), (uint32_t)components);
	}
	static const JNINativeMethod encoder_bc67_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)encoder_bc67_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)encoder_bc67_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)encoder_bc67_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)encoder_bc67_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)encoder_bc67_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)encoder_bc67_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)encoder_bc67_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)encoder_bc67_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)encoder_bc67_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)encoder_bc67_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)encoder_bc67_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)encoder_bc67_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)encoder_bc67_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)encoder_bc67_clear },
		{ (char*)"is_created", (char*)"(JI)Z", (void*)encoder_bc67_is_created },
		{ (char*)"create_", (char*)"(JJI)Z", (void*)encoder_bc67_create },
		{ (char*)"create_1", (char*)"(JJI)Z", (void*)encoder_bc67_create_1 },
		{ (char*)"dispatch_", (char*)"(JJIJJJJI)Z", (void*)encoder_bc67_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJIJJJI)Z", (void*)encoder_bc67_dispatch_1 },
		{ (char*)"dispatch_2", (char*)"(JJIJJI)Z", (void*)encoder_bc67_dispatch_2 },
	};
	
	// Tellusim::EncoderASTC
	static jlong encoder_astc_new(TS_JNI_ARGS) {
		return newEncoderASTC();
	}
	static void encoder_astc_delete(TS_JNI_ARGS, jlong self) {
		delete (EncoderASTC*)self;
	}
	static jboolean encoder_astc_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toEncoderASTC(self) == toEncoderASTC(ptr));
	}
	static jlong encoder_astc_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newEncoderASTC(toEncoderASTC(self).clonePtr());
	}
	static void encoder_astc_clear_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderASTC(self).clearPtr();
	}
	static void encoder_astc_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderASTC(self).destroyPtr();
	}
	static void encoder_astc_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderASTC(self).acquirePtr();
	}
	static void encoder_astc_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toEncoderASTC(self).unacquirePtr();
	}
	static jboolean encoder_astc_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderASTC(self).isValidPtr();
	}
	static jboolean encoder_astc_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderASTC(self).isOwnerPtr();
	}
	static jboolean encoder_astc_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderASTC(self).isConstPtr();
	}
	static jint encoder_astc_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toEncoderASTC(self).getCountPtr();
	}
	static jlong encoder_astc_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toEncoderASTC(self).getInternalPtr();
	}
	static void encoder_astc_clear(TS_JNI_ARGS, jlong self) {
		toEncoderASTC(self).clear();
	}
	static jboolean encoder_astc_is_created(TS_JNI_ARGS, jlong self, jint mode) {
		return toEncoderASTC(self).isCreated((EncoderASTC::Mode)mode);
	}
	static jboolean encoder_astc_create(TS_JNI_ARGS, jlong self, jlong device, jint mode) {
		return toEncoderASTC(self).create(toDevice(device), (EncoderASTC::Mode)mode);
	}
	static jboolean encoder_astc_create_1(TS_JNI_ARGS, jlong self, jlong device, jint flags) {
		return toEncoderASTC(self).create(toDevice(device), (EncoderASTC::Flags)flags);
	}
	static jboolean encoder_astc_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jlong dest_slice, jlong src_slice, jint components) {
		return toEncoderASTC(self).dispatch(toCompute(compute), (EncoderASTC::Mode)mode, toTexture(dest), toTexture(src), toSlice(dest_slice), toSlice(src_slice), (uint32_t)components);
	}
	static jboolean encoder_astc_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jlong src_slice, jint components) {
		return toEncoderASTC(self).dispatch(toCompute(compute), (EncoderASTC::Mode)mode, toTexture(dest), toTexture(src), toSlice(src_slice), (uint32_t)components);
	}
	static jboolean encoder_astc_dispatch_2(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jlong dest, jlong src, jint components) {
		return toEncoderASTC(self).dispatch(toCompute(compute), (EncoderASTC::Mode)mode, toTexture(dest), toTexture(src), (uint32_t)components);
	}
	static const JNINativeMethod encoder_astc_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)encoder_astc_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)encoder_astc_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)encoder_astc_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)encoder_astc_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)encoder_astc_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)encoder_astc_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)encoder_astc_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)encoder_astc_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)encoder_astc_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)encoder_astc_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)encoder_astc_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)encoder_astc_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)encoder_astc_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)encoder_astc_clear },
		{ (char*)"is_created", (char*)"(JI)Z", (void*)encoder_astc_is_created },
		{ (char*)"create_", (char*)"(JJI)Z", (void*)encoder_astc_create },
		{ (char*)"create_1", (char*)"(JJI)Z", (void*)encoder_astc_create_1 },
		{ (char*)"dispatch_", (char*)"(JJIJJJJI)Z", (void*)encoder_astc_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJIJJJI)Z", (void*)encoder_astc_dispatch_1 },
		{ (char*)"dispatch_2", (char*)"(JJIJJI)Z", (void*)encoder_astc_dispatch_2 },
	};
	
	// Tellusim::MeshModel
	static bool mesh_model_create_callback_func(const void *src, size_t size, bool owner, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "MeshModel$CreateCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(JJZ)Z");
			if(!clazz) TS_LOGF(Error, "mesh_model_create_callback_func(): can't find \"%s\" class\n", "MeshModel$CreateCallback");
			else if(!method_id) TS_LOGF(Error, "mesh_model_create_callback_func(): can't get \"%s\" method\n", "(JJZ)Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id, (jlong)src, (jlong)size, (jboolean)owner) != 0);
		}
		return false;
	}
	static MeshModel::CreateCallback make_mesh_model_create_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(mesh_model_create_callback_func);
			ret.setArg3(env);
			ret.setArg4(func);
			return ret;
		}
		return MeshModel::CreateCallback();
	}
	
	static jlong mesh_model_new(TS_JNI_ARGS) {
		return newMeshModel();
	}
	static void mesh_model_delete(TS_JNI_ARGS, jlong self) {
		delete (MeshModel*)self;
	}
	static void mesh_model_clear(TS_JNI_ARGS, jlong self) {
		toMeshModel(self).clear();
	}
	static jboolean mesh_model_is_created(TS_JNI_ARGS, jlong self) {
		return toMeshModel(self).isCreated();
	}
	static jint mesh_model_get_flags(TS_JNI_ARGS, jlong self) {
		return toMeshModel(self).getFlags();
	}
	static jboolean mesh_model_has_flag(TS_JNI_ARGS, jlong self, jint flags) {
		return toMeshModel(self).hasFlag((MeshModel::Flags)flags);
	}
	static jboolean mesh_model_has_flags(TS_JNI_ARGS, jlong self, jint flags) {
		return toMeshModel(self).hasFlags((MeshModel::Flags)flags);
	}
	static jboolean mesh_model_load(TS_JNI_ARGS, jlong self, jlong device, jlong pipeline, jstring name, jint flags, jlong async) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toMeshModel(self).load(toDevice(device), toPipeline(pipeline), name_, (MeshModel::Flags)flags, (Async*)async);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean mesh_model_load_1(TS_JNI_ARGS, jlong self, jlong device, jlong pipeline, jlong stream, jint flags, jlong async) {
		return toMeshModel(self).load(toDevice(device), toPipeline(pipeline), toStream(stream), (MeshModel::Flags)flags, (Async*)async);
	}
	static jboolean mesh_model_create(TS_JNI_ARGS, jlong self, jlong device, jlong pipeline, jstring name, jint flags) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		bool ret_ = toMeshModel(self).create(toDevice(device), toPipeline(pipeline), name_, (MeshModel::Flags)flags);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean mesh_model_create_1(TS_JNI_ARGS, jlong self, jlong device, jlong pipeline, jlong mesh, jint flags) {
		return toMeshModel(self).create(toDevice(device), toPipeline(pipeline), toMesh(mesh), (MeshModel::Flags)flags);
	}
	static jboolean mesh_model_create_2(TS_JNI_ARGS, jlong self, jlong device, jlong pipeline, jlong geometry, jint flags) {
		return toMeshModel(self).create(toDevice(device), toPipeline(pipeline), toMeshGeometry(geometry), (MeshModel::Flags)flags);
	}
	static jboolean mesh_model_create_3(TS_JNI_ARGS, jlong self, jlong device, jlong pipeline, jlongArray geometries, jint flags) {
		Array<MeshGeometry> geometries_((uint32_t)env->GetArrayLength(geometries));
		jlong *geometries__ = env->GetLongArrayElements(geometries, nullptr);
		for(uint32_t i = 0; i < geometries_.size(); i++) geometries_[i] = toMeshGeometry(geometries__[i]);
		bool ret_ = toMeshModel(self).create(toDevice(device), toPipeline(pipeline), geometries_, (MeshModel::Flags)flags);
		if(geometries__) env->ReleaseLongArrayElements(geometries, geometries__, 0);
		return ret_;
	}
	static void mesh_model_set_vertex_buffer_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toMeshModel(self).setVertexBufferCallback(make_mesh_model_create_callback(env, func));
	}
	static void mesh_model_set_index_buffer_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toMeshModel(self).setIndexBufferCallback(make_mesh_model_create_callback(env, func));
	}
	static void mesh_model_set_mesh_buffer_callback(TS_JNI_ARGS, jlong self, jobject func) {
		toMeshModel(self).setMeshBufferCallback(make_mesh_model_create_callback(env, func));
	}
	static void mesh_model_set_buffers(TS_JNI_ARGS, jlong self, jlong command, jint index, jlong pipeline) {
		toMeshModel(self).setBuffers(toCommand(command), (uint32_t)index, (Pipeline*)pipeline);
	}
	static void mesh_model_draw(TS_JNI_ARGS, jlong self, jlong command) {
		toMeshModel(self).draw(toCommand(command));
	}
	static void mesh_model_draw_1(TS_JNI_ARGS, jlong self, jlong command, jint geometry) {
		toMeshModel(self).draw(toCommand(command), (uint32_t)geometry);
	}
	static void mesh_model_draw_2(TS_JNI_ARGS, jlong self, jlong command, jint geometry, jint material) {
		toMeshModel(self).draw(toCommand(command), (uint32_t)geometry, (uint32_t)material);
	}
	static void mesh_model_draw_instanced(TS_JNI_ARGS, jlong self, jlong command, jint geometry, jint num_instances, jint base_instance) {
		toMeshModel(self).drawInstanced(toCommand(command), (uint32_t)geometry, (uint32_t)num_instances, (uint32_t)base_instance);
	}
	static void mesh_model_draw_instanced_1(TS_JNI_ARGS, jlong self, jlong command, jint geometry, jint material, jint num_instances, jint base_instance) {
		toMeshModel(self).drawInstanced(toCommand(command), (uint32_t)geometry, (uint32_t)material, (uint32_t)num_instances, (uint32_t)base_instance);
	}
	static jint mesh_model_get_num_vertices(TS_JNI_ARGS, jlong self) {
		return toMeshModel(self).getNumVertices();
	}
	static jint mesh_model_get_num_vertex_buffers(TS_JNI_ARGS, jlong self) {
		return toMeshModel(self).getNumVertexBuffers();
	}
	static jint mesh_model_get_vertex_buffer_stride(TS_JNI_ARGS, jlong self, jint index) {
		return toMeshModel(self).getVertexBufferStride((uint32_t)index);
	}
	static jlong mesh_model_get_vertex_buffer_offset(TS_JNI_ARGS, jlong self, jint index) {
		return (jlong)toMeshModel(self).getVertexBufferOffset((uint32_t)index);
	}
	static jlong mesh_model_get_vertex_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toMeshModel(self).getVertexBuffer());
	}
	static jint mesh_model_get_num_indices(TS_JNI_ARGS, jlong self) {
		return toMeshModel(self).getNumIndices();
	}
	static jint mesh_model_get_index_format(TS_JNI_ARGS, jlong self) {
		return toMeshModel(self).getIndexFormat();
	}
	static jlong mesh_model_get_index_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toMeshModel(self).getIndexBuffer());
	}
	static jint mesh_model_get_num_meshlets(TS_JNI_ARGS, jlong self) {
		return toMeshModel(self).getNumMeshlets();
	}
	static jlong mesh_model_get_meshlet_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toMeshModel(self).getMeshletBuffer());
	}
	static jint mesh_model_get_num_geometries(TS_JNI_ARGS, jlong self) {
		return toMeshModel(self).getNumGeometries();
	}
	static jint mesh_model_get_num_geometry_indices(TS_JNI_ARGS, jlong self, jint geometry) {
		return toMeshModel(self).getNumGeometryIndices((uint32_t)geometry);
	}
	static jint mesh_model_get_num_geometry_vertices(TS_JNI_ARGS, jlong self, jint geometry) {
		return toMeshModel(self).getNumGeometryVertices((uint32_t)geometry);
	}
	static jint mesh_model_get_num_geometry_meshlets(TS_JNI_ARGS, jlong self, jint geometry) {
		return toMeshModel(self).getNumGeometryMeshlets((uint32_t)geometry);
	}
	static jint mesh_model_get_geometry_base_index(TS_JNI_ARGS, jlong self, jint geometry) {
		return toMeshModel(self).getGeometryBaseIndex((uint32_t)geometry);
	}
	static jint mesh_model_get_geometry_base_vertex(TS_JNI_ARGS, jlong self, jint geometry) {
		return toMeshModel(self).getGeometryBaseVertex((uint32_t)geometry);
	}
	static jint mesh_model_get_geometry_base_meshlet(TS_JNI_ARGS, jlong self, jint geometry) {
		return toMeshModel(self).getGeometryBaseMeshlet((uint32_t)geometry);
	}
	static jint mesh_model_get_num_materials(TS_JNI_ARGS, jlong self, jint geometry) {
		return toMeshModel(self).getNumMaterials((uint32_t)geometry);
	}
	static jint mesh_model_get_num_material_indices(TS_JNI_ARGS, jlong self, jint geometry, jint material) {
		return toMeshModel(self).getNumMaterialIndices((uint32_t)geometry, (uint32_t)material);
	}
	static jint mesh_model_get_num_material_vertices(TS_JNI_ARGS, jlong self, jint geometry, jint material) {
		return toMeshModel(self).getNumMaterialVertices((uint32_t)geometry, (uint32_t)material);
	}
	static jint mesh_model_get_num_material_meshlets(TS_JNI_ARGS, jlong self, jint geometry, jint material) {
		return toMeshModel(self).getNumMaterialMeshlets((uint32_t)geometry, (uint32_t)material);
	}
	static jint mesh_model_get_material_base_index(TS_JNI_ARGS, jlong self, jint geometry, jint material) {
		return toMeshModel(self).getMaterialBaseIndex((uint32_t)geometry, (uint32_t)material);
	}
	static jint mesh_model_get_material_base_vertex(TS_JNI_ARGS, jlong self, jint geometry, jint material) {
		return toMeshModel(self).getMaterialBaseVertex((uint32_t)geometry, (uint32_t)material);
	}
	static jint mesh_model_get_material_base_meshlet(TS_JNI_ARGS, jlong self, jint geometry, jint material) {
		return toMeshModel(self).getMaterialBaseMeshlet((uint32_t)geometry, (uint32_t)material);
	}
	static jlong mesh_model_get_memory(TS_JNI_ARGS, jlong self) {
		return (jlong)toMeshModel(self).getMemory();
	}
	static const JNINativeMethod mesh_model_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)mesh_model_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)mesh_model_delete },
		{ (char*)"clear_", (char*)"(J)V", (void*)mesh_model_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)mesh_model_is_created },
		{ (char*)"get_flags", (char*)"(J)I", (void*)mesh_model_get_flags },
		{ (char*)"has_flag", (char*)"(JI)Z", (void*)mesh_model_has_flag },
		{ (char*)"has_flags", (char*)"(JI)Z", (void*)mesh_model_has_flags },
		{ (char*)"load_", (char*)"(JJJLjava/lang/String;IJ)Z", (void*)mesh_model_load },
		{ (char*)"load_1", (char*)"(JJJJIJ)Z", (void*)mesh_model_load_1 },
		{ (char*)"create_", (char*)"(JJJLjava/lang/String;I)Z", (void*)mesh_model_create },
		{ (char*)"create_1", (char*)"(JJJJI)Z", (void*)mesh_model_create_1 },
		{ (char*)"create_2", (char*)"(JJJJI)Z", (void*)mesh_model_create_2 },
		{ (char*)"create_3", (char*)"(JJJ[JI)Z", (void*)mesh_model_create_3 },
		{ (char*)"set_vertex_buffer_callback", (char*)"(JL" TS_JNI_PREFIX "MeshModel$CreateCallback;)V", (void*)mesh_model_set_vertex_buffer_callback },
		{ (char*)"set_index_buffer_callback", (char*)"(JL" TS_JNI_PREFIX "MeshModel$CreateCallback;)V", (void*)mesh_model_set_index_buffer_callback },
		{ (char*)"set_mesh_buffer_callback", (char*)"(JL" TS_JNI_PREFIX "MeshModel$CreateCallback;)V", (void*)mesh_model_set_mesh_buffer_callback },
		{ (char*)"set_buffers", (char*)"(JJIJ)V", (void*)mesh_model_set_buffers },
		{ (char*)"draw_", (char*)"(JJ)V", (void*)mesh_model_draw },
		{ (char*)"draw_1", (char*)"(JJI)V", (void*)mesh_model_draw_1 },
		{ (char*)"draw_2", (char*)"(JJII)V", (void*)mesh_model_draw_2 },
		{ (char*)"draw_instanced", (char*)"(JJIII)V", (void*)mesh_model_draw_instanced },
		{ (char*)"draw_instanced_1", (char*)"(JJIIII)V", (void*)mesh_model_draw_instanced_1 },
		{ (char*)"get_num_vertices", (char*)"(J)I", (void*)mesh_model_get_num_vertices },
		{ (char*)"get_num_vertex_buffers", (char*)"(J)I", (void*)mesh_model_get_num_vertex_buffers },
		{ (char*)"get_vertex_buffer_stride", (char*)"(JI)I", (void*)mesh_model_get_vertex_buffer_stride },
		{ (char*)"get_vertex_buffer_offset", (char*)"(JI)J", (void*)mesh_model_get_vertex_buffer_offset },
		{ (char*)"get_vertex_buffer", (char*)"(J)J", (void*)mesh_model_get_vertex_buffer },
		{ (char*)"get_num_indices", (char*)"(J)I", (void*)mesh_model_get_num_indices },
		{ (char*)"get_index_format", (char*)"(J)I", (void*)mesh_model_get_index_format },
		{ (char*)"get_index_buffer", (char*)"(J)J", (void*)mesh_model_get_index_buffer },
		{ (char*)"get_num_meshlets", (char*)"(J)I", (void*)mesh_model_get_num_meshlets },
		{ (char*)"get_meshlet_buffer", (char*)"(J)J", (void*)mesh_model_get_meshlet_buffer },
		{ (char*)"get_num_geometries", (char*)"(J)I", (void*)mesh_model_get_num_geometries },
		{ (char*)"get_num_geometry_indices", (char*)"(JI)I", (void*)mesh_model_get_num_geometry_indices },
		{ (char*)"get_num_geometry_vertices", (char*)"(JI)I", (void*)mesh_model_get_num_geometry_vertices },
		{ (char*)"get_num_geometry_meshlets", (char*)"(JI)I", (void*)mesh_model_get_num_geometry_meshlets },
		{ (char*)"get_geometry_base_index", (char*)"(JI)I", (void*)mesh_model_get_geometry_base_index },
		{ (char*)"get_geometry_base_vertex", (char*)"(JI)I", (void*)mesh_model_get_geometry_base_vertex },
		{ (char*)"get_geometry_base_meshlet", (char*)"(JI)I", (void*)mesh_model_get_geometry_base_meshlet },
		{ (char*)"get_num_materials", (char*)"(JI)I", (void*)mesh_model_get_num_materials },
		{ (char*)"get_num_material_indices", (char*)"(JII)I", (void*)mesh_model_get_num_material_indices },
		{ (char*)"get_num_material_vertices", (char*)"(JII)I", (void*)mesh_model_get_num_material_vertices },
		{ (char*)"get_num_material_meshlets", (char*)"(JII)I", (void*)mesh_model_get_num_material_meshlets },
		{ (char*)"get_material_base_index", (char*)"(JII)I", (void*)mesh_model_get_material_base_index },
		{ (char*)"get_material_base_vertex", (char*)"(JII)I", (void*)mesh_model_get_material_base_vertex },
		{ (char*)"get_material_base_meshlet", (char*)"(JII)I", (void*)mesh_model_get_material_base_meshlet },
		{ (char*)"get_memory", (char*)"(J)J", (void*)mesh_model_get_memory },
	};
	
	// Tellusim::SeparableFilter
	static jlong separable_filter_new(TS_JNI_ARGS) {
		return newSeparableFilter();
	}
	static void separable_filter_delete(TS_JNI_ARGS, jlong self) {
		delete (SeparableFilter*)self;
	}
	static jboolean separable_filter_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toSeparableFilter(self) == toSeparableFilter(ptr));
	}
	static jlong separable_filter_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newSeparableFilter(toSeparableFilter(self).clonePtr());
	}
	static void separable_filter_clear_ptr(TS_JNI_ARGS, jlong self) {
		toSeparableFilter(self).clearPtr();
	}
	static void separable_filter_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toSeparableFilter(self).destroyPtr();
	}
	static void separable_filter_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toSeparableFilter(self).acquirePtr();
	}
	static void separable_filter_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toSeparableFilter(self).unacquirePtr();
	}
	static jboolean separable_filter_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toSeparableFilter(self).isValidPtr();
	}
	static jboolean separable_filter_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toSeparableFilter(self).isOwnerPtr();
	}
	static jboolean separable_filter_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toSeparableFilter(self).isConstPtr();
	}
	static jint separable_filter_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toSeparableFilter(self).getCountPtr();
	}
	static jlong separable_filter_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toSeparableFilter(self).getInternalPtr();
	}
	static void separable_filter_clear(TS_JNI_ARGS, jlong self) {
		toSeparableFilter(self).clear();
	}
	static jboolean separable_filter_is_created(TS_JNI_ARGS, jlong self, jint format, jint size) {
		return toSeparableFilter(self).isCreated((Format)format, (uint32_t)size);
	}
	static void separable_filter_set_input_source(TS_JNI_ARGS, jlong self, jint mode, jstring src) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		toSeparableFilter(self).setInputSource((SeparableFilter::Mode)mode, src_);
		env->ReleaseStringUTFChars(src, src_);
	}
	static jstring separable_filter_get_input_source(TS_JNI_ARGS, jlong self, jint mode) {
		return env->NewStringUTF(toSeparableFilter(self).getInputSource((SeparableFilter::Mode)mode).get());
	}
	static void separable_filter_set_output_source(TS_JNI_ARGS, jlong self, jint mode, jstring src) {
		const char *src_ = (src) ? env->GetStringUTFChars(src, nullptr) : nullptr;
		toSeparableFilter(self).setOutputSource((SeparableFilter::Mode)mode, src_);
		env->ReleaseStringUTFChars(src, src_);
	}
	static jstring separable_filter_get_output_source(TS_JNI_ARGS, jlong self, jint mode) {
		return env->NewStringUTF(toSeparableFilter(self).getOutputSource((SeparableFilter::Mode)mode).get());
	}
	static jboolean separable_filter_create(TS_JNI_ARGS, jlong self, jlong device, jint format, jint size, jint flags) {
		return toSeparableFilter(self).create(toDevice(device), (Format)format, (uint32_t)size, (SeparableFilter::Flags)flags);
	}
	static void separable_filter_set_weights(TS_JNI_ARGS, jlong self, jint mode, jlongArray weights, jboolean normalize) {
		Array<Vector4f> weights_((uint32_t)env->GetArrayLength(weights));
		jlong *weights__ = env->GetLongArrayElements(weights, nullptr);
		for(uint32_t i = 0; i < weights_.size(); i++) weights_[i] = toVector4f(weights__[i]);
		toSeparableFilter(self).setWeights((SeparableFilter::Mode)mode, weights_, (bool)normalize);
		if(weights__) env->ReleaseLongArrayElements(weights, weights__, 0);
	}
	static void separable_filter_set_weights_1(TS_JNI_ARGS, jlong self, jint mode, jfloatArray weights, jboolean normalize) {
		float32_t *weights__ = env->GetFloatArrayElements(weights, nullptr);
		Array<float32_t> weights_((uint32_t)env->GetArrayLength(weights), weights__);
		toSeparableFilter(self).setWeights((SeparableFilter::Mode)mode, weights_, (bool)normalize);
		if(weights_) env->ReleaseFloatArrayElements(weights, weights__, 0);
	}
	static void separable_filter_set_gaussian_weights(TS_JNI_ARGS, jlong self, jint size, jlong sigma) {
		toSeparableFilter(self).setGaussianWeights((uint32_t)size, toVector4f(sigma));
	}
	static void separable_filter_set_gaussian_weights_1(TS_JNI_ARGS, jlong self, jint size, jfloat sigma) {
		toSeparableFilter(self).setGaussianWeights((uint32_t)size, sigma);
	}
	static void separable_filter_set_sobel_xweights(TS_JNI_ARGS, jlong self, jint size) {
		toSeparableFilter(self).setSobelXWeights((uint32_t)size);
	}
	static void separable_filter_set_sobel_yweights(TS_JNI_ARGS, jlong self, jint size) {
		toSeparableFilter(self).setSobelYWeights((uint32_t)size);
	}
	static void separable_filter_set_box_weights(TS_JNI_ARGS, jlong self, jint size) {
		toSeparableFilter(self).setBoxWeights((uint32_t)size);
	}
	static jboolean separable_filter_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jint size, jlong dest, jlong src, jlong dest_slice, jlong src_slice, jlong values) {
		return toSeparableFilter(self).dispatch(toCompute(compute), (SeparableFilter::Mode)mode, (uint32_t)size, toTexture(dest), toTexture(src), toSlice(dest_slice), toSlice(src_slice), toVector4f(values));
	}
	static jboolean separable_filter_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jint size, jlong dest, jlong src, jlong src_slice, jlong values) {
		return toSeparableFilter(self).dispatch(toCompute(compute), (SeparableFilter::Mode)mode, (uint32_t)size, toTexture(dest), toTexture(src), toSlice(src_slice), toVector4f(values));
	}
	static jboolean separable_filter_dispatch_2(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jint size, jlong dest, jlong src, jlong values) {
		return toSeparableFilter(self).dispatch(toCompute(compute), (SeparableFilter::Mode)mode, (uint32_t)size, toTexture(dest), toTexture(src), toVector4f(values));
	}
	static const JNINativeMethod separable_filter_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)separable_filter_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)separable_filter_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)separable_filter_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)separable_filter_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)separable_filter_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)separable_filter_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)separable_filter_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)separable_filter_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)separable_filter_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)separable_filter_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)separable_filter_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)separable_filter_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)separable_filter_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)separable_filter_clear },
		{ (char*)"is_created", (char*)"(JII)Z", (void*)separable_filter_is_created },
		{ (char*)"set_input_source", (char*)"(JILjava/lang/String;)V", (void*)separable_filter_set_input_source },
		{ (char*)"get_input_source", (char*)"(JI)Ljava/lang/String;", (void*)separable_filter_get_input_source },
		{ (char*)"set_output_source", (char*)"(JILjava/lang/String;)V", (void*)separable_filter_set_output_source },
		{ (char*)"get_output_source", (char*)"(JI)Ljava/lang/String;", (void*)separable_filter_get_output_source },
		{ (char*)"create_", (char*)"(JJIII)Z", (void*)separable_filter_create },
		{ (char*)"set_weights", (char*)"(JI[JZ)V", (void*)separable_filter_set_weights },
		{ (char*)"set_weights_1", (char*)"(JI[FZ)V", (void*)separable_filter_set_weights_1 },
		{ (char*)"set_gaussian_weights", (char*)"(JIJ)V", (void*)separable_filter_set_gaussian_weights },
		{ (char*)"set_gaussian_weights_1", (char*)"(JIF)V", (void*)separable_filter_set_gaussian_weights_1 },
		{ (char*)"set_sobel_xweights", (char*)"(JI)V", (void*)separable_filter_set_sobel_xweights },
		{ (char*)"set_sobel_yweights", (char*)"(JI)V", (void*)separable_filter_set_sobel_yweights },
		{ (char*)"set_box_weights", (char*)"(JI)V", (void*)separable_filter_set_box_weights },
		{ (char*)"dispatch_", (char*)"(JJIIJJJJJ)Z", (void*)separable_filter_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJIIJJJJ)Z", (void*)separable_filter_dispatch_1 },
		{ (char*)"dispatch_2", (char*)"(JJIIJJJ)Z", (void*)separable_filter_dispatch_2 },
	};
	
	// Tellusim::PrefixScan::DispatchParameters
	static jlong prefix_scan_dispatch_parameters_new(TS_JNI_ARGS) {
		return newPrefixScanDispatchParameters();
	}
	static jlong prefix_scan_dispatch_parameters_copy(TS_JNI_ARGS, jlong self) {
		return newPrefixScanDispatchParameters(toPrefixScanDispatchParameters(self));
	}
	static void prefix_scan_dispatch_parameters_delete(TS_JNI_ARGS, jlong self) {
		delete (PrefixScan::DispatchParameters*)self;
	}
	static void prefix_scan_dispatch_parameters_set_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toPrefixScanDispatchParameters(self).offset = offset;
	}
	static jint prefix_scan_dispatch_parameters_get_offset(TS_JNI_ARGS, jlong self) {
		return toPrefixScanDispatchParameters(self).offset;
	}
	static void prefix_scan_dispatch_parameters_set_size(TS_JNI_ARGS, jlong self, jint size) {
		toPrefixScanDispatchParameters(self).size = size;
	}
	static jint prefix_scan_dispatch_parameters_get_size(TS_JNI_ARGS, jlong self) {
		return toPrefixScanDispatchParameters(self).size;
	}
	static const JNINativeMethod prefix_scan_dispatch_parameters_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)prefix_scan_dispatch_parameters_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)prefix_scan_dispatch_parameters_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)prefix_scan_dispatch_parameters_delete },
		{ (char*)"set_offset_", (char*)"(JI)V", (void*)prefix_scan_dispatch_parameters_set_offset },
		{ (char*)"get_offset_", (char*)"(J)I", (void*)prefix_scan_dispatch_parameters_get_offset },
		{ (char*)"set_size_", (char*)"(JI)V", (void*)prefix_scan_dispatch_parameters_set_size },
		{ (char*)"get_size_", (char*)"(J)I", (void*)prefix_scan_dispatch_parameters_get_size },
	};
	// Tellusim::PrefixScan
	static jlong prefix_scan_new(TS_JNI_ARGS) {
		return newPrefixScan();
	}
	static void prefix_scan_delete(TS_JNI_ARGS, jlong self) {
		delete (PrefixScan*)self;
	}
	static jboolean prefix_scan_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toPrefixScan(self) == toPrefixScan(ptr));
	}
	static jlong prefix_scan_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newPrefixScan(toPrefixScan(self).clonePtr());
	}
	static void prefix_scan_clear_ptr(TS_JNI_ARGS, jlong self) {
		toPrefixScan(self).clearPtr();
	}
	static void prefix_scan_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toPrefixScan(self).destroyPtr();
	}
	static void prefix_scan_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toPrefixScan(self).acquirePtr();
	}
	static void prefix_scan_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toPrefixScan(self).unacquirePtr();
	}
	static jboolean prefix_scan_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toPrefixScan(self).isValidPtr();
	}
	static jboolean prefix_scan_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toPrefixScan(self).isOwnerPtr();
	}
	static jboolean prefix_scan_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toPrefixScan(self).isConstPtr();
	}
	static jint prefix_scan_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toPrefixScan(self).getCountPtr();
	}
	static jlong prefix_scan_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toPrefixScan(self).getInternalPtr();
	}
	static void prefix_scan_clear(TS_JNI_ARGS, jlong self) {
		toPrefixScan(self).clear();
	}
	static jboolean prefix_scan_is_created(TS_JNI_ARGS, jlong self, jint flags) {
		return toPrefixScan(self).isCreated((PrefixScan::Flags)flags);
	}
	static jint prefix_scan_get_group_size(TS_JNI_ARGS, jlong self) {
		return toPrefixScan(self).getGroupSize();
	}
	static jint prefix_scan_get_scan_elements(TS_JNI_ARGS, jlong self) {
		return toPrefixScan(self).getScanElements();
	}
	static jint prefix_scan_get_max_elements(TS_JNI_ARGS, jlong self) {
		return toPrefixScan(self).getMaxElements();
	}
	static jint prefix_scan_get_max_regions(TS_JNI_ARGS, jlong self) {
		return toPrefixScan(self).getMaxRegions();
	}
	static jboolean prefix_scan_create(TS_JNI_ARGS, jlong self, jlong device, jint mode, jint groups, jint regions, jlong async) {
		return toPrefixScan(self).create(toDevice(device), (PrefixScan::Mode)mode, (uint32_t)groups, (uint32_t)regions, (Async*)async);
	}
	static jboolean prefix_scan_create_1(TS_JNI_ARGS, jlong self, jlong device, jint flags, jint groups, jint regions, jlong async) {
		return toPrefixScan(self).create(toDevice(device), (PrefixScan::Flags)flags, (uint32_t)groups, (uint32_t)regions, (Async*)async);
	}
	static jboolean prefix_scan_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jint offset, jint size) {
		return toPrefixScan(self).dispatch(toCompute(compute), toBuffer(data), (uint32_t)offset, (uint32_t)size);
	}
	static jboolean prefix_scan_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jint count, jintArray offsets, jintArray sizes, jint flags) {
		return toPrefixScan(self).dispatch(toCompute(compute), toBuffer(data), (uint32_t)count, (uint32_t*)IntArray(env, offsets).get(), (uint32_t*)IntArray(env, sizes).get(), (PrefixScan::Flags)flags);
	}
	static jboolean prefix_scan_dispatch_indirect(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jlong dispatch, jint offset, jint flags, jint max_size) {
		return toPrefixScan(self).dispatchIndirect(toCompute(compute), toBuffer(data), toBuffer(dispatch), (uint32_t)offset, (PrefixScan::Flags)flags, (uint32_t)max_size);
	}
	static jboolean prefix_scan_dispatch_indirect_1(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jint count, jlong dispatch, jint offset, jint flags, jint max_size) {
		return toPrefixScan(self).dispatchIndirect(toCompute(compute), toBuffer(data), (uint32_t)count, toBuffer(dispatch), (uint32_t)offset, (PrefixScan::Flags)flags, (uint32_t)max_size);
	}
	static jboolean prefix_scan_dispatch_indirect_2(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jlong count, jlong dispatch, jint count_offset, jint dispatch_offset, jint flags, jint max_size) {
		return toPrefixScan(self).dispatchIndirect(toCompute(compute), toBuffer(data), toBuffer(count), toBuffer(dispatch), (uint32_t)count_offset, (uint32_t)dispatch_offset, (PrefixScan::Flags)flags, (uint32_t)max_size);
	}
	static const JNINativeMethod prefix_scan_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)prefix_scan_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)prefix_scan_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)prefix_scan_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)prefix_scan_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)prefix_scan_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)prefix_scan_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)prefix_scan_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)prefix_scan_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)prefix_scan_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)prefix_scan_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)prefix_scan_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)prefix_scan_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)prefix_scan_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)prefix_scan_clear },
		{ (char*)"is_created", (char*)"(JI)Z", (void*)prefix_scan_is_created },
		{ (char*)"get_group_size", (char*)"(J)I", (void*)prefix_scan_get_group_size },
		{ (char*)"get_scan_elements", (char*)"(J)I", (void*)prefix_scan_get_scan_elements },
		{ (char*)"get_max_elements", (char*)"(J)I", (void*)prefix_scan_get_max_elements },
		{ (char*)"get_max_regions", (char*)"(J)I", (void*)prefix_scan_get_max_regions },
		{ (char*)"create_", (char*)"(JJIIIJ)Z", (void*)prefix_scan_create },
		{ (char*)"create_1", (char*)"(JJIIIJ)Z", (void*)prefix_scan_create_1 },
		{ (char*)"dispatch_", (char*)"(JJJII)Z", (void*)prefix_scan_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJJI[I[II)Z", (void*)prefix_scan_dispatch_1 },
		{ (char*)"dispatch_indirect", (char*)"(JJJJIII)Z", (void*)prefix_scan_dispatch_indirect },
		{ (char*)"dispatch_indirect_1", (char*)"(JJJIJIII)Z", (void*)prefix_scan_dispatch_indirect_1 },
		{ (char*)"dispatch_indirect_2", (char*)"(JJJJJIIII)Z", (void*)prefix_scan_dispatch_indirect_2 },
	};
	
	// Tellusim::RadixSort::DispatchParameters
	static jlong radix_sort_dispatch_parameters_new(TS_JNI_ARGS) {
		return newRadixSortDispatchParameters();
	}
	static jlong radix_sort_dispatch_parameters_copy(TS_JNI_ARGS, jlong self) {
		return newRadixSortDispatchParameters(toRadixSortDispatchParameters(self));
	}
	static void radix_sort_dispatch_parameters_delete(TS_JNI_ARGS, jlong self) {
		delete (RadixSort::DispatchParameters*)self;
	}
	static void radix_sort_dispatch_parameters_set_keys_offset(TS_JNI_ARGS, jlong self, jint keys_offset) {
		toRadixSortDispatchParameters(self).keys_offset = keys_offset;
	}
	static jint radix_sort_dispatch_parameters_get_keys_offset(TS_JNI_ARGS, jlong self) {
		return toRadixSortDispatchParameters(self).keys_offset;
	}
	static void radix_sort_dispatch_parameters_set_data_offset(TS_JNI_ARGS, jlong self, jint data_offset) {
		toRadixSortDispatchParameters(self).data_offset = data_offset;
	}
	static jint radix_sort_dispatch_parameters_get_data_offset(TS_JNI_ARGS, jlong self) {
		return toRadixSortDispatchParameters(self).data_offset;
	}
	static void radix_sort_dispatch_parameters_set_size(TS_JNI_ARGS, jlong self, jint size) {
		toRadixSortDispatchParameters(self).size = size;
	}
	static jint radix_sort_dispatch_parameters_get_size(TS_JNI_ARGS, jlong self) {
		return toRadixSortDispatchParameters(self).size;
	}
	static const JNINativeMethod radix_sort_dispatch_parameters_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)radix_sort_dispatch_parameters_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)radix_sort_dispatch_parameters_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)radix_sort_dispatch_parameters_delete },
		{ (char*)"set_keys_offset_", (char*)"(JI)V", (void*)radix_sort_dispatch_parameters_set_keys_offset },
		{ (char*)"get_keys_offset_", (char*)"(J)I", (void*)radix_sort_dispatch_parameters_get_keys_offset },
		{ (char*)"set_data_offset_", (char*)"(JI)V", (void*)radix_sort_dispatch_parameters_set_data_offset },
		{ (char*)"get_data_offset_", (char*)"(J)I", (void*)radix_sort_dispatch_parameters_get_data_offset },
		{ (char*)"set_size_", (char*)"(JI)V", (void*)radix_sort_dispatch_parameters_set_size },
		{ (char*)"get_size_", (char*)"(J)I", (void*)radix_sort_dispatch_parameters_get_size },
	};
	// Tellusim::RadixSort
	static jlong radix_sort_new(TS_JNI_ARGS) {
		return newRadixSort();
	}
	static void radix_sort_delete(TS_JNI_ARGS, jlong self) {
		delete (RadixSort*)self;
	}
	static jboolean radix_sort_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toRadixSort(self) == toRadixSort(ptr));
	}
	static jlong radix_sort_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newRadixSort(toRadixSort(self).clonePtr());
	}
	static void radix_sort_clear_ptr(TS_JNI_ARGS, jlong self) {
		toRadixSort(self).clearPtr();
	}
	static void radix_sort_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toRadixSort(self).destroyPtr();
	}
	static void radix_sort_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toRadixSort(self).acquirePtr();
	}
	static void radix_sort_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toRadixSort(self).unacquirePtr();
	}
	static jboolean radix_sort_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toRadixSort(self).isValidPtr();
	}
	static jboolean radix_sort_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toRadixSort(self).isOwnerPtr();
	}
	static jboolean radix_sort_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toRadixSort(self).isConstPtr();
	}
	static jint radix_sort_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toRadixSort(self).getCountPtr();
	}
	static jlong radix_sort_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toRadixSort(self).getInternalPtr();
	}
	static void radix_sort_clear(TS_JNI_ARGS, jlong self) {
		toRadixSort(self).clear();
	}
	static jboolean radix_sort_is_created(TS_JNI_ARGS, jlong self, jint flags) {
		return toRadixSort(self).isCreated((RadixSort::Flags)flags);
	}
	static jint radix_sort_get_data_size(TS_JNI_ARGS, jlong self) {
		return toRadixSort(self).getDataSize();
	}
	static jint radix_sort_get_group_size(TS_JNI_ARGS, jlong self) {
		return toRadixSort(self).getGroupSize();
	}
	static jint radix_sort_get_sort_elements(TS_JNI_ARGS, jlong self) {
		return toRadixSort(self).getSortElements();
	}
	static jint radix_sort_get_update_elements(TS_JNI_ARGS, jlong self) {
		return toRadixSort(self).getUpdateElements();
	}
	static jint radix_sort_get_max_elements(TS_JNI_ARGS, jlong self) {
		return toRadixSort(self).getMaxElements();
	}
	static jint radix_sort_get_max_regions(TS_JNI_ARGS, jlong self) {
		return toRadixSort(self).getMaxRegions();
	}
	static jlong radix_sort_get_prefix_scan(TS_JNI_ARGS, jlong self) {
		return newPrefixScan(toRadixSort(self).getPrefixScan());
	}
	static jlong radix_sort_get_data_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toRadixSort(self).getDataBuffer());
	}
	static jboolean radix_sort_create(TS_JNI_ARGS, jlong self, jlong device, jint mode, jlong scan, jint size, jint groups, jint regions, jlong async) {
		return toRadixSort(self).create(toDevice(device), (RadixSort::Mode)mode, toPrefixScan(scan), (uint32_t)size, (uint32_t)groups, (uint32_t)regions, (Async*)async);
	}
	static jboolean radix_sort_create_1(TS_JNI_ARGS, jlong self, jlong device, jint flags, jlong scan, jint size, jint groups, jint regions, jlong async) {
		return toRadixSort(self).create(toDevice(device), (RadixSort::Flags)flags, toPrefixScan(scan), (uint32_t)size, (uint32_t)groups, (uint32_t)regions, (Async*)async);
	}
	static jboolean radix_sort_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jint keys_offset, jint data_offset, jint size, jint flags, jint bits) {
		return toRadixSort(self).dispatch(toCompute(compute), toBuffer(data), (uint32_t)keys_offset, (uint32_t)data_offset, (uint32_t)size, (RadixSort::Flags)flags, (uint32_t)bits);
	}
	static jboolean radix_sort_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jint count, jintArray keys_offsets, jintArray data_offsets, jintArray sizes, jint flags, jint bits) {
		return toRadixSort(self).dispatch(toCompute(compute), toBuffer(data), (uint32_t)count, (uint32_t*)IntArray(env, keys_offsets).get(), (uint32_t*)IntArray(env, data_offsets).get(), (uint32_t*)IntArray(env, sizes).get(), (RadixSort::Flags)flags, (uint32_t)bits);
	}
	static jboolean radix_sort_dispatch_indirect(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jlong dispatch, jint offset, jint flags, jint bits, jint max_size) {
		return toRadixSort(self).dispatchIndirect(toCompute(compute), toBuffer(data), toBuffer(dispatch), (uint32_t)offset, (RadixSort::Flags)flags, (uint32_t)bits, (uint32_t)max_size);
	}
	static jboolean radix_sort_dispatch_indirect_1(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jint count, jlong dispatch, jint offset, jint flags, jint bits, jint max_size) {
		return toRadixSort(self).dispatchIndirect(toCompute(compute), toBuffer(data), (uint32_t)count, toBuffer(dispatch), (uint32_t)offset, (RadixSort::Flags)flags, (uint32_t)bits, (uint32_t)max_size);
	}
	static jboolean radix_sort_dispatch_indirect_2(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jlong count, jlong dispatch, jint count_offset, jint dispatch_offset, jint flags, jint bits, jint max_size) {
		return toRadixSort(self).dispatchIndirect(toCompute(compute), toBuffer(data), toBuffer(count), toBuffer(dispatch), (uint32_t)count_offset, (uint32_t)dispatch_offset, (RadixSort::Flags)flags, (uint32_t)bits, (uint32_t)max_size);
	}
	static const JNINativeMethod radix_sort_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)radix_sort_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)radix_sort_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)radix_sort_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)radix_sort_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)radix_sort_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)radix_sort_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)radix_sort_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)radix_sort_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)radix_sort_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)radix_sort_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)radix_sort_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)radix_sort_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)radix_sort_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)radix_sort_clear },
		{ (char*)"is_created", (char*)"(JI)Z", (void*)radix_sort_is_created },
		{ (char*)"get_data_size", (char*)"(J)I", (void*)radix_sort_get_data_size },
		{ (char*)"get_group_size", (char*)"(J)I", (void*)radix_sort_get_group_size },
		{ (char*)"get_sort_elements", (char*)"(J)I", (void*)radix_sort_get_sort_elements },
		{ (char*)"get_update_elements", (char*)"(J)I", (void*)radix_sort_get_update_elements },
		{ (char*)"get_max_elements", (char*)"(J)I", (void*)radix_sort_get_max_elements },
		{ (char*)"get_max_regions", (char*)"(J)I", (void*)radix_sort_get_max_regions },
		{ (char*)"get_prefix_scan", (char*)"(J)J", (void*)radix_sort_get_prefix_scan },
		{ (char*)"get_data_buffer", (char*)"(J)J", (void*)radix_sort_get_data_buffer },
		{ (char*)"create_", (char*)"(JJIJIIIJ)Z", (void*)radix_sort_create },
		{ (char*)"create_1", (char*)"(JJIJIIIJ)Z", (void*)radix_sort_create_1 },
		{ (char*)"dispatch_", (char*)"(JJJIIIII)Z", (void*)radix_sort_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJJI[I[I[III)Z", (void*)radix_sort_dispatch_1 },
		{ (char*)"dispatch_indirect", (char*)"(JJJJIIII)Z", (void*)radix_sort_dispatch_indirect },
		{ (char*)"dispatch_indirect_1", (char*)"(JJJIJIIII)Z", (void*)radix_sort_dispatch_indirect_1 },
		{ (char*)"dispatch_indirect_2", (char*)"(JJJJJIIIII)Z", (void*)radix_sort_dispatch_indirect_2 },
	};
	
	// Tellusim::BitonicSort::DispatchParameters
	static jlong bitonic_sort_dispatch_parameters_new(TS_JNI_ARGS) {
		return newBitonicSortDispatchParameters();
	}
	static jlong bitonic_sort_dispatch_parameters_copy(TS_JNI_ARGS, jlong self) {
		return newBitonicSortDispatchParameters(toBitonicSortDispatchParameters(self));
	}
	static void bitonic_sort_dispatch_parameters_delete(TS_JNI_ARGS, jlong self) {
		delete (BitonicSort::DispatchParameters*)self;
	}
	static void bitonic_sort_dispatch_parameters_set_keys_offset(TS_JNI_ARGS, jlong self, jint keys_offset) {
		toBitonicSortDispatchParameters(self).keys_offset = keys_offset;
	}
	static jint bitonic_sort_dispatch_parameters_get_keys_offset(TS_JNI_ARGS, jlong self) {
		return toBitonicSortDispatchParameters(self).keys_offset;
	}
	static void bitonic_sort_dispatch_parameters_set_data_offset(TS_JNI_ARGS, jlong self, jint data_offset) {
		toBitonicSortDispatchParameters(self).data_offset = data_offset;
	}
	static jint bitonic_sort_dispatch_parameters_get_data_offset(TS_JNI_ARGS, jlong self) {
		return toBitonicSortDispatchParameters(self).data_offset;
	}
	static void bitonic_sort_dispatch_parameters_set_size(TS_JNI_ARGS, jlong self, jint size) {
		toBitonicSortDispatchParameters(self).size = size;
	}
	static jint bitonic_sort_dispatch_parameters_get_size(TS_JNI_ARGS, jlong self) {
		return toBitonicSortDispatchParameters(self).size;
	}
	static const JNINativeMethod bitonic_sort_dispatch_parameters_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)bitonic_sort_dispatch_parameters_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)bitonic_sort_dispatch_parameters_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)bitonic_sort_dispatch_parameters_delete },
		{ (char*)"set_keys_offset_", (char*)"(JI)V", (void*)bitonic_sort_dispatch_parameters_set_keys_offset },
		{ (char*)"get_keys_offset_", (char*)"(J)I", (void*)bitonic_sort_dispatch_parameters_get_keys_offset },
		{ (char*)"set_data_offset_", (char*)"(JI)V", (void*)bitonic_sort_dispatch_parameters_set_data_offset },
		{ (char*)"get_data_offset_", (char*)"(J)I", (void*)bitonic_sort_dispatch_parameters_get_data_offset },
		{ (char*)"set_size_", (char*)"(JI)V", (void*)bitonic_sort_dispatch_parameters_set_size },
		{ (char*)"get_size_", (char*)"(J)I", (void*)bitonic_sort_dispatch_parameters_get_size },
	};
	// Tellusim::BitonicSort
	static jlong bitonic_sort_new(TS_JNI_ARGS) {
		return newBitonicSort();
	}
	static void bitonic_sort_delete(TS_JNI_ARGS, jlong self) {
		delete (BitonicSort*)self;
	}
	static jboolean bitonic_sort_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toBitonicSort(self) == toBitonicSort(ptr));
	}
	static jlong bitonic_sort_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newBitonicSort(toBitonicSort(self).clonePtr());
	}
	static void bitonic_sort_clear_ptr(TS_JNI_ARGS, jlong self) {
		toBitonicSort(self).clearPtr();
	}
	static void bitonic_sort_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toBitonicSort(self).destroyPtr();
	}
	static void bitonic_sort_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toBitonicSort(self).acquirePtr();
	}
	static void bitonic_sort_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toBitonicSort(self).unacquirePtr();
	}
	static jboolean bitonic_sort_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toBitonicSort(self).isValidPtr();
	}
	static jboolean bitonic_sort_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toBitonicSort(self).isOwnerPtr();
	}
	static jboolean bitonic_sort_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toBitonicSort(self).isConstPtr();
	}
	static jint bitonic_sort_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toBitonicSort(self).getCountPtr();
	}
	static jlong bitonic_sort_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toBitonicSort(self).getInternalPtr();
	}
	static void bitonic_sort_clear(TS_JNI_ARGS, jlong self) {
		toBitonicSort(self).clear();
	}
	static jboolean bitonic_sort_is_created(TS_JNI_ARGS, jlong self, jint flags) {
		return toBitonicSort(self).isCreated((BitonicSort::Flags)flags);
	}
	static jint bitonic_sort_get_data_size(TS_JNI_ARGS, jlong self) {
		return toBitonicSort(self).getDataSize();
	}
	static jint bitonic_sort_get_group_size(TS_JNI_ARGS, jlong self) {
		return toBitonicSort(self).getGroupSize();
	}
	static jint bitonic_sort_get_sort_elements(TS_JNI_ARGS, jlong self) {
		return toBitonicSort(self).getSortElements();
	}
	static jint bitonic_sort_get_max_regions(TS_JNI_ARGS, jlong self) {
		return toBitonicSort(self).getMaxRegions();
	}
	static jboolean bitonic_sort_create(TS_JNI_ARGS, jlong self, jlong device, jint mode, jint size, jint groups, jint regions, jlong async) {
		return toBitonicSort(self).create(toDevice(device), (BitonicSort::Mode)mode, (uint32_t)size, (uint32_t)groups, (uint32_t)regions, (Async*)async);
	}
	static jboolean bitonic_sort_create_1(TS_JNI_ARGS, jlong self, jlong device, jint flags, jint size, jint groups, jint regions, jlong async) {
		return toBitonicSort(self).create(toDevice(device), (BitonicSort::Flags)flags, (uint32_t)size, (uint32_t)groups, (uint32_t)regions, (Async*)async);
	}
	static jboolean bitonic_sort_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jint keys_offset, jint data_offset, jint size, jint flags) {
		return toBitonicSort(self).dispatch(toCompute(compute), toBuffer(data), (uint32_t)keys_offset, (uint32_t)data_offset, (uint32_t)size, (BitonicSort::Flags)flags);
	}
	static jboolean bitonic_sort_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jint count, jintArray keys_offsets, jintArray data_offsets, jintArray sizes, jint flags) {
		return toBitonicSort(self).dispatch(toCompute(compute), toBuffer(data), (uint32_t)count, (uint32_t*)IntArray(env, keys_offsets).get(), (uint32_t*)IntArray(env, data_offsets).get(), (uint32_t*)IntArray(env, sizes).get(), (BitonicSort::Flags)flags);
	}
	static jboolean bitonic_sort_dispatch_indirect(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jlong dispatch, jint offset, jint flags) {
		return toBitonicSort(self).dispatchIndirect(toCompute(compute), toBuffer(data), toBuffer(dispatch), (uint32_t)offset, (BitonicSort::Flags)flags);
	}
	static jboolean bitonic_sort_dispatch_indirect_1(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jint count, jlong dispatch, jint offset, jint flags) {
		return toBitonicSort(self).dispatchIndirect(toCompute(compute), toBuffer(data), (uint32_t)count, toBuffer(dispatch), (uint32_t)offset, (BitonicSort::Flags)flags);
	}
	static jboolean bitonic_sort_dispatch_indirect_2(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jlong count, jlong dispatch, jint count_offset, jint dispatch_offset, jint flags) {
		return toBitonicSort(self).dispatchIndirect(toCompute(compute), toBuffer(data), toBuffer(count), toBuffer(dispatch), (uint32_t)count_offset, (uint32_t)dispatch_offset, (BitonicSort::Flags)flags);
	}
	static const JNINativeMethod bitonic_sort_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)bitonic_sort_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)bitonic_sort_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)bitonic_sort_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)bitonic_sort_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)bitonic_sort_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)bitonic_sort_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)bitonic_sort_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)bitonic_sort_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)bitonic_sort_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)bitonic_sort_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)bitonic_sort_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)bitonic_sort_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)bitonic_sort_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)bitonic_sort_clear },
		{ (char*)"is_created", (char*)"(JI)Z", (void*)bitonic_sort_is_created },
		{ (char*)"get_data_size", (char*)"(J)I", (void*)bitonic_sort_get_data_size },
		{ (char*)"get_group_size", (char*)"(J)I", (void*)bitonic_sort_get_group_size },
		{ (char*)"get_sort_elements", (char*)"(J)I", (void*)bitonic_sort_get_sort_elements },
		{ (char*)"get_max_regions", (char*)"(J)I", (void*)bitonic_sort_get_max_regions },
		{ (char*)"create_", (char*)"(JJIIIIJ)Z", (void*)bitonic_sort_create },
		{ (char*)"create_1", (char*)"(JJIIIIJ)Z", (void*)bitonic_sort_create_1 },
		{ (char*)"dispatch_", (char*)"(JJJIIII)Z", (void*)bitonic_sort_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJJI[I[I[II)Z", (void*)bitonic_sort_dispatch_1 },
		{ (char*)"dispatch_indirect", (char*)"(JJJJII)Z", (void*)bitonic_sort_dispatch_indirect },
		{ (char*)"dispatch_indirect_1", (char*)"(JJJIJII)Z", (void*)bitonic_sort_dispatch_indirect_1 },
		{ (char*)"dispatch_indirect_2", (char*)"(JJJJJIII)Z", (void*)bitonic_sort_dispatch_indirect_2 },
	};
	
	// Tellusim::SpatialGrid::DispatchParameters
	static jlong spatial_grid_dispatch_parameters_new(TS_JNI_ARGS) {
		return newSpatialGridDispatchParameters();
	}
	static jlong spatial_grid_dispatch_parameters_copy(TS_JNI_ARGS, jlong self) {
		return newSpatialGridDispatchParameters(toSpatialGridDispatchParameters(self));
	}
	static void spatial_grid_dispatch_parameters_delete(TS_JNI_ARGS, jlong self) {
		delete (SpatialGrid::DispatchParameters*)self;
	}
	static void spatial_grid_dispatch_parameters_set_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toSpatialGridDispatchParameters(self).offset = offset;
	}
	static jint spatial_grid_dispatch_parameters_get_offset(TS_JNI_ARGS, jlong self) {
		return toSpatialGridDispatchParameters(self).offset;
	}
	static void spatial_grid_dispatch_parameters_set_size(TS_JNI_ARGS, jlong self, jint size) {
		toSpatialGridDispatchParameters(self).size = size;
	}
	static jint spatial_grid_dispatch_parameters_get_size(TS_JNI_ARGS, jlong self) {
		return toSpatialGridDispatchParameters(self).size;
	}
	static const JNINativeMethod spatial_grid_dispatch_parameters_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)spatial_grid_dispatch_parameters_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)spatial_grid_dispatch_parameters_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)spatial_grid_dispatch_parameters_delete },
		{ (char*)"set_offset_", (char*)"(JI)V", (void*)spatial_grid_dispatch_parameters_set_offset },
		{ (char*)"get_offset_", (char*)"(J)I", (void*)spatial_grid_dispatch_parameters_get_offset },
		{ (char*)"set_size_", (char*)"(JI)V", (void*)spatial_grid_dispatch_parameters_set_size },
		{ (char*)"get_size_", (char*)"(J)I", (void*)spatial_grid_dispatch_parameters_get_size },
	};
	// Tellusim::SpatialGrid
	static jlong spatial_grid_new(TS_JNI_ARGS) {
		return newSpatialGrid();
	}
	static void spatial_grid_delete(TS_JNI_ARGS, jlong self) {
		delete (SpatialGrid*)self;
	}
	static jboolean spatial_grid_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toSpatialGrid(self) == toSpatialGrid(ptr));
	}
	static jlong spatial_grid_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newSpatialGrid(toSpatialGrid(self).clonePtr());
	}
	static void spatial_grid_clear_ptr(TS_JNI_ARGS, jlong self) {
		toSpatialGrid(self).clearPtr();
	}
	static void spatial_grid_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toSpatialGrid(self).destroyPtr();
	}
	static void spatial_grid_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toSpatialGrid(self).acquirePtr();
	}
	static void spatial_grid_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toSpatialGrid(self).unacquirePtr();
	}
	static jboolean spatial_grid_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toSpatialGrid(self).isValidPtr();
	}
	static jboolean spatial_grid_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toSpatialGrid(self).isOwnerPtr();
	}
	static jboolean spatial_grid_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toSpatialGrid(self).isConstPtr();
	}
	static jint spatial_grid_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toSpatialGrid(self).getCountPtr();
	}
	static jlong spatial_grid_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toSpatialGrid(self).getInternalPtr();
	}
	static void spatial_grid_clear(TS_JNI_ARGS, jlong self) {
		toSpatialGrid(self).clear();
	}
	static jboolean spatial_grid_is_created(TS_JNI_ARGS, jlong self) {
		return toSpatialGrid(self).isCreated();
	}
	static jint spatial_grid_get_group_size(TS_JNI_ARGS, jlong self) {
		return toSpatialGrid(self).getGroupSize();
	}
	static jlong spatial_grid_get_radix_sort(TS_JNI_ARGS, jlong self) {
		return newRadixSort(toSpatialGrid(self).getRadixSort());
	}
	static jboolean spatial_grid_create(TS_JNI_ARGS, jlong self, jlong device, jlong sort, jint groups) {
		return toSpatialGrid(self).create(toDevice(device), toRadixSort(sort), (uint32_t)groups);
	}
	static jboolean spatial_grid_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jint offset, jint size, jint bits) {
		return toSpatialGrid(self).dispatch(toCompute(compute), toBuffer(data), (uint32_t)offset, (uint32_t)size, (uint32_t)bits);
	}
	static jboolean spatial_grid_dispatch_indirect(TS_JNI_ARGS, jlong self, jlong compute, jlong data, jlong dispatch, jint offset, jint max_size) {
		return toSpatialGrid(self).dispatchIndirect(toCompute(compute), toBuffer(data), toBuffer(dispatch), (uint32_t)offset, (uint32_t)max_size);
	}
	static const JNINativeMethod spatial_grid_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)spatial_grid_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)spatial_grid_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)spatial_grid_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)spatial_grid_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)spatial_grid_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)spatial_grid_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)spatial_grid_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)spatial_grid_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)spatial_grid_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)spatial_grid_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)spatial_grid_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)spatial_grid_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)spatial_grid_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)spatial_grid_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)spatial_grid_is_created },
		{ (char*)"get_group_size", (char*)"(J)I", (void*)spatial_grid_get_group_size },
		{ (char*)"get_radix_sort", (char*)"(J)J", (void*)spatial_grid_get_radix_sort },
		{ (char*)"create_", (char*)"(JJJI)Z", (void*)spatial_grid_create },
		{ (char*)"dispatch_", (char*)"(JJJIII)Z", (void*)spatial_grid_dispatch },
		{ (char*)"dispatch_indirect", (char*)"(JJJJII)Z", (void*)spatial_grid_dispatch_indirect },
	};
	
	// Tellusim::SpatialTree::Node
	static jlong spatial_tree_node_new(TS_JNI_ARGS) {
		return newSpatialTreeNode();
	}
	static jlong spatial_tree_node_copy(TS_JNI_ARGS, jlong self) {
		return newSpatialTreeNode(toSpatialTreeNode(self));
	}
	static void spatial_tree_node_delete(TS_JNI_ARGS, jlong self) {
		delete (SpatialTree::Node*)self;
	}
	static void spatial_tree_node_set_bound_min(TS_JNI_ARGS, jlong self, jlong bound_min) {
		toVector3f(bound_min).get(toSpatialTreeNode(self).bound_min);
	}
	static jlong spatial_tree_node_get_bound_min(TS_JNI_ARGS, jlong self) {
		return newVector3f(toSpatialTreeNode(self).bound_min);
	}
	static void spatial_tree_node_set_is_enabled(TS_JNI_ARGS, jlong self, jfloat is_enabled) {
		toSpatialTreeNode(self).is_enabled = is_enabled;
	}
	static jfloat spatial_tree_node_get_is_enabled(TS_JNI_ARGS, jlong self) {
		return toSpatialTreeNode(self).is_enabled;
	}
	static void spatial_tree_node_set_bound_max(TS_JNI_ARGS, jlong self, jlong bound_max) {
		toVector3f(bound_max).get(toSpatialTreeNode(self).bound_max);
	}
	static jlong spatial_tree_node_get_bound_max(TS_JNI_ARGS, jlong self) {
		return newVector3f(toSpatialTreeNode(self).bound_max);
	}
	static void spatial_tree_node_set_data(TS_JNI_ARGS, jlong self, jint data) {
		toSpatialTreeNode(self).data = data;
	}
	static jint spatial_tree_node_get_data(TS_JNI_ARGS, jlong self) {
		return toSpatialTreeNode(self).data;
	}
	static void spatial_tree_node_set_left(TS_JNI_ARGS, jlong self, jint left) {
		toSpatialTreeNode(self).left = left;
	}
	static jint spatial_tree_node_get_left(TS_JNI_ARGS, jlong self) {
		return toSpatialTreeNode(self).left;
	}
	static void spatial_tree_node_set_right(TS_JNI_ARGS, jlong self, jint right) {
		toSpatialTreeNode(self).right = right;
	}
	static jint spatial_tree_node_get_right(TS_JNI_ARGS, jlong self) {
		return toSpatialTreeNode(self).right;
	}
	static void spatial_tree_node_set_parent(TS_JNI_ARGS, jlong self, jint parent) {
		toSpatialTreeNode(self).parent = parent;
	}
	static jint spatial_tree_node_get_parent(TS_JNI_ARGS, jlong self) {
		return toSpatialTreeNode(self).parent;
	}
	static void spatial_tree_node_set_spatial(TS_JNI_ARGS, jlong self, jint spatial) {
		toSpatialTreeNode(self).spatial = spatial;
	}
	static jint spatial_tree_node_get_spatial(TS_JNI_ARGS, jlong self) {
		return toSpatialTreeNode(self).spatial;
	}
	static const JNINativeMethod spatial_tree_node_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)spatial_tree_node_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)spatial_tree_node_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)spatial_tree_node_delete },
		{ (char*)"set_bound_min_", (char*)"(JJ)V", (void*)spatial_tree_node_set_bound_min },
		{ (char*)"get_bound_min_", (char*)"(J)J", (void*)spatial_tree_node_get_bound_min },
		{ (char*)"set_is_enabled_", (char*)"(JF)V", (void*)spatial_tree_node_set_is_enabled },
		{ (char*)"get_is_enabled_", (char*)"(J)F", (void*)spatial_tree_node_get_is_enabled },
		{ (char*)"set_bound_max_", (char*)"(JJ)V", (void*)spatial_tree_node_set_bound_max },
		{ (char*)"get_bound_max_", (char*)"(J)J", (void*)spatial_tree_node_get_bound_max },
		{ (char*)"set_data_", (char*)"(JI)V", (void*)spatial_tree_node_set_data },
		{ (char*)"get_data_", (char*)"(J)I", (void*)spatial_tree_node_get_data },
		{ (char*)"set_left_", (char*)"(JI)V", (void*)spatial_tree_node_set_left },
		{ (char*)"get_left_", (char*)"(J)I", (void*)spatial_tree_node_get_left },
		{ (char*)"set_right_", (char*)"(JI)V", (void*)spatial_tree_node_set_right },
		{ (char*)"get_right_", (char*)"(J)I", (void*)spatial_tree_node_get_right },
		{ (char*)"set_parent_", (char*)"(JI)V", (void*)spatial_tree_node_set_parent },
		{ (char*)"get_parent_", (char*)"(J)I", (void*)spatial_tree_node_get_parent },
		{ (char*)"set_spatial_", (char*)"(JI)V", (void*)spatial_tree_node_set_spatial },
		{ (char*)"get_spatial_", (char*)"(J)I", (void*)spatial_tree_node_get_spatial },
	};
	// Tellusim::SpatialTree::DispatchParameters
	static jlong spatial_tree_dispatch_parameters_new(TS_JNI_ARGS) {
		return newSpatialTreeDispatchParameters();
	}
	static jlong spatial_tree_dispatch_parameters_copy(TS_JNI_ARGS, jlong self) {
		return newSpatialTreeDispatchParameters(toSpatialTreeDispatchParameters(self));
	}
	static void spatial_tree_dispatch_parameters_delete(TS_JNI_ARGS, jlong self) {
		delete (SpatialTree::DispatchParameters*)self;
	}
	static void spatial_tree_dispatch_parameters_set_offset(TS_JNI_ARGS, jlong self, jint offset) {
		toSpatialTreeDispatchParameters(self).offset = offset;
	}
	static jint spatial_tree_dispatch_parameters_get_offset(TS_JNI_ARGS, jlong self) {
		return toSpatialTreeDispatchParameters(self).offset;
	}
	static void spatial_tree_dispatch_parameters_set_size(TS_JNI_ARGS, jlong self, jint size) {
		toSpatialTreeDispatchParameters(self).size = size;
	}
	static jint spatial_tree_dispatch_parameters_get_size(TS_JNI_ARGS, jlong self) {
		return toSpatialTreeDispatchParameters(self).size;
	}
	static const JNINativeMethod spatial_tree_dispatch_parameters_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)spatial_tree_dispatch_parameters_new },
		{ (char*)"copy_", (char*)"(J)J", (void*)spatial_tree_dispatch_parameters_copy },
		{ (char*)"delete_", (char*)"(J)V", (void*)spatial_tree_dispatch_parameters_delete },
		{ (char*)"set_offset_", (char*)"(JI)V", (void*)spatial_tree_dispatch_parameters_set_offset },
		{ (char*)"get_offset_", (char*)"(J)I", (void*)spatial_tree_dispatch_parameters_get_offset },
		{ (char*)"set_size_", (char*)"(JI)V", (void*)spatial_tree_dispatch_parameters_set_size },
		{ (char*)"get_size_", (char*)"(J)I", (void*)spatial_tree_dispatch_parameters_get_size },
	};
	// Tellusim::SpatialTree
	static jlong spatial_tree_new(TS_JNI_ARGS) {
		return newSpatialTree();
	}
	static void spatial_tree_delete(TS_JNI_ARGS, jlong self) {
		delete (SpatialTree*)self;
	}
	static jboolean spatial_tree_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toSpatialTree(self) == toSpatialTree(ptr));
	}
	static jlong spatial_tree_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newSpatialTree(toSpatialTree(self).clonePtr());
	}
	static void spatial_tree_clear_ptr(TS_JNI_ARGS, jlong self) {
		toSpatialTree(self).clearPtr();
	}
	static void spatial_tree_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toSpatialTree(self).destroyPtr();
	}
	static void spatial_tree_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toSpatialTree(self).acquirePtr();
	}
	static void spatial_tree_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toSpatialTree(self).unacquirePtr();
	}
	static jboolean spatial_tree_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toSpatialTree(self).isValidPtr();
	}
	static jboolean spatial_tree_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toSpatialTree(self).isOwnerPtr();
	}
	static jboolean spatial_tree_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toSpatialTree(self).isConstPtr();
	}
	static jint spatial_tree_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toSpatialTree(self).getCountPtr();
	}
	static jlong spatial_tree_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toSpatialTree(self).getInternalPtr();
	}
	static void spatial_tree_clear(TS_JNI_ARGS, jlong self) {
		toSpatialTree(self).clear();
	}
	static jboolean spatial_tree_is_created(TS_JNI_ARGS, jlong self, jint flags) {
		return toSpatialTree(self).isCreated((SpatialTree::Flags)flags);
	}
	static jint spatial_tree_get_group_size(TS_JNI_ARGS, jlong self) {
		return toSpatialTree(self).getGroupSize();
	}
	static jint spatial_tree_get_bounds_nodes(TS_JNI_ARGS, jlong self) {
		return toSpatialTree(self).getBoundsNodes();
	}
	static jint spatial_tree_get_max_nodes(TS_JNI_ARGS, jlong self) {
		return toSpatialTree(self).getMaxNodes();
	}
	static jint spatial_tree_get_max_regions(TS_JNI_ARGS, jlong self) {
		return toSpatialTree(self).getMaxRegions();
	}
	static jlong spatial_tree_get_radix_sort(TS_JNI_ARGS, jlong self) {
		return newRadixSort(toSpatialTree(self).getRadixSort());
	}
	static jlong spatial_tree_get_hash_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toSpatialTree(self).getHashBuffer());
	}
	static jlong spatial_tree_get_parents_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toSpatialTree(self).getParentsBuffer());
	}
	static jlong spatial_tree_get_counter_buffer(TS_JNI_ARGS, jlong self) {
		return newBuffer(toSpatialTree(self).getCounterBuffer());
	}
	static jboolean spatial_tree_create(TS_JNI_ARGS, jlong self, jlong device, jint mode, jlong sort, jint size, jint groups, jint regions, jlong async) {
		return toSpatialTree(self).create(toDevice(device), (SpatialTree::Mode)mode, toRadixSort(sort), (uint32_t)size, (uint32_t)groups, (uint32_t)regions, (Async*)async);
	}
	static jboolean spatial_tree_create_1(TS_JNI_ARGS, jlong self, jlong device, jint flags, jlong sort, jint size, jint groups, jint regions, jlong async) {
		return toSpatialTree(self).create(toDevice(device), (SpatialTree::Flags)flags, toRadixSort(sort), (uint32_t)size, (uint32_t)groups, (uint32_t)regions, (Async*)async);
	}
	static jboolean spatial_tree_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jint hash, jlong nodes, jint offset, jint size, jint flags) {
		return toSpatialTree(self).dispatch(toCompute(compute), (SpatialTree::Hash)hash, toBuffer(nodes), (uint32_t)offset, (uint32_t)size, (SpatialTree::Flags)flags);
	}
	static jboolean spatial_tree_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jint hash, jlong nodes, jint count, jintArray offsets, jintArray sizes, jint flags) {
		return toSpatialTree(self).dispatch(toCompute(compute), (SpatialTree::Hash)hash, toBuffer(nodes), (uint32_t)count, (uint32_t*)IntArray(env, offsets).get(), (uint32_t*)IntArray(env, sizes).get(), (SpatialTree::Flags)flags);
	}
	static jboolean spatial_tree_dispatch_indirect(TS_JNI_ARGS, jlong self, jlong compute, jint hash, jlong nodes, jlong dispatch, jint offset, jint max_size) {
		return toSpatialTree(self).dispatchIndirect(toCompute(compute), (SpatialTree::Hash)hash, toBuffer(nodes), toBuffer(dispatch), (uint32_t)offset, (uint32_t)max_size);
	}
	static jboolean spatial_tree_dispatch_indirect_1(TS_JNI_ARGS, jlong self, jlong compute, jint hash, jlong nodes, jint count, jlong dispatch, jint offset, jint max_size) {
		return toSpatialTree(self).dispatchIndirect(toCompute(compute), (SpatialTree::Hash)hash, toBuffer(nodes), (uint32_t)count, toBuffer(dispatch), (uint32_t)offset, (uint32_t)max_size);
	}
	static const JNINativeMethod spatial_tree_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)spatial_tree_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)spatial_tree_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)spatial_tree_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)spatial_tree_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)spatial_tree_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)spatial_tree_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)spatial_tree_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)spatial_tree_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)spatial_tree_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)spatial_tree_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)spatial_tree_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)spatial_tree_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)spatial_tree_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)spatial_tree_clear },
		{ (char*)"is_created", (char*)"(JI)Z", (void*)spatial_tree_is_created },
		{ (char*)"get_group_size", (char*)"(J)I", (void*)spatial_tree_get_group_size },
		{ (char*)"get_bounds_nodes", (char*)"(J)I", (void*)spatial_tree_get_bounds_nodes },
		{ (char*)"get_max_nodes", (char*)"(J)I", (void*)spatial_tree_get_max_nodes },
		{ (char*)"get_max_regions", (char*)"(J)I", (void*)spatial_tree_get_max_regions },
		{ (char*)"get_radix_sort", (char*)"(J)J", (void*)spatial_tree_get_radix_sort },
		{ (char*)"get_hash_buffer", (char*)"(J)J", (void*)spatial_tree_get_hash_buffer },
		{ (char*)"get_parents_buffer", (char*)"(J)J", (void*)spatial_tree_get_parents_buffer },
		{ (char*)"get_counter_buffer", (char*)"(J)J", (void*)spatial_tree_get_counter_buffer },
		{ (char*)"create_", (char*)"(JJIJIIIJ)Z", (void*)spatial_tree_create },
		{ (char*)"create_1", (char*)"(JJIJIIIJ)Z", (void*)spatial_tree_create_1 },
		{ (char*)"dispatch_", (char*)"(JJIJIII)Z", (void*)spatial_tree_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJIJI[I[II)Z", (void*)spatial_tree_dispatch_1 },
		{ (char*)"dispatch_indirect", (char*)"(JJIJJII)Z", (void*)spatial_tree_dispatch_indirect },
		{ (char*)"dispatch_indirect_1", (char*)"(JJIJIJII)Z", (void*)spatial_tree_dispatch_indirect_1 },
	};
	
	// Tellusim::FourierTransform
	static jlong fourier_transform_new(TS_JNI_ARGS) {
		return newFourierTransform();
	}
	static void fourier_transform_delete(TS_JNI_ARGS, jlong self) {
		delete (FourierTransform*)self;
	}
	static jboolean fourier_transform_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toFourierTransform(self) == toFourierTransform(ptr));
	}
	static jlong fourier_transform_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newFourierTransform(toFourierTransform(self).clonePtr());
	}
	static void fourier_transform_clear_ptr(TS_JNI_ARGS, jlong self) {
		toFourierTransform(self).clearPtr();
	}
	static void fourier_transform_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toFourierTransform(self).destroyPtr();
	}
	static void fourier_transform_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toFourierTransform(self).acquirePtr();
	}
	static void fourier_transform_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toFourierTransform(self).unacquirePtr();
	}
	static jboolean fourier_transform_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toFourierTransform(self).isValidPtr();
	}
	static jboolean fourier_transform_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toFourierTransform(self).isOwnerPtr();
	}
	static jboolean fourier_transform_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toFourierTransform(self).isConstPtr();
	}
	static jint fourier_transform_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toFourierTransform(self).getCountPtr();
	}
	static jlong fourier_transform_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toFourierTransform(self).getInternalPtr();
	}
	static void fourier_transform_clear(TS_JNI_ARGS, jlong self) {
		toFourierTransform(self).clear();
	}
	static jboolean fourier_transform_is_created(TS_JNI_ARGS, jlong self, jint mode) {
		return toFourierTransform(self).isCreated((FourierTransform::Mode)mode);
	}
	static jboolean fourier_transform_is_created_1(TS_JNI_ARGS, jlong self, jint flags) {
		return toFourierTransform(self).isCreated((FourierTransform::Flags)flags);
	}
	static jint fourier_transform_get_max_width(TS_JNI_ARGS, jlong self) {
		return toFourierTransform(self).getMaxWidth();
	}
	static jint fourier_transform_get_max_height(TS_JNI_ARGS, jlong self) {
		return toFourierTransform(self).getMaxHeight();
	}
	static jboolean fourier_transform_create(TS_JNI_ARGS, jlong self, jlong device, jint mode, jint width, jint height, jlong async) {
		return toFourierTransform(self).create(toDevice(device), (FourierTransform::Mode)mode, (uint32_t)width, (uint32_t)height, (Async*)async);
	}
	static jboolean fourier_transform_create_1(TS_JNI_ARGS, jlong self, jlong device, jint flags, jint width, jint height, jlong async) {
		return toFourierTransform(self).create(toDevice(device), (FourierTransform::Flags)flags, (uint32_t)width, (uint32_t)height, (Async*)async);
	}
	static jboolean fourier_transform_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jint op, jlong dest, jlong src, jlong dest_slice, jlong src_slice) {
		return toFourierTransform(self).dispatch(toCompute(compute), (FourierTransform::Mode)mode, (FourierTransform::Operation)op, toTexture(dest), toTexture(src), toSlice(dest_slice), toSlice(src_slice));
	}
	static jboolean fourier_transform_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jint op, jlong dest, jlong src, jlong src_slice) {
		return toFourierTransform(self).dispatch(toCompute(compute), (FourierTransform::Mode)mode, (FourierTransform::Operation)op, toTexture(dest), toTexture(src), toSlice(src_slice));
	}
	static jboolean fourier_transform_dispatch_2(TS_JNI_ARGS, jlong self, jlong compute, jint mode, jint op, jlong dest, jlong src) {
		return toFourierTransform(self).dispatch(toCompute(compute), (FourierTransform::Mode)mode, (FourierTransform::Operation)op, toTexture(dest), toTexture(src));
	}
	static const JNINativeMethod fourier_transform_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)fourier_transform_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)fourier_transform_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)fourier_transform_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)fourier_transform_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)fourier_transform_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)fourier_transform_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)fourier_transform_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)fourier_transform_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)fourier_transform_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)fourier_transform_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)fourier_transform_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)fourier_transform_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)fourier_transform_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)fourier_transform_clear },
		{ (char*)"is_created", (char*)"(JI)Z", (void*)fourier_transform_is_created },
		{ (char*)"is_created_1", (char*)"(JI)Z", (void*)fourier_transform_is_created_1 },
		{ (char*)"get_max_width", (char*)"(J)I", (void*)fourier_transform_get_max_width },
		{ (char*)"get_max_height", (char*)"(J)I", (void*)fourier_transform_get_max_height },
		{ (char*)"create_", (char*)"(JJIIIJ)Z", (void*)fourier_transform_create },
		{ (char*)"create_1", (char*)"(JJIIIJ)Z", (void*)fourier_transform_create_1 },
		{ (char*)"dispatch_", (char*)"(JJIIJJJJ)Z", (void*)fourier_transform_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJIIJJJ)Z", (void*)fourier_transform_dispatch_1 },
		{ (char*)"dispatch_2", (char*)"(JJIIJJ)Z", (void*)fourier_transform_dispatch_2 },
	};
	
	// Tellusim::TensorGraph
	static jlong tensor_graph_new(TS_JNI_ARGS) {
		return newTensorGraph();
	}
	static void tensor_graph_delete(TS_JNI_ARGS, jlong self) {
		delete (TensorGraph*)self;
	}
	static jboolean tensor_graph_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toTensorGraph(self) == toTensorGraph(ptr));
	}
	static jlong tensor_graph_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newTensorGraph(toTensorGraph(self).clonePtr());
	}
	static void tensor_graph_clear_ptr(TS_JNI_ARGS, jlong self) {
		toTensorGraph(self).clearPtr();
	}
	static void tensor_graph_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toTensorGraph(self).destroyPtr();
	}
	static void tensor_graph_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toTensorGraph(self).acquirePtr();
	}
	static void tensor_graph_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toTensorGraph(self).unacquirePtr();
	}
	static jboolean tensor_graph_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toTensorGraph(self).isValidPtr();
	}
	static jboolean tensor_graph_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toTensorGraph(self).isOwnerPtr();
	}
	static jboolean tensor_graph_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toTensorGraph(self).isConstPtr();
	}
	static jint tensor_graph_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toTensorGraph(self).getCountPtr();
	}
	static jlong tensor_graph_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toTensorGraph(self).getInternalPtr();
	}
	static void tensor_graph_clear(TS_JNI_ARGS, jlong self) {
		toTensorGraph(self).clear();
	}
	static jboolean tensor_graph_is_created(TS_JNI_ARGS, jlong self) {
		return toTensorGraph(self).isCreated();
	}
	static jboolean tensor_graph_create(TS_JNI_ARGS, jlong self, jlong device, jint flags, jint masks, jlong async) {
		return toTensorGraph(self).create(toDevice(device), (TensorGraph::Flags)flags, (TensorGraph::Masks)masks, (Async*)async);
	}
	static jboolean tensor_graph_dispatch(TS_JNI_ARGS, jlong self, jlong compute, jint op, jlong dest, jint flags) {
		return toTensorGraph(self).dispatch(toCompute(compute), (TensorGraph::Operation)op, toTensor(dest), (TensorGraph::Flags)flags);
	}
	static jboolean tensor_graph_dispatch_1(TS_JNI_ARGS, jlong self, jlong compute, jint op, jlong dest, jlong src_0, jint flags) {
		return toTensorGraph(self).dispatch(toCompute(compute), (TensorGraph::Operation)op, toTensor(dest), toTensor(src_0), (TensorGraph::Flags)flags);
	}
	static jboolean tensor_graph_dispatch_2(TS_JNI_ARGS, jlong self, jlong compute, jint op, jlong dest, jlong src_0, jlong src_1, jint flags) {
		return toTensorGraph(self).dispatch(toCompute(compute), (TensorGraph::Operation)op, toTensor(dest), toTensor(src_0), toTensor(src_1), (TensorGraph::Flags)flags);
	}
	static jboolean tensor_graph_dispatch_3(TS_JNI_ARGS, jlong self, jlong compute, jint op, jlong dest, jlong src_0, jlong src_1, jlong src_2, jint flags) {
		return toTensorGraph(self).dispatch(toCompute(compute), (TensorGraph::Operation)op, toTensor(dest), toTensor(src_0), toTensor(src_1), toTensor(src_2), (TensorGraph::Flags)flags);
	}
	static jboolean tensor_graph_dispatch_4(TS_JNI_ARGS, jlong self, jlong compute, jlong dest, jlong src, jlong region, jlong slice) {
		return toTensorGraph(self).dispatch(toCompute(compute), toTensor(dest), toTexture(src), toRegion(region), toSlice(slice));
	}
	static jboolean tensor_graph_dispatch_5(TS_JNI_ARGS, jlong self, jlong compute, jlong dest, jlong src, jlong slice) {
		return toTensorGraph(self).dispatch(toCompute(compute), toTensor(dest), toTexture(src), toSlice(slice));
	}
	static jboolean tensor_graph_dispatch_6(TS_JNI_ARGS, jlong self, jlong compute, jlong dest, jlong src, jlong region, jlong slice) {
		return toTensorGraph(self).dispatch(toCompute(compute), toTexture(dest), toTensor(src), toRegion(region), toSlice(slice));
	}
	static jboolean tensor_graph_dispatch_7(TS_JNI_ARGS, jlong self, jlong compute, jlong dest, jlong src, jlong slice) {
		return toTensorGraph(self).dispatch(toCompute(compute), toTexture(dest), toTensor(src), toSlice(slice));
	}
	static const JNINativeMethod tensor_graph_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)tensor_graph_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)tensor_graph_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)tensor_graph_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)tensor_graph_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)tensor_graph_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)tensor_graph_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)tensor_graph_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)tensor_graph_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)tensor_graph_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)tensor_graph_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)tensor_graph_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)tensor_graph_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)tensor_graph_get_internal_ptr },
		{ (char*)"clear_", (char*)"(J)V", (void*)tensor_graph_clear },
		{ (char*)"is_created", (char*)"(J)Z", (void*)tensor_graph_is_created },
		{ (char*)"create_", (char*)"(JJIIJ)Z", (void*)tensor_graph_create },
		{ (char*)"dispatch_", (char*)"(JJIJI)Z", (void*)tensor_graph_dispatch },
		{ (char*)"dispatch_1", (char*)"(JJIJJI)Z", (void*)tensor_graph_dispatch_1 },
		{ (char*)"dispatch_2", (char*)"(JJIJJJI)Z", (void*)tensor_graph_dispatch_2 },
		{ (char*)"dispatch_3", (char*)"(JJIJJJJI)Z", (void*)tensor_graph_dispatch_3 },
		{ (char*)"dispatch_4", (char*)"(JJJJJJ)Z", (void*)tensor_graph_dispatch_4 },
		{ (char*)"dispatch_5", (char*)"(JJJJJ)Z", (void*)tensor_graph_dispatch_5 },
		{ (char*)"dispatch_6", (char*)"(JJJJJJ)Z", (void*)tensor_graph_dispatch_6 },
		{ (char*)"dispatch_7", (char*)"(JJJJJ)Z", (void*)tensor_graph_dispatch_7 },
	};
	
	// Tellusim::Desktop
	static jlong desktop_new(TS_JNI_ARGS) {
		return newDesktop();
	}
	static void desktop_delete(TS_JNI_ARGS, jlong self) {
		delete (Desktop*)self;
	}
	static jboolean desktop_equal_ptr(TS_JNI_ARGS, jlong self, jlong ptr) {
		return (toDesktop(self) == toDesktop(ptr));
	}
	static jlong desktop_clone_ptr(TS_JNI_ARGS, jlong self) {
		return newDesktop(toDesktop(self).clonePtr());
	}
	static void desktop_clear_ptr(TS_JNI_ARGS, jlong self) {
		toDesktop(self).clearPtr();
	}
	static void desktop_destroy_ptr(TS_JNI_ARGS, jlong self) {
		toDesktop(self).destroyPtr();
	}
	static void desktop_acquire_ptr(TS_JNI_ARGS, jlong self) {
		toDesktop(self).acquirePtr();
	}
	static void desktop_unacquire_ptr(TS_JNI_ARGS, jlong self) {
		toDesktop(self).unacquirePtr();
	}
	static jboolean desktop_is_valid_ptr(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).isValidPtr();
	}
	static jboolean desktop_is_owner_ptr(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).isOwnerPtr();
	}
	static jboolean desktop_is_const_ptr(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).isConstPtr();
	}
	static jint desktop_get_count_ptr(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).getCountPtr();
	}
	static jlong desktop_get_internal_ptr(TS_JNI_ARGS, jlong self) {
		return (jlong)toDesktop(self).getInternalPtr();
	}
	static jboolean desktop_update(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).update();
	}
	static jint desktop_get_width(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).getWidth();
	}
	static jint desktop_get_height(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).getHeight();
	}
	static jint desktop_get_position_x(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).getPositionX();
	}
	static jint desktop_get_position_y(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).getPositionY();
	}
	static jfloat desktop_get_scale(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).getScale();
	}
	static jint desktop_get_num_screens(TS_JNI_ARGS, jlong self) {
		return toDesktop(self).getNumScreens();
	}
	static jstring desktop_get_screen_name(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toDesktop(self).getScreenName((uint32_t)index).get());
	}
	static jstring desktop_get_screen_device(TS_JNI_ARGS, jlong self, jint index) {
		return env->NewStringUTF(toDesktop(self).getScreenDevice((uint32_t)index).get());
	}
	static jint desktop_get_screen_width(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).getScreenWidth((uint32_t)index);
	}
	static jint desktop_get_screen_height(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).getScreenHeight((uint32_t)index);
	}
	static jint desktop_get_screen_position_x(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).getScreenPositionX((uint32_t)index);
	}
	static jint desktop_get_screen_position_y(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).getScreenPositionY((uint32_t)index);
	}
	static jint desktop_get_screen_frequency(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).getScreenFrequency((uint32_t)index);
	}
	static jint desktop_get_num_modes(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).getNumModes((uint32_t)index);
	}
	static jint desktop_get_mode_width(TS_JNI_ARGS, jlong self, jint index, jint mode) {
		return toDesktop(self).getModeWidth((uint32_t)index, (uint32_t)mode);
	}
	static jint desktop_get_mode_height(TS_JNI_ARGS, jlong self, jint index, jint mode) {
		return toDesktop(self).getModeHeight((uint32_t)index, (uint32_t)mode);
	}
	static jint desktop_get_mode_index(TS_JNI_ARGS, jlong self, jint index, jint width, jint height) {
		return toDesktop(self).getModeIndex((uint32_t)index, (uint32_t)width, (uint32_t)height);
	}
	static jboolean desktop_set_mode(TS_JNI_ARGS, jlong self, jint index, jint width, jint height) {
		return toDesktop(self).setMode((uint32_t)index, (uint32_t)width, (uint32_t)height);
	}
	static jboolean desktop_restore_mode(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).restoreMode((uint32_t)index);
	}
	static jint desktop_get_width_1(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).getWidth((uint32_t)index);
	}
	static jint desktop_get_height_1(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).getHeight((uint32_t)index);
	}
	static jint desktop_get_position_x_1(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).getPositionX((uint32_t)index);
	}
	static jint desktop_get_position_y_1(TS_JNI_ARGS, jlong self, jint index) {
		return toDesktop(self).getPositionY((uint32_t)index);
	}
	static jint desktop_get_screen_index(TS_JNI_ARGS, jlong self, jint x, jint y) {
		return toDesktop(self).getScreenIndex(x, y);
	}
	static jboolean desktop_set_mouse(TS_JNI_ARGS, jlong self, jint x, jint y) {
		return toDesktop(self).setMouse(x, y);
	}
	static jboolean desktop_get_mouse(TS_JNI_ARGS, jlong self, jintArray x, jintArray y) {
		int32_t *x_ = (int32_t*)env->GetIntArrayElements(x, nullptr);
		int32_t *y_ = (int32_t*)env->GetIntArrayElements(y, nullptr);
		bool ret_ = toDesktop(self).getMouse(x_[0], y_[0]);
		env->ReleaseIntArrayElements(x, (jint*)x_, 0);
		env->ReleaseIntArrayElements(y, (jint*)y_, 0);
		return ret_;
	}
	static const JNINativeMethod desktop_methods[] = {
		{ (char*)"new_", (char*)"()J", (void*)desktop_new },
		{ (char*)"delete_", (char*)"(J)V", (void*)desktop_delete },
		{ (char*)"equal_ptr", (char*)"(JJ)Z", (void*)desktop_equal_ptr },
		{ (char*)"clone_ptr", (char*)"(J)J", (void*)desktop_clone_ptr },
		{ (char*)"clear_ptr", (char*)"(J)V", (void*)desktop_clear_ptr },
		{ (char*)"destroy_ptr", (char*)"(J)V", (void*)desktop_destroy_ptr },
		{ (char*)"acquire_ptr", (char*)"(J)V", (void*)desktop_acquire_ptr },
		{ (char*)"unacquire_ptr", (char*)"(J)V", (void*)desktop_unacquire_ptr },
		{ (char*)"is_valid_ptr", (char*)"(J)Z", (void*)desktop_is_valid_ptr },
		{ (char*)"is_owner_ptr", (char*)"(J)Z", (void*)desktop_is_owner_ptr },
		{ (char*)"is_const_ptr", (char*)"(J)Z", (void*)desktop_is_const_ptr },
		{ (char*)"get_count_ptr", (char*)"(J)I", (void*)desktop_get_count_ptr },
		{ (char*)"get_internal_ptr", (char*)"(J)J", (void*)desktop_get_internal_ptr },
		{ (char*)"update_", (char*)"(J)Z", (void*)desktop_update },
		{ (char*)"get_width", (char*)"(J)I", (void*)desktop_get_width },
		{ (char*)"get_height", (char*)"(J)I", (void*)desktop_get_height },
		{ (char*)"get_position_x", (char*)"(J)I", (void*)desktop_get_position_x },
		{ (char*)"get_position_y", (char*)"(J)I", (void*)desktop_get_position_y },
		{ (char*)"get_scale", (char*)"(J)F", (void*)desktop_get_scale },
		{ (char*)"get_num_screens", (char*)"(J)I", (void*)desktop_get_num_screens },
		{ (char*)"get_screen_name", (char*)"(JI)Ljava/lang/String;", (void*)desktop_get_screen_name },
		{ (char*)"get_screen_device", (char*)"(JI)Ljava/lang/String;", (void*)desktop_get_screen_device },
		{ (char*)"get_screen_width", (char*)"(JI)I", (void*)desktop_get_screen_width },
		{ (char*)"get_screen_height", (char*)"(JI)I", (void*)desktop_get_screen_height },
		{ (char*)"get_screen_position_x", (char*)"(JI)I", (void*)desktop_get_screen_position_x },
		{ (char*)"get_screen_position_y", (char*)"(JI)I", (void*)desktop_get_screen_position_y },
		{ (char*)"get_screen_frequency", (char*)"(JI)I", (void*)desktop_get_screen_frequency },
		{ (char*)"get_num_modes", (char*)"(JI)I", (void*)desktop_get_num_modes },
		{ (char*)"get_mode_width", (char*)"(JII)I", (void*)desktop_get_mode_width },
		{ (char*)"get_mode_height", (char*)"(JII)I", (void*)desktop_get_mode_height },
		{ (char*)"get_mode_index", (char*)"(JIII)I", (void*)desktop_get_mode_index },
		{ (char*)"set_mode", (char*)"(JIII)Z", (void*)desktop_set_mode },
		{ (char*)"restore_mode", (char*)"(JI)Z", (void*)desktop_restore_mode },
		{ (char*)"get_width_1", (char*)"(JI)I", (void*)desktop_get_width_1 },
		{ (char*)"get_height_1", (char*)"(JI)I", (void*)desktop_get_height_1 },
		{ (char*)"get_position_x_1", (char*)"(JI)I", (void*)desktop_get_position_x_1 },
		{ (char*)"get_position_y_1", (char*)"(JI)I", (void*)desktop_get_position_y_1 },
		{ (char*)"get_screen_index", (char*)"(JII)I", (void*)desktop_get_screen_index },
		{ (char*)"set_mouse", (char*)"(JII)Z", (void*)desktop_set_mouse },
		{ (char*)"get_mouse", (char*)"(J[I[I)Z", (void*)desktop_get_mouse },
	};
	
	// Tellusim
	static jstring base_get_platform_name(TS_JNI_ARGS, jint platform) {
		return env->NewStringUTF(Tellusim::getPlatformName((Platform)platform));
	}
	static jint base_find_platform_name(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Platform ret_ = Tellusim::findPlatformName(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean base_is_platform_available(TS_JNI_ARGS, jint platform) {
		return Tellusim::isPlatformAvailable((Platform)platform);
	}
	static jstring base_get_format_name(TS_JNI_ARGS, jint format) {
		return env->NewStringUTF(Tellusim::getFormatName((Format)format));
	}
	static jint base_find_format_name(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Format ret_ = Tellusim::findFormatName(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jstring base_get_glsl_format_name(TS_JNI_ARGS, jint format) {
		return env->NewStringUTF(Tellusim::getGLSLFormatName((Format)format));
	}
	static jint base_find_glsl_format_name(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		Format ret_ = Tellusim::findGLSLFormatName(name_);
		env->ReleaseStringUTFChars(name, name_);
		return ret_;
	}
	static jboolean base_is_color_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isColorFormat((Format)format);
	}
	static jboolean base_is_depth_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isDepthFormat((Format)format);
	}
	static jboolean base_is_pixel_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isPixelFormat((Format)format);
	}
	static jboolean base_is_plain_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isPlainFormat((Format)format);
	}
	static jboolean base_is_mixed_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isMixedFormat((Format)format);
	}
	static jboolean base_is_block_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isBlockFormat((Format)format);
	}
	static jboolean base_is_stencil_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isStencilFormat((Format)format);
	}
	static jint base_to_pixel_format(TS_JNI_ARGS, jint format) {
		return Tellusim::toPixelFormat((Format)format);
	}
	static jboolean base_is_norm_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isNormFormat((Format)format);
	}
	static jboolean base_is_srgb_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isSRGBFormat((Format)format);
	}
	static jboolean base_is_signed_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isSignedFormat((Format)format);
	}
	static jboolean base_is_unsigned_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isUnsignedFormat((Format)format);
	}
	static jboolean base_is_integer_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isIntegerFormat((Format)format);
	}
	static jboolean base_is_float_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isFloatFormat((Format)format);
	}
	static jint base_to_norm_format(TS_JNI_ARGS, jint format) {
		return Tellusim::toNormFormat((Format)format);
	}
	static jint base_to_srgb_format(TS_JNI_ARGS, jint format) {
		return Tellusim::toSRGBFormat((Format)format);
	}
	static jint base_to_signed_format(TS_JNI_ARGS, jint format) {
		return Tellusim::toSignedFormat((Format)format);
	}
	static jint base_to_unsigned_format(TS_JNI_ARGS, jint format) {
		return Tellusim::toUnsignedFormat((Format)format);
	}
	static jint base_to_float_format(TS_JNI_ARGS, jint format) {
		return Tellusim::toFloatFormat((Format)format);
	}
	static jboolean base_isi8_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isi8Format((Format)format);
	}
	static jboolean base_isu8_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isu8Format((Format)format);
	}
	static jboolean base_is8_bit_format(TS_JNI_ARGS, jint format) {
		return Tellusim::is8BitFormat((Format)format);
	}
	static jint base_to8_bit_format(TS_JNI_ARGS, jint format) {
		return Tellusim::to8BitFormat((Format)format);
	}
	static jboolean base_isi16_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isi16Format((Format)format);
	}
	static jboolean base_isu16_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isu16Format((Format)format);
	}
	static jboolean base_isf16_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isf16Format((Format)format);
	}
	static jboolean base_is16_bit_format(TS_JNI_ARGS, jint format) {
		return Tellusim::is16BitFormat((Format)format);
	}
	static jint base_to16_bit_format(TS_JNI_ARGS, jint format) {
		return Tellusim::to16BitFormat((Format)format);
	}
	static jboolean base_isi32_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isi32Format((Format)format);
	}
	static jboolean base_isu32_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isu32Format((Format)format);
	}
	static jboolean base_isf32_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isf32Format((Format)format);
	}
	static jboolean base_is32_bit_format(TS_JNI_ARGS, jint format) {
		return Tellusim::is32BitFormat((Format)format);
	}
	static jint base_to32_bit_format(TS_JNI_ARGS, jint format) {
		return Tellusim::to32BitFormat((Format)format);
	}
	static jboolean base_isi64_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isi64Format((Format)format);
	}
	static jboolean base_isu64_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isu64Format((Format)format);
	}
	static jboolean base_isf64_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isf64Format((Format)format);
	}
	static jboolean base_is64_bit_format(TS_JNI_ARGS, jint format) {
		return Tellusim::is64BitFormat((Format)format);
	}
	static jboolean base_is_bc15_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isBC15Format((Format)format);
	}
	static jboolean base_is_bc67_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isBC67Format((Format)format);
	}
	static jboolean base_is_etc2_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isETC2Format((Format)format);
	}
	static jboolean base_is_astc_format(TS_JNI_ARGS, jint format) {
		return Tellusim::isASTCFormat((Format)format);
	}
	static jint base_get_format_components(TS_JNI_ARGS, jint format) {
		return Tellusim::getFormatComponents((Format)format);
	}
	static jint base_to_format_components(TS_JNI_ARGS, jint format, jint components) {
		return Tellusim::toFormatComponents((Format)format, (uint32_t)components);
	}
	static jint base_get_format_pixel_size(TS_JNI_ARGS, jint format) {
		return Tellusim::getFormatPixelSize((Format)format);
	}
	static jint base_get_format_block_size(TS_JNI_ARGS, jint format) {
		return Tellusim::getFormatBlockSize((Format)format);
	}
	static jint base_get_format_block_width(TS_JNI_ARGS, jint format) {
		return Tellusim::getFormatBlockWidth((Format)format);
	}
	static jint base_get_format_block_height(TS_JNI_ARGS, jint format) {
		return Tellusim::getFormatBlockHeight((Format)format);
	}
	static jint base_get_pixel_format_value(TS_JNI_ARGS, jint format, jlong value, jlong src, jint stride) {
		return Tellusim::getPixelFormatValue((Format)format, toVector4f(value).v, (const void*)src, (uint32_t)stride);
	}
	static jint base_set_pixel_format_value(TS_JNI_ARGS, jint format, jlong dest, jlong value, jint stride) {
		return Tellusim::setPixelFormatValue((Format)format, (void*)dest, toVector4f(value).v, (uint32_t)stride);
	}
	static const JNINativeMethod base_methods[] = {
		{ (char*)"get_platform_name", (char*)"(I)Ljava/lang/String;", (void*)base_get_platform_name },
		{ (char*)"find_platform_name", (char*)"(Ljava/lang/String;)I", (void*)base_find_platform_name },
		{ (char*)"is_platform_available", (char*)"(I)Z", (void*)base_is_platform_available },
		{ (char*)"get_format_name", (char*)"(I)Ljava/lang/String;", (void*)base_get_format_name },
		{ (char*)"find_format_name", (char*)"(Ljava/lang/String;)I", (void*)base_find_format_name },
		{ (char*)"get_glsl_format_name", (char*)"(I)Ljava/lang/String;", (void*)base_get_glsl_format_name },
		{ (char*)"find_glsl_format_name", (char*)"(Ljava/lang/String;)I", (void*)base_find_glsl_format_name },
		{ (char*)"is_color_format", (char*)"(I)Z", (void*)base_is_color_format },
		{ (char*)"is_depth_format", (char*)"(I)Z", (void*)base_is_depth_format },
		{ (char*)"is_pixel_format", (char*)"(I)Z", (void*)base_is_pixel_format },
		{ (char*)"is_plain_format", (char*)"(I)Z", (void*)base_is_plain_format },
		{ (char*)"is_mixed_format", (char*)"(I)Z", (void*)base_is_mixed_format },
		{ (char*)"is_block_format", (char*)"(I)Z", (void*)base_is_block_format },
		{ (char*)"is_stencil_format", (char*)"(I)Z", (void*)base_is_stencil_format },
		{ (char*)"to_pixel_format", (char*)"(I)I", (void*)base_to_pixel_format },
		{ (char*)"is_norm_format", (char*)"(I)Z", (void*)base_is_norm_format },
		{ (char*)"is_srgb_format", (char*)"(I)Z", (void*)base_is_srgb_format },
		{ (char*)"is_signed_format", (char*)"(I)Z", (void*)base_is_signed_format },
		{ (char*)"is_unsigned_format", (char*)"(I)Z", (void*)base_is_unsigned_format },
		{ (char*)"is_integer_format", (char*)"(I)Z", (void*)base_is_integer_format },
		{ (char*)"is_float_format", (char*)"(I)Z", (void*)base_is_float_format },
		{ (char*)"to_norm_format", (char*)"(I)I", (void*)base_to_norm_format },
		{ (char*)"to_srgb_format", (char*)"(I)I", (void*)base_to_srgb_format },
		{ (char*)"to_signed_format", (char*)"(I)I", (void*)base_to_signed_format },
		{ (char*)"to_unsigned_format", (char*)"(I)I", (void*)base_to_unsigned_format },
		{ (char*)"to_float_format", (char*)"(I)I", (void*)base_to_float_format },
		{ (char*)"isi8_format", (char*)"(I)Z", (void*)base_isi8_format },
		{ (char*)"isu8_format", (char*)"(I)Z", (void*)base_isu8_format },
		{ (char*)"is8_bit_format", (char*)"(I)Z", (void*)base_is8_bit_format },
		{ (char*)"to8_bit_format", (char*)"(I)I", (void*)base_to8_bit_format },
		{ (char*)"isi16_format", (char*)"(I)Z", (void*)base_isi16_format },
		{ (char*)"isu16_format", (char*)"(I)Z", (void*)base_isu16_format },
		{ (char*)"isf16_format", (char*)"(I)Z", (void*)base_isf16_format },
		{ (char*)"is16_bit_format", (char*)"(I)Z", (void*)base_is16_bit_format },
		{ (char*)"to16_bit_format", (char*)"(I)I", (void*)base_to16_bit_format },
		{ (char*)"isi32_format", (char*)"(I)Z", (void*)base_isi32_format },
		{ (char*)"isu32_format", (char*)"(I)Z", (void*)base_isu32_format },
		{ (char*)"isf32_format", (char*)"(I)Z", (void*)base_isf32_format },
		{ (char*)"is32_bit_format", (char*)"(I)Z", (void*)base_is32_bit_format },
		{ (char*)"to32_bit_format", (char*)"(I)I", (void*)base_to32_bit_format },
		{ (char*)"isi64_format", (char*)"(I)Z", (void*)base_isi64_format },
		{ (char*)"isu64_format", (char*)"(I)Z", (void*)base_isu64_format },
		{ (char*)"isf64_format", (char*)"(I)Z", (void*)base_isf64_format },
		{ (char*)"is64_bit_format", (char*)"(I)Z", (void*)base_is64_bit_format },
		{ (char*)"is_bc15_format", (char*)"(I)Z", (void*)base_is_bc15_format },
		{ (char*)"is_bc67_format", (char*)"(I)Z", (void*)base_is_bc67_format },
		{ (char*)"is_etc2_format", (char*)"(I)Z", (void*)base_is_etc2_format },
		{ (char*)"is_astc_format", (char*)"(I)Z", (void*)base_is_astc_format },
		{ (char*)"get_format_components", (char*)"(I)I", (void*)base_get_format_components },
		{ (char*)"to_format_components", (char*)"(II)I", (void*)base_to_format_components },
		{ (char*)"get_format_pixel_size", (char*)"(I)I", (void*)base_get_format_pixel_size },
		{ (char*)"get_format_block_size", (char*)"(I)I", (void*)base_get_format_block_size },
		{ (char*)"get_format_block_width", (char*)"(I)I", (void*)base_get_format_block_width },
		{ (char*)"get_format_block_height", (char*)"(I)I", (void*)base_get_format_block_height },
		{ (char*)"get_pixel_format_value", (char*)"(IJJI)I", (void*)base_get_pixel_format_value },
		{ (char*)"set_pixel_format_value", (char*)"(IJJI)I", (void*)base_set_pixel_format_value },
	};
	
	// Tellusim::Allocator
	static jlong allocator_allocate(TS_JNI_ARGS, jlong size) {
		return (jlong)Allocator::allocate((size_t)size);
	}
	static jlong allocator_reallocate(TS_JNI_ARGS, jlong ptr, jlong old_size, jlong new_size) {
		return (jlong)Allocator::reallocate((void*)ptr, (size_t)old_size, (size_t)new_size);
	}
	static void allocator_free(TS_JNI_ARGS, jlong ptr, jlong size) {
		Allocator::free((const void*)ptr, (size_t)size);
	}
	static jlong allocator_get_memory(TS_JNI_ARGS) {
		return (jlong)Allocator::getMemory();
	}
	static jlong allocator_get_allocations(TS_JNI_ARGS) {
		return (jlong)Allocator::getAllocations();
	}
	static const JNINativeMethod allocator_methods[] = {
		{ (char*)"allocate_", (char*)"(J)J", (void*)allocator_allocate },
		{ (char*)"reallocate_", (char*)"(JJJ)J", (void*)allocator_reallocate },
		{ (char*)"free_", (char*)"(JJ)V", (void*)allocator_free },
		{ (char*)"get_memory", (char*)"()J", (void*)allocator_get_memory },
		{ (char*)"get_allocations", (char*)"()J", (void*)allocator_get_allocations },
	};
	
	// Tellusim::Log
	static void log_set_level(TS_JNI_ARGS, jint level) {
		Log::setLevel((Log::Level)level);
	}
	static jint log_get_level(TS_JNI_ARGS) {
		return Log::getLevel();
	}
	static void log_unlock_callback(TS_JNI_ARGS) {
		Log::unlockCallback();
	}
	static void log_lock_callback(TS_JNI_ARGS) {
		Log::lockCallback();
	}
	static void log_print(TS_JNI_ARGS, jstring str) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		Log::print(str_);
		env->ReleaseStringUTFChars(str, str_);
	}
	static void log_print_1(TS_JNI_ARGS, jint level, jstring str) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		Log::print((Log::Level)level, str_);
		env->ReleaseStringUTFChars(str, str_);
	}
	static void log_printe(TS_JNI_ARGS, jint level, jstring str) {
		const char *str_ = (str) ? env->GetStringUTFChars(str, nullptr) : nullptr;
		Log::printe((Log::Level)level, str_);
		env->ReleaseStringUTFChars(str, str_);
	}
	static const JNINativeMethod log_methods[] = {
		{ (char*)"set_level", (char*)"(I)V", (void*)log_set_level },
		{ (char*)"get_level", (char*)"()I", (void*)log_get_level },
		{ (char*)"unlock_callback", (char*)"()V", (void*)log_unlock_callback },
		{ (char*)"lock_callback", (char*)"()V", (void*)log_lock_callback },
		{ (char*)"print_", (char*)"(Ljava/lang/String;)V", (void*)log_print },
		{ (char*)"print_1", (char*)"(ILjava/lang/String;)V", (void*)log_print_1 },
		{ (char*)"printe_", (char*)"(ILjava/lang/String;)V", (void*)log_printe },
	};
	
	// Tellusim::Time
	static jlong time_current(TS_JNI_ARGS) {
		return (jlong)Time::current();
	}
	static jdouble time_seconds(TS_JNI_ARGS) {
		return Time::seconds();
	}
	static void time_sleep(TS_JNI_ARGS, jint usec) {
		Time::sleep((uint32_t)usec);
	}
	static const JNINativeMethod time_methods[] = {
		{ (char*)"current_", (char*)"()J", (void*)time_current },
		{ (char*)"seconds_", (char*)"()D", (void*)time_seconds },
		{ (char*)"sleep_", (char*)"(I)V", (void*)time_sleep },
	};
	
	// Tellusim::System
	static jint sys_get_thread_id(TS_JNI_ARGS) {
		return System::getThreadID();
	}
	static jboolean sys_set_environment(TS_JNI_ARGS, jstring name, jstring value) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		const char *value_ = (value) ? env->GetStringUTFChars(value, nullptr) : nullptr;
		bool ret_ = System::setEnvironment(name_, value_);
		env->ReleaseStringUTFChars(name, name_);
		env->ReleaseStringUTFChars(value, value_);
		return ret_;
	}
	static jboolean sys_set_environment_1(TS_JNI_ARGS, jlong name, jstring value) {
		const char *value_ = (value) ? env->GetStringUTFChars(value, nullptr) : nullptr;
		bool ret_ = System::setEnvironment(toString(name), value_);
		env->ReleaseStringUTFChars(value, value_);
		return ret_;
	}
	static jstring sys_get_environment(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		String ret_ = System::getEnvironment(name_);
		env->ReleaseStringUTFChars(name, name_);
		return env->NewStringUTF(ret_.get());
	}
	static jstring sys_get_environment_1(TS_JNI_ARGS, jlong name) {
		return env->NewStringUTF(System::getEnvironment(toString(name)).get());
	}
	static jlong sys_load_library(TS_JNI_ARGS, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		void* ret_ = System::loadLibrary(name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jlong sys_load_library_1(TS_JNI_ARGS, jlong name) {
		return (jlong)System::loadLibrary(toString(name));
	}
	static jlong sys_get_function(TS_JNI_ARGS, jlong handle, jstring name) {
		const char *name_ = (name) ? env->GetStringUTFChars(name, nullptr) : nullptr;
		void* ret_ = System::getFunction((void*)handle, name_);
		env->ReleaseStringUTFChars(name, name_);
		return (jlong)ret_;
	}
	static jlong sys_get_function_1(TS_JNI_ARGS, jlong handle, jlong name) {
		return (jlong)System::getFunction((void*)handle, toString(name));
	}
	static void sys_close_library(TS_JNI_ARGS, jlong handle) {
		System::closeLibrary((void*)handle);
	}
	static jboolean sys_exec(TS_JNI_ARGS, jstring command, jboolean wait) {
		const char *command_ = (command) ? env->GetStringUTFChars(command, nullptr) : nullptr;
		bool ret_ = System::exec(command_, (bool)wait);
		env->ReleaseStringUTFChars(command, command_);
		return ret_;
	}
	static jboolean sys_exec_1(TS_JNI_ARGS, jlong command, jboolean wait) {
		return System::exec(toString(command), (bool)wait);
	}
	static jboolean sys_open(TS_JNI_ARGS, jstring command) {
		const char *command_ = (command) ? env->GetStringUTFChars(command, nullptr) : nullptr;
		bool ret_ = System::open(command_);
		env->ReleaseStringUTFChars(command, command_);
		return ret_;
	}
	static jboolean sys_open_1(TS_JNI_ARGS, jlong command) {
		return System::open(toString(command));
	}
	static const JNINativeMethod sys_methods[] = {
		{ (char*)"get_thread_id", (char*)"()I", (void*)sys_get_thread_id },
		{ (char*)"set_environment", (char*)"(Ljava/lang/String;Ljava/lang/String;)Z", (void*)sys_set_environment },
		{ (char*)"set_environment_1", (char*)"(JLjava/lang/String;)Z", (void*)sys_set_environment_1 },
		{ (char*)"get_environment", (char*)"(Ljava/lang/String;)Ljava/lang/String;", (void*)sys_get_environment },
		{ (char*)"get_environment_1", (char*)"(J)Ljava/lang/String;", (void*)sys_get_environment_1 },
		{ (char*)"load_library", (char*)"(Ljava/lang/String;)J", (void*)sys_load_library },
		{ (char*)"load_library_1", (char*)"(J)J", (void*)sys_load_library_1 },
		{ (char*)"get_function", (char*)"(JLjava/lang/String;)J", (void*)sys_get_function },
		{ (char*)"get_function_1", (char*)"(JJ)J", (void*)sys_get_function_1 },
		{ (char*)"close_library", (char*)"(J)V", (void*)sys_close_library },
		{ (char*)"exec_", (char*)"(Ljava/lang/String;Z)Z", (void*)sys_exec },
		{ (char*)"exec_1", (char*)"(JZ)Z", (void*)sys_exec_1 },
		{ (char*)"open_", (char*)"(Ljava/lang/String;)Z", (void*)sys_open },
		{ (char*)"open_1", (char*)"(J)Z", (void*)sys_open_1 },
	};
	
	// Tellusim::MeshGraph
	static bool mesh_graph_progress_callback_func(uint32_t progress, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "MeshGraph/ProgressCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(I)Z");
			if(!clazz) TS_LOGF(Error, "mesh_graph_progress_callback_func(): can't find \"%s\" class\n", "MeshGraph/ProgressCallback");
			else if(!method_id) TS_LOGF(Error, "mesh_graph_progress_callback_func(): can't get \"%s\" method\n", "(I)Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id, (jint)progress) != 0);
		}
		return false;
	}
	static MeshGraph::ProgressCallback make_mesh_graph_progress_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(mesh_graph_progress_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return MeshGraph::ProgressCallback();
	}
	
	static jboolean mesh_graph_create(TS_JNI_ARGS, jlong dest, jlong src, jint max_attributes, jint max_primitives, jobject func, jlong async) {
		MeshGraph::ProgressCallback func_ = make_mesh_graph_progress_callback(env, func);
		return MeshGraph::create(toMesh(dest), toMesh(src), (uint32_t)max_attributes, (uint32_t)max_primitives, &func_, (Async*)async);
	}
	static const JNINativeMethod mesh_graph_methods[] = {
		{ (char*)"create_", (char*)"(JJIIL" TS_JNI_PREFIX "MeshGraph$ProgressCallback;J)Z", (void*)mesh_graph_create },
	};
	
	// Tellusim::MeshReduce
	static bool mesh_reduce_progress_callback_func(uint32_t progress, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "MeshReduce/ProgressCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(I)Z");
			if(!clazz) TS_LOGF(Error, "mesh_reduce_progress_callback_func(): can't find \"%s\" class\n", "MeshReduce/ProgressCallback");
			else if(!method_id) TS_LOGF(Error, "mesh_reduce_progress_callback_func(): can't get \"%s\" method\n", "(I)Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id, (jint)progress) != 0);
		}
		return false;
	}
	static MeshReduce::ProgressCallback make_mesh_reduce_progress_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(mesh_reduce_progress_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return MeshReduce::ProgressCallback();
	}
	
	static jboolean mesh_reduce_collapse(TS_JNI_ARGS, jlong dest, jlong src, jfloat ratio, jfloat threshold, jobject func) {
		MeshReduce::ProgressCallback func_ = make_mesh_reduce_progress_callback(env, func);
		return MeshReduce::collapse(toMesh(dest), toMesh(src), ratio, threshold, &func_);
	}
	static jboolean mesh_reduce_collapse_1(TS_JNI_ARGS, jlong dest, jlong src, jfloat ratio, jfloat threshold, jobject func, jint position) {
		MeshReduce::ProgressCallback func_ = make_mesh_reduce_progress_callback(env, func);
		return MeshReduce::collapse(toMeshGeometry(dest), toMeshGeometry(src), ratio, threshold, &func_, (uint32_t)position);
	}
	static const JNINativeMethod mesh_reduce_methods[] = {
		{ (char*)"collapse_", (char*)"(JJFFL" TS_JNI_PREFIX "MeshReduce$ProgressCallback;)Z", (void*)mesh_reduce_collapse },
		{ (char*)"collapse_1", (char*)"(JJFFL" TS_JNI_PREFIX "MeshReduce$ProgressCallback;I)Z", (void*)mesh_reduce_collapse_1 },
	};
	
	// Tellusim::MeshRefine
	static jboolean mesh_refine_subdiv(TS_JNI_ARGS, jlong dest, jlong src, jint steps) {
		return MeshRefine::subdiv(toMesh(dest), toMesh(src), (uint32_t)steps);
	}
	static jboolean mesh_refine_subdiv_1(TS_JNI_ARGS, jlong dest, jlong src, jint steps, jint position) {
		return MeshRefine::subdiv(toMeshGeometry(dest), toMeshGeometry(src), (uint32_t)steps, (uint32_t)position);
	}
	static const JNINativeMethod mesh_refine_methods[] = {
		{ (char*)"subdiv_", (char*)"(JJI)Z", (void*)mesh_refine_subdiv },
		{ (char*)"subdiv_1", (char*)"(JJII)Z", (void*)mesh_refine_subdiv_1 },
	};
	
	// Tellusim::MeshSolid
	static bool mesh_solid_progress_callback_func(uint32_t progress, JNIEnv *env, jobject func) {
		static jclass clazz = nullptr;
		static jmethodID method_id = 0;
		if(!clazz) {
			clazz = env->FindClass(TS_JNI_PREFIX "MeshSolid/ProgressCallback");
			if(clazz) method_id = env->GetMethodID(clazz, "run_", "(I)Z");
			if(!clazz) TS_LOGF(Error, "mesh_solid_progress_callback_func(): can't find \"%s\" class\n", "MeshSolid/ProgressCallback");
			else if(!method_id) TS_LOGF(Error, "mesh_solid_progress_callback_func(): can't get \"%s\" method\n", "(I)Z");
		}
		if(method_id) {
			return (env->CallBooleanMethod(func, method_id, (jint)progress) != 0);
		}
		return false;
	}
	static MeshSolid::ProgressCallback make_mesh_solid_progress_callback(JNIEnv *env, jobject func) {
		if(env && func) {
			func = env->NewGlobalRef(func);
			auto ret = makeFunction(mesh_solid_progress_callback_func);
			ret.setArg1(env);
			ret.setArg2(func);
			return ret;
		}
		return MeshSolid::ProgressCallback();
	}
	
	static jboolean mesh_solid_create(TS_JNI_ARGS, jlong dest, jlong src, jfloat ratio, jfloat threshold, jobject func) {
		MeshSolid::ProgressCallback func_ = make_mesh_solid_progress_callback(env, func);
		return MeshSolid::create(toMesh(dest), toMesh(src), ratio, threshold, &func_);
	}
	static jboolean mesh_solid_create_1(TS_JNI_ARGS, jlong dest, jlong src, jfloat ratio, jfloat threshold, jobject func, jint position) {
		MeshSolid::ProgressCallback func_ = make_mesh_solid_progress_callback(env, func);
		return MeshSolid::create(toMeshGeometry(dest), toMeshGeometry(src), ratio, threshold, &func_, (uint32_t)position);
	}
	static const JNINativeMethod mesh_solid_methods[] = {
		{ (char*)"create_", (char*)"(JJFFL" TS_JNI_PREFIX "MeshSolid$ProgressCallback;)Z", (void*)mesh_solid_create },
		{ (char*)"create_1", (char*)"(JJFFL" TS_JNI_PREFIX "MeshSolid$ProgressCallback;I)Z", (void*)mesh_solid_create_1 },
	};
	
	// Init Tellusim API
	bool jniInitAPI(JNIEnv *env) {
		#define TS_JNI_REGISTER_CLASS(NAME, METHODS) { \
			jclass clazz = env->FindClass(TS_JNI_PREFIX #NAME); \
			if(!clazz) { \
				TS_LOGE(Error, "jniInitAPI(): can't find " #NAME "\n"); \
				return false; \
			} \
			if(env->RegisterNatives(clazz, METHODS ## _methods, TS_COUNTOF(METHODS ## _methods)) < 0) { \
				TS_LOGE(Error, "jniInitAPI(): can't register " #NAME "\n"); \
				return false; \
			} \
		}
		TS_JNI_REGISTER_CLASS(Base, base)
		TS_JNI_REGISTER_CLASS(TSString, string)
		TS_JNI_REGISTER_CLASS(App, app)
		TS_JNI_REGISTER_CLASS(Async, async)
		TS_JNI_REGISTER_CLASS(Stream, stream)
		TS_JNI_REGISTER_CLASS(Blob, blob)
		TS_JNI_REGISTER_CLASS(File, file)
		TS_JNI_REGISTER_CLASS(Socket, socket)
		TS_JNI_REGISTER_CLASS(SocketSSL, socket_ssl)
		TS_JNI_REGISTER_CLASS(Source, source)
		TS_JNI_REGISTER_CLASS(Date, date)
		TS_JNI_REGISTER_CLASS(Info, info)
		TS_JNI_REGISTER_CLASS(Directory, directory)
		TS_JNI_REGISTER_CLASS(Archive, archive)
		TS_JNI_REGISTER_CLASS(Image, image)
		TS_JNI_REGISTER_CLASS(ImageSampler, image_sampler)
		TS_JNI_REGISTER_CLASS(MeshNode, mesh_node)
		TS_JNI_REGISTER_CLASS(MeshIndices, mesh_indices)
		TS_JNI_REGISTER_CLASS(MeshAttribute, mesh_attribute)
		TS_JNI_REGISTER_CLASS(MeshJoint, mesh_joint)
		TS_JNI_REGISTER_CLASS(MeshMaterial, mesh_material)
		TS_JNI_REGISTER_CLASS(MeshGeometry, mesh_geometry)
		TS_JNI_REGISTER_CLASS(MeshTransform, mesh_transform)
		TS_JNI_REGISTER_CLASS(MeshAnimation, mesh_animation)
		TS_JNI_REGISTER_CLASS(MeshAttachment, mesh_attachment)
		TS_JNI_REGISTER_CLASS(Mesh, mesh)
		TS_JNI_REGISTER_CLASS(Json, json)
		TS_JNI_REGISTER_CLASS(Xml, xml)
		TS_JNI_REGISTER_CLASS(Buffer, buffer)
		TS_JNI_REGISTER_CLASS(BufferTable, buffer_table)
		TS_JNI_REGISTER_CLASS(D3D12Buffer, d3d12_buffer)
		TS_JNI_REGISTER_CLASS(D3D11Buffer, d3d11_buffer)
		TS_JNI_REGISTER_CLASS(MTLBuffer, mtl_buffer)
		TS_JNI_REGISTER_CLASS(VKBuffer, vk_buffer)
		TS_JNI_REGISTER_CLASS(GLBuffer, gl_buffer)
		TS_JNI_REGISTER_CLASS(GLESBuffer, gles_buffer)
		TS_JNI_REGISTER_CLASS(CUBuffer, cu_buffer)
		TS_JNI_REGISTER_CLASS(HIPBuffer, hip_buffer)
		TS_JNI_REGISTER_CLASS(FUBuffer, fu_buffer)
		TS_JNI_REGISTER_CLASS(Command, command)
		TS_JNI_REGISTER_CLASS(Command$DrawArraysIndirect, command_draw_arrays_indirect)
		TS_JNI_REGISTER_CLASS(Command$DrawElementsIndirect, command_draw_elements_indirect)
		TS_JNI_REGISTER_CLASS(Command$DrawMeshIndirect, command_draw_mesh_indirect)
		TS_JNI_REGISTER_CLASS(D3D12Command, d3d12_command)
		TS_JNI_REGISTER_CLASS(MTLCommand, mtl_command)
		TS_JNI_REGISTER_CLASS(VKCommand, vk_command)
		TS_JNI_REGISTER_CLASS(FUCommand, fu_command)
		TS_JNI_REGISTER_CLASS(Compute, compute)
		TS_JNI_REGISTER_CLASS(Compute$DispatchIndirect, compute_dispatch_indirect)
		TS_JNI_REGISTER_CLASS(D3D12Compute, d3d12_compute)
		TS_JNI_REGISTER_CLASS(MTLCompute, mtl_compute)
		TS_JNI_REGISTER_CLASS(VKCompute, vk_compute)
		TS_JNI_REGISTER_CLASS(FUCompute, fu_compute)
		TS_JNI_REGISTER_CLASS(Context, context)
		TS_JNI_REGISTER_CLASS(D3D12Context, d3d12_context)
		TS_JNI_REGISTER_CLASS(D3D11Context, d3d11_context)
		TS_JNI_REGISTER_CLASS(MTLContext, mtl_context)
		TS_JNI_REGISTER_CLASS(VKContext, vk_context)
		TS_JNI_REGISTER_CLASS(GLContext, gl_context)
		TS_JNI_REGISTER_CLASS(GLESContext, gles_context)
		TS_JNI_REGISTER_CLASS(WGContext, wg_context)
		TS_JNI_REGISTER_CLASS(CUContext, cu_context)
		TS_JNI_REGISTER_CLASS(HIPContext, hip_context)
		TS_JNI_REGISTER_CLASS(Query, query)
		TS_JNI_REGISTER_CLASS(Query$Statistics, query_statistics)
		TS_JNI_REGISTER_CLASS(FUQuery, fu_query)
		TS_JNI_REGISTER_CLASS(Fence, fence)
		TS_JNI_REGISTER_CLASS(VKFence, vk_fence)
		TS_JNI_REGISTER_CLASS(FUFence, fu_fence)
		TS_JNI_REGISTER_CLASS(Shader, shader)
		TS_JNI_REGISTER_CLASS(ShaderCompiler, shader_compiler)
		TS_JNI_REGISTER_CLASS(D3D12Shader, d3d12_shader)
		TS_JNI_REGISTER_CLASS(D3D11Shader, d3d11_shader)
		TS_JNI_REGISTER_CLASS(MTLShader, mtl_shader)
		TS_JNI_REGISTER_CLASS(VKShader, vk_shader)
		TS_JNI_REGISTER_CLASS(GLShader, gl_shader)
		TS_JNI_REGISTER_CLASS(GLESShader, gles_shader)
		TS_JNI_REGISTER_CLASS(CUShader, cu_shader)
		TS_JNI_REGISTER_CLASS(HIPShader, hip_shader)
		TS_JNI_REGISTER_CLASS(FUShader, fu_shader)
		TS_JNI_REGISTER_CLASS(Sampler, sampler)
		TS_JNI_REGISTER_CLASS(MTLSampler, mtl_sampler)
		TS_JNI_REGISTER_CLASS(FUSampler, fu_sampler)
		TS_JNI_REGISTER_CLASS(Texture, texture)
		TS_JNI_REGISTER_CLASS(TextureTable, texture_table)
		TS_JNI_REGISTER_CLASS(D3D12Texture, d3d12_texture)
		TS_JNI_REGISTER_CLASS(D3D11Texture, d3d11_texture)
		TS_JNI_REGISTER_CLASS(MTLTexture, mtl_texture)
		TS_JNI_REGISTER_CLASS(VKTexture, vk_texture)
		TS_JNI_REGISTER_CLASS(GLTexture, gl_texture)
		TS_JNI_REGISTER_CLASS(GLESTexture, gles_texture)
		TS_JNI_REGISTER_CLASS(CUTexture, cu_texture)
		TS_JNI_REGISTER_CLASS(HIPTexture, hip_texture)
		TS_JNI_REGISTER_CLASS(FUTexture, fu_texture)
		TS_JNI_REGISTER_CLASS(Tracing, tracing)
		TS_JNI_REGISTER_CLASS(Tracing$Instance, tracing_instance)
		TS_JNI_REGISTER_CLASS(Tracing$BuildIndirect, tracing_build_indirect)
		TS_JNI_REGISTER_CLASS(D3D12Tracing, d3d12_tracing)
		TS_JNI_REGISTER_CLASS(MTLTracing, mtl_tracing)
		TS_JNI_REGISTER_CLASS(VKTracing, vk_tracing)
		TS_JNI_REGISTER_CLASS(FUTracing, fu_tracing)
		TS_JNI_REGISTER_CLASS(Target, target)
		TS_JNI_REGISTER_CLASS(D3D12Target, d3d12_target)
		TS_JNI_REGISTER_CLASS(D3D11Target, d3d11_target)
		TS_JNI_REGISTER_CLASS(MTLTarget, mtl_target)
		TS_JNI_REGISTER_CLASS(VKTarget, vk_target)
		TS_JNI_REGISTER_CLASS(GLTarget, gl_target)
		TS_JNI_REGISTER_CLASS(GLESTarget, gles_target)
		TS_JNI_REGISTER_CLASS(FUTarget, fu_target)
		TS_JNI_REGISTER_CLASS(Device, device)
		TS_JNI_REGISTER_CLASS(Device$Features, device_features)
		TS_JNI_REGISTER_CLASS(D3D12Device, d3d12_device)
		TS_JNI_REGISTER_CLASS(D3D11Device, d3d11_device)
		TS_JNI_REGISTER_CLASS(MTLDevice, mtl_device)
		TS_JNI_REGISTER_CLASS(VKDevice, vk_device)
		TS_JNI_REGISTER_CLASS(FUDevice, fu_device)
		TS_JNI_REGISTER_CLASS(Kernel, kernel)
		TS_JNI_REGISTER_CLASS(D3D12Kernel, d3d12_kernel)
		TS_JNI_REGISTER_CLASS(MTLKernel, mtl_kernel)
		TS_JNI_REGISTER_CLASS(FUKernel, fu_kernel)
		TS_JNI_REGISTER_CLASS(Pipeline, pipeline)
		TS_JNI_REGISTER_CLASS(D3D12Pipeline, d3d12_pipeline)
		TS_JNI_REGISTER_CLASS(MTLPipeline, mtl_pipeline)
		TS_JNI_REGISTER_CLASS(FUPipeline, fu_pipeline)
		TS_JNI_REGISTER_CLASS(Traversal, traversal)
		TS_JNI_REGISTER_CLASS(D3D12Traversal, d3d12_traversal)
		TS_JNI_REGISTER_CLASS(FUTraversal, fu_traversal)
		TS_JNI_REGISTER_CLASS(Surface, surface)
		TS_JNI_REGISTER_CLASS(D3D12Surface, d3d12_surface)
		TS_JNI_REGISTER_CLASS(D3D11Surface, d3d11_surface)
		TS_JNI_REGISTER_CLASS(MTLSurface, mtl_surface)
		TS_JNI_REGISTER_CLASS(VKSurface, vk_surface)
		TS_JNI_REGISTER_CLASS(GLSurface, gl_surface)
		TS_JNI_REGISTER_CLASS(GLESSurface, gles_surface)
		TS_JNI_REGISTER_CLASS(Window, window)
		TS_JNI_REGISTER_CLASS(Font, font)
		TS_JNI_REGISTER_CLASS(CanvasElement, canvas_element)
		TS_JNI_REGISTER_CLASS(CanvasText, canvas_text)
		TS_JNI_REGISTER_CLASS(CanvasMesh, canvas_mesh)
		TS_JNI_REGISTER_CLASS(CanvasRect, canvas_rect)
		TS_JNI_REGISTER_CLASS(CanvasTriangle, canvas_triangle)
		TS_JNI_REGISTER_CLASS(CanvasEllipse, canvas_ellipse)
		TS_JNI_REGISTER_CLASS(CanvasShape, canvas_shape)
		TS_JNI_REGISTER_CLASS(CanvasStrip, canvas_strip)
		TS_JNI_REGISTER_CLASS(Canvas, canvas)
		TS_JNI_REGISTER_CLASS(Control, control)
		TS_JNI_REGISTER_CLASS(ControlRoot, control_root)
		TS_JNI_REGISTER_CLASS(ControlText, control_text)
		TS_JNI_REGISTER_CLASS(ControlRect, control_rect)
		TS_JNI_REGISTER_CLASS(ControlGrid, control_grid)
		TS_JNI_REGISTER_CLASS(ControlGroup, control_group)
		TS_JNI_REGISTER_CLASS(ControlPanel, control_panel)
		TS_JNI_REGISTER_CLASS(ControlDialog, control_dialog)
		TS_JNI_REGISTER_CLASS(ControlWindow, control_window)
		TS_JNI_REGISTER_CLASS(ControlCheck, control_check)
		TS_JNI_REGISTER_CLASS(ControlCombo, control_combo)
		TS_JNI_REGISTER_CLASS(ControlButton, control_button)
		TS_JNI_REGISTER_CLASS(ControlSlider, control_slider)
		TS_JNI_REGISTER_CLASS(ControlScroll, control_scroll)
		TS_JNI_REGISTER_CLASS(ControlSplit, control_split)
		TS_JNI_REGISTER_CLASS(ControlArea, control_area)
		TS_JNI_REGISTER_CLASS(ControlTree, control_tree)
		TS_JNI_REGISTER_CLASS(ControlEdit, control_edit)
		TS_JNI_REGISTER_CLASS(DialogMessage, dialog_message)
		TS_JNI_REGISTER_CLASS(DialogFileOpen, dialog_file_open)
		TS_JNI_REGISTER_CLASS(DialogFileSave, dialog_file_save)
		TS_JNI_REGISTER_CLASS(DialogDirectory, dialog_directory)
		TS_JNI_REGISTER_CLASS(DialogProgress, dialog_progress)
		TS_JNI_REGISTER_CLASS(DialogColor, dialog_color)
		TS_JNI_REGISTER_CLASS(DialogMenu, dialog_menu)
		TS_JNI_REGISTER_CLASS(CubeFilter, cube_filter)
		TS_JNI_REGISTER_CLASS(DecoderJPEG, decoder_jpeg)
		TS_JNI_REGISTER_CLASS(EncoderBC15, encoder_bc15)
		TS_JNI_REGISTER_CLASS(EncoderBC67, encoder_bc67)
		TS_JNI_REGISTER_CLASS(EncoderASTC, encoder_astc)
		TS_JNI_REGISTER_CLASS(MeshModel, mesh_model)
		TS_JNI_REGISTER_CLASS(SeparableFilter, separable_filter)
		TS_JNI_REGISTER_CLASS(PrefixScan, prefix_scan)
		TS_JNI_REGISTER_CLASS(PrefixScan$DispatchParameters, prefix_scan_dispatch_parameters)
		TS_JNI_REGISTER_CLASS(RadixSort, radix_sort)
		TS_JNI_REGISTER_CLASS(RadixSort$DispatchParameters, radix_sort_dispatch_parameters)
		TS_JNI_REGISTER_CLASS(BitonicSort, bitonic_sort)
		TS_JNI_REGISTER_CLASS(BitonicSort$DispatchParameters, bitonic_sort_dispatch_parameters)
		TS_JNI_REGISTER_CLASS(SpatialGrid, spatial_grid)
		TS_JNI_REGISTER_CLASS(SpatialGrid$DispatchParameters, spatial_grid_dispatch_parameters)
		TS_JNI_REGISTER_CLASS(SpatialTree, spatial_tree)
		TS_JNI_REGISTER_CLASS(SpatialTree$Node, spatial_tree_node)
		TS_JNI_REGISTER_CLASS(SpatialTree$DispatchParameters, spatial_tree_dispatch_parameters)
		TS_JNI_REGISTER_CLASS(FourierTransform, fourier_transform)
		TS_JNI_REGISTER_CLASS(TensorGraph, tensor_graph)
		TS_JNI_REGISTER_CLASS(Desktop, desktop)
		TS_JNI_REGISTER_CLASS(Allocator, allocator)
		TS_JNI_REGISTER_CLASS(Log, log)
		TS_JNI_REGISTER_CLASS(Time, time)
		TS_JNI_REGISTER_CLASS(Sys, sys)
		TS_JNI_REGISTER_CLASS(MeshGraph, mesh_graph)
		TS_JNI_REGISTER_CLASS(MeshReduce, mesh_reduce)
		TS_JNI_REGISTER_CLASS(MeshRefine, mesh_refine)
		TS_JNI_REGISTER_CLASS(MeshSolid, mesh_solid)
		#undef TS_JNI_REGISTER_CLASS
		return true;
	}
}
