Update Files

This commit is contained in:
2025-01-22 16:18:30 +01:00
parent ed4603cf95
commit a36294b518
16718 changed files with 2960346 additions and 0 deletions

View File

@ -0,0 +1,154 @@
let project = new Project('Kha');
const pcreVersion = '10.42';
const tlsVersion = '2.28.2';
const zlibVersion = '1.2.13';
project.addFiles('khacpp/src/**.h', 'khacpp/src/**.cpp', 'khacpp/include/**.h');
project.addFiles('khacpp/project/libs/common/**.h', 'khacpp/project/libs/common/**.cpp');
if (platform === Platform.Windows || platform === Platform.WindowsApp) project.addFiles('khacpp/project/libs/msvccompat/**.cpp');
if (platform === Platform.Linux) project.addFiles('khacpp/project/libs/linuxcompat/**.cpp');
project.addFiles('khacpp/project/libs/regexp/**.h', 'khacpp/project/libs/regexp/**.cpp', 'khacpp/project/libs/std/**.h', 'khacpp/project/libs/std/**.cpp');
project.addFiles('khacpp/project/thirdparty/pcre2-' + pcreVersion + '-8/src/**.h', 'khacpp/project/thirdparty/pcre2-' + pcreVersion + '-8/src/**.c');
project.addFiles('khacpp/project/thirdparty/pcre2-' + pcreVersion + '-16/src/**.h', 'khacpp/project/thirdparty/pcre2-' + pcreVersion + '-16/src/**.c');
const zlibFiles = [
'**.h',
'adler32.c',
'compress.c',
'crc32.c',
'gzio.c',
'uncompr.c',
'deflate.c',
'trees.c',
'zutil.c',
'inflate.c',
'infback.c',
'inftrees.c',
'inffast.c'
];
for (const file of zlibFiles) {
project.addFile('khacpp/project/thirdparty/zlib-' + zlibVersion + '/' + file);
}
project.addFiles('khacpp/project/thirdparty/mbedtls-' + tlsVersion + '/**');
project.addFiles('*.cpp', '*.c', 'Backends/Kore/*.h', '*.natvis');
project.addFiles('lib/**');
project.addIncludeDir('lib');
const pcreExcludes = [
'pcre2_dftables.c',
'pcre2_fuzzsupport.c',
'pcre2_printint.c',
'pcre2_jit_match.c',
'pcre2_jit_misc.c',
'pcre2_jit_test.c',
'pcre2_ucptables.c',
'pcre2demo.c',
'pcre2grep.c',
'pcre2posix.h',
'pcre2posix.c',
'pcre2posix_test.c',
'pcre2test.c',
'sljit/**'
];
for (const file of pcreExcludes) {
project.addExclude('khacpp/project/thirdparty/pcre2-' + pcreVersion + '-8/src/' + file);
project.addExclude('khacpp/project/thirdparty/pcre2-' + pcreVersion + '-16/src/' + file);
}
project.addExcludes('khacpp/src/ExampleMain.cpp', 'khacpp/src/hx/Scriptable.cpp', 'khacpp/src/hx/NoFiles.cpp', 'khacpp/src/hx/cppia/**');
project.addExcludes('khacpp/src/hx/Debugger.cpp', 'khacpp/src/hx/Profiler.cpp', 'khacpp/src/hx/Telemetry.cpp');
project.addExcludes('khacpp/src/hx/NekoAPI.cpp');
project.addExcludes('khacpp/src/hx/libs/sqlite/**');
project.addExcludes('khacpp/src/hx/libs/mysql/**');
project.addIncludeDirs('khacpp/include', 'khacpp/project/thirdparty/zlib-' + zlibVersion, 'khacpp/project/libs/nekoapi', 'khacpp/project/thirdparty/mbedtls-' + tlsVersion + '/include');
project.addIncludeDir('khacpp/src/hx/libs/ssl');
//if (options.vrApi == "rift") {
// out += "project.addIncludeDirs('C:/khaviar/LibOVRKernel/Src/');\n";
// out += "project.addIncludeDirs('C:/khaviar/LibOVR/Include/');\n";
//}
if (platform !== Platform.Android) {
project.addExcludes('khacpp/src/hx/AndroidCompat.cpp');
}
if (platform === Platform.Windows) {
project.addDefine('HX_WINDOWS');
project.addLib('Shlwapi');
project.addLib('Crypt32');
}
if (platform === Platform.WindowsApp) {
project.addDefine('HX_WINDOWS');
project.addDefine('HX_WINRT');
}
if (platform !== Platform.Windows || audio !== AudioApi.DirectSound) {
project.addDefine('KORE_MULTITHREADED_AUDIO');
}
if (platform === Platform.OSX) {
project.addDefine('HXCPP_M64');
project.addDefine('HX_MACOS');
}
if (platform === Platform.Linux) project.addDefine('HX_LINUX');
if (platform === Platform.iOS) {
project.addDefine('IPHONE');
project.addDefine('HX_IPHONE');
}
if (platform === Platform.tvOS) {
project.addDefine('APPLETV');
}
if (platform === Platform.Android) {
project.addDefine('ANDROID');
project.addDefine('_ANDROID');
project.addDefine('HX_ANDROID');
project.addDefine('HXCPP_ANDROID_PLATFORM=24');
}
if (platform === Platform.OSX) {
project.addDefine('KORE_DEBUGDIR="osx"');
project.addLib('Security');
}
if (platform === Platform.iOS) project.addDefine('KORE_DEBUGDIR="ios"');
// project:addDefine('HXCPP_SCRIPTABLE');
project.addDefine('STATIC_LINK');
project.addDefine('PCRE2_STATIC');
project.addDefine('HXCPP_VISIT_ALLOCS');
project.addDefine('KHA');
project.addDefine('KORE');
project.addDefine('ROTATE90');
project.addDefine('HAVE_CONFIG_H');
project.addDefine('SUPPORT_UTF');
project.addDefine('SUPPORT_UCP');
project.addDefine('SUPPORT_UNICODE');
project.addDefine('MBEDTLS_USER_CONFIG_FILE="mbedtls_config.h"');
project.addDefine('HX_SMART_STRINGS');
//if (Options.vrApi === "gearvr") {
// out += "project.addDefine('VR_GEAR_VR');\n";
//}
//else if (Options.vrApi === "cardboard") {
// out += "project.addDefine('VR_CARDBOARD');\n";
//}
//else if (Options.vrApi === "rift") {
// out += "project.addDefine('VR_RIFT');\n";
//}
//
//if (options.vrApi == "rift") {
// out += "project.addLib('C:/khaviar/LibOVRKernel/Lib/Windows/Win32/Release/VS2013/LibOVRKernel');\n";
// out += "project.addLib('C:/khaviar/LibOVR/Lib/Windows/Win32/Release/VS2013/LibOVR');\n";
//}
if (platform === Platform.Windows || platform === Platform.WindowsApp) {
project.addDefine('_WINSOCK_DEPRECATED_NO_WARNINGS');
}
if (platform === Platform.Windows) {
project.addLib('ws2_32');
}
resolve(project);

View File

@ -0,0 +1,3 @@
package kha;
typedef Blob = kha.internal.BytesBlob;

View File

@ -0,0 +1,150 @@
package kha;
@:headerCode("
#include <kinc/display.h>
")
class Display {
var num: Int;
static var displays: Array<Display> = null;
function new(num: Int) {
this.num = num;
}
@:functionCode("return kinc_count_displays();")
static function count(): Int {
return 0;
}
@:functionCode("kinc_display_init();")
static function initKoreDisplay(): Void {}
public static function init() {
if (displays == null) {
initKoreDisplay();
displays = [];
for (i in 0...count()) {
displays.push(new Display(i));
}
}
}
@:functionCode("return kinc_primary_display();")
static function primaryId() {
return 0;
}
public static var primary(get, never): Display;
static function get_primary(): Display {
init();
return displays[primaryId()];
}
public static var all(get, never): Array<Display>;
static function get_all(): Array<Display> {
init();
return displays;
}
public var available(get, never): Bool;
@:functionCode("return kinc_display_available(num);")
function get_available(): Bool {
return true;
}
public var name(get, never): String;
@:functionCode("return ::String(kinc_display_name(num));")
function get_name(): String {
return "Display";
}
public var x(get, never): Int;
@:functionCode("return kinc_display_current_mode(num).x;")
function get_x(): Int {
return 0;
}
public var y(get, never): Int;
@:functionCode("return kinc_display_current_mode(num).y;")
function get_y(): Int {
return 0;
}
public var width(get, never): Int;
@:functionCode("return kinc_display_current_mode(num).width;")
function get_width(): Int {
return 800;
}
public var height(get, never): Int;
@:functionCode("return kinc_display_current_mode(num).height;")
function get_height(): Int {
return 600;
}
public var frequency(get, never): Int;
@:functionCode("return kinc_display_current_mode(num).frequency;")
function get_frequency(): Int {
return 60;
}
public var pixelsPerInch(get, never): Int;
@:functionCode("return kinc_display_current_mode(num).pixels_per_inch;")
function get_pixelsPerInch(): Int {
return 72;
}
public var modes(get, never): Array<DisplayMode>;
var allModes: Array<DisplayMode> = null;
@:functionCode("return kinc_display_count_available_modes(num);")
function modeCount(): Int {
return 0;
}
@:functionCode("return kinc_display_available_mode(num, modeIndex).width;")
function getModeWidth(modeIndex: Int) {
return 800;
}
@:functionCode("return kinc_display_available_mode(num, modeIndex).height;")
function getModeHeight(modeIndex: Int) {
return 600;
}
@:functionCode("return kinc_display_available_mode(num, modeIndex).frequency;")
function getModeFrequency(modeIndex: Int) {
return 60;
}
@:functionCode("return kinc_display_available_mode(num, modeIndex).bits_per_pixel;")
function getModeBitsPerPixel(modeIndex: Int) {
return 32;
}
function initModes() {
if (allModes == null) {
allModes = [];
for (i in 0...modeCount()) {
allModes.push(new DisplayMode(getModeWidth(i), getModeHeight(i), getModeFrequency(i), getModeBitsPerPixel(i)));
}
}
}
function get_modes(): Array<DisplayMode> {
initModes();
return allModes;
}
}

View File

@ -0,0 +1,3 @@
package kha;
typedef Font = kha.Kravur;

View File

@ -0,0 +1,559 @@
package kha;
import haxe.io.Bytes;
import haxe.io.BytesData;
import kha.kore.graphics4.TextureUnit;
import kha.graphics4.TextureFormat;
import kha.graphics4.DepthStencilFormat;
import kha.graphics4.Usage;
@:headerCode("
#include <kinc/graphics4/rendertarget.h>
#include <kinc/graphics4/texture.h>
#include <kinc/graphics4/texturearray.h>
#include <kinc/video.h>
#include <assert.h>
enum KhaImageType {
KhaImageTypeNone,
KhaImageTypeTexture,
KhaImageTypeRenderTarget,
KhaImageTypeTextureArray
};
")
@:headerClassCode("
KhaImageType imageType;
int originalWidth;
int originalHeight;
uint8_t *imageData;
bool ownsImageData;
kinc_g4_texture_t texture;
kinc_g4_render_target_t renderTarget;
kinc_g4_texture_array_t textureArray;
")
class Image implements Canvas implements Resource {
var myFormat: TextureFormat;
var readable: Bool;
var graphics1: kha.graphics1.Graphics;
var graphics2: kha.graphics2.Graphics;
var graphics4: kha.graphics4.Graphics;
public static function fromVideo(video: Video): Image {
var image = new Image(false, false);
image.myFormat = RGBA32;
image.initVideo(cast(video, kha.kore.Video));
return image;
}
public static function create(width: Int, height: Int, format: TextureFormat = null, usage: Usage = null, readable: Bool = false): Image {
return _create2(width, height, format == null ? TextureFormat.RGBA32 : format, readable, false, NoDepthAndStencil, 0);
}
public static function create3D(width: Int, height: Int, depth: Int, format: TextureFormat = null, usage: Usage = null, readable: Bool = false): Image {
return _create3(width, height, depth, format == null ? TextureFormat.RGBA32 : format, readable, 0);
}
public static function createRenderTarget(width: Int, height: Int, format: TextureFormat = null, depthStencil: DepthStencilFormat = NoDepthAndStencil,
antiAliasingSamples: Int = 1): Image {
return _create2(width, height, format == null ? TextureFormat.RGBA32 : format, false, true, depthStencil, antiAliasingSamples);
}
/**
* The provided images need to be readable.
*/
public static function createArray(images: Array<Image>, format: TextureFormat = null): Image {
var image = new Image(false);
image.myFormat = (format == null) ? TextureFormat.RGBA32 : format;
initArrayTexture(image, images);
return image;
}
@:functionCode("
kinc_image_t *kincImages = (kinc_image_t*)malloc(sizeof(kinc_image_t) * images->length);
for (unsigned i = 0; i < images->length; ++i) {
kinc_image_init(&kincImages[i], images->__get(i).StaticCast<::kha::Image>()->imageData, images->__get(i).StaticCast<::kha::Image>()->originalWidth, images->__get(i).StaticCast<::kha::Image>()->originalHeight, (kinc_image_format_t)getTextureFormat(images->__get(i).StaticCast<::kha::Image>()->myFormat));
}
kinc_g4_texture_array_init(&source->textureArray, kincImages, images->length);
for (unsigned i = 0; i < images->length; ++i) {
kinc_image_destroy(&kincImages[i]);
}
free(kincImages);
")
static function initArrayTexture(source: Image, images: Array<Image>): Void {}
public static function fromBytes(bytes: Bytes, width: Int, height: Int, format: TextureFormat = null, usage: Usage = null, readable: Bool = false): Image {
var image = new Image(readable);
image.myFormat = format;
image.initFromBytes(bytes.getData(), width, height, getTextureFormat(format));
return image;
}
@:functionCode("
kinc_image_t image;
kinc_image_init(&image, bytes.GetPtr()->GetBase(), width, height, (kinc_image_format_t)format);
kinc_g4_texture_init_from_image(&texture, &image);
if (readable) {
imageData = (uint8_t*)image.data;
}
kinc_image_destroy(&image);
imageType = KhaImageTypeTexture;
originalWidth = width;
originalHeight = height;
")
function initFromBytes(bytes: BytesData, width: Int, height: Int, format: Int): Void {}
public static function fromBytes3D(bytes: Bytes, width: Int, height: Int, depth: Int, format: TextureFormat = null, usage: Usage = null,
readable: Bool = false): Image {
var image = new Image(readable);
image.myFormat = format;
image.initFromBytes3D(bytes.getData(), width, height, depth, getTextureFormat(format));
return image;
}
@:functionCode("
kinc_image_t image;
kinc_image_init3d(&image, bytes.GetPtr()->GetBase(), width, height, depth, (kinc_image_format_t)format);
kinc_g4_texture_init_from_image3d(&texture, &image);
if (readable) {
imageData = (uint8_t*)image.data;
}
kinc_image_destroy(&image);
imageType = KhaImageTypeTexture;
originalWidth = width;
originalHeight = height;
")
function initFromBytes3D(bytes: BytesData, width: Int, height: Int, depth: Int, format: Int): Void {}
public static function fromEncodedBytes(bytes: Bytes, format: String, doneCallback: Image->Void, errorCallback: String->Void,
readable: Bool = false): Void {
var image = new Image(readable);
var isFloat = format == "hdr" || format == "HDR";
image.myFormat = isFloat ? TextureFormat.RGBA128 : TextureFormat.RGBA32;
image.initFromEncodedBytes(bytes.getData(), format);
doneCallback(image);
}
@:functionCode("
size_t size = kinc_image_size_from_encoded_bytes(bytes.GetPtr()->GetBase(), bytes.GetPtr()->length, format.c_str());
void* data = malloc(size);
kinc_image_t image;
kinc_image_init_from_encoded_bytes(&image, data, bytes.GetPtr()->GetBase(), bytes.GetPtr()->length, format.c_str());
originalWidth = image.width;
originalHeight = image.height;
kinc_g4_texture_init_from_image(&texture, &image);
if (readable) {
imageData = (uint8_t*)image.data;
}
kinc_image_destroy(&image);
if (!readable) {
free(data);
}
imageType = KhaImageTypeTexture;
")
function initFromEncodedBytes(bytes: BytesData, format: String): Void {}
function new(readable: Bool, ?dispose = true) {
this.readable = readable;
nullify();
if (dispose) {
cpp.vm.Gc.setFinalizer(this, cpp.Function.fromStaticFunction(finalize));
}
}
@:functionCode("
imageType = KhaImageTypeNone;
originalWidth = 0;
originalHeight = 0;
imageData = NULL;
ownsImageData = false;
")
function nullify() {}
@:functionCode("
if (image->imageType != KhaImageTypeNone) {
image->unload();
}
")
@:void static function finalize(image: Image): Void {}
static function getRenderTargetFormat(format: TextureFormat): Int {
switch (format) {
case RGBA32: // Target32Bit
return 0;
case RGBA64: // Target64BitFloat
return 1;
case A32: // Target32BitRedFloat
return 2;
case RGBA128: // Target128BitFloat
return 3;
case DEPTH16: // Target16BitDepth
return 4;
case L8:
return 5; // Target8BitRed
case A16:
return 6; // Target16BitRedFloat
default:
return 0;
}
}
static function getDepthBufferBits(depthAndStencil: DepthStencilFormat): Int {
return switch (depthAndStencil) {
case NoDepthAndStencil: -1;
case DepthOnly: 24;
case DepthAutoStencilAuto: 24;
case Depth24Stencil8: 24;
case Depth32Stencil8: 32;
case Depth16: 16;
}
}
static function getStencilBufferBits(depthAndStencil: DepthStencilFormat): Int {
return switch (depthAndStencil) {
case NoDepthAndStencil: -1;
case DepthOnly: -1;
case DepthAutoStencilAuto: 8;
case Depth24Stencil8: 8;
case Depth32Stencil8: 8;
case Depth16: 0;
}
}
static function getTextureFormat(format: TextureFormat): Int {
switch (format) {
case RGBA32:
return 0;
case RGBA128:
return 3;
case RGBA64:
return 4;
case A32:
return 5;
case A16:
return 7;
default:
return 1; // Grey8
}
}
@:noCompletion
public static function _create2(width: Int, height: Int, format: TextureFormat, readable: Bool, renderTarget: Bool, depthStencil: DepthStencilFormat,
samplesPerPixel: Int): Image {
var image = new Image(readable);
image.myFormat = format;
if (renderTarget)
image.initRenderTarget(width, height, getRenderTargetFormat(format), getDepthBufferBits(depthStencil), getStencilBufferBits(depthStencil),
samplesPerPixel);
else
image.init(width, height, getTextureFormat(format));
return image;
}
@:noCompletion
public static function _create3(width: Int, height: Int, depth: Int, format: TextureFormat, readable: Bool, contextId: Int): Image {
var image = new Image(readable);
image.myFormat = format;
image.init3D(width, height, depth, getTextureFormat(format));
return image;
}
@:functionCode("
kinc_g4_render_target_init_with_multisampling(&renderTarget, width, height, (kinc_g4_render_target_format_t)format, depthBufferBits, stencilBufferBits, samplesPerPixel);
imageType = KhaImageTypeRenderTarget;
originalWidth = width;
originalHeight = height;
")
function initRenderTarget(width: Int, height: Int, format: Int, depthBufferBits: Int, stencilBufferBits: Int, samplesPerPixel: Int): Void {}
@:functionCode("
kinc_g4_texture_init(&texture, width, height, (kinc_image_format_t)format);
imageType = KhaImageTypeTexture;
originalWidth = width;
originalHeight = height;
")
function init(width: Int, height: Int, format: Int): Void {}
@:functionCode("
kinc_g4_texture_init3d(&texture, width, height, depth, (kinc_image_format_t)format);
imageType = KhaImageTypeTexture;
originalWidth = width;
originalHeight = height;
")
function init3D(width: Int, height: Int, depth: Int, format: Int): Void {}
@:functionCode("
texture = *kinc_video_current_image(&video->video);
imageType = KhaImageTypeTexture;
")
function initVideo(video: kha.kore.Video): Void {}
public static function createEmpty(readable: Bool, floatFormat: Bool): Image {
var image = new Image(readable);
image.myFormat = floatFormat ? TextureFormat.RGBA128 : TextureFormat.RGBA32;
return image;
}
/*public static function fromFile(filename: String, readable: Bool): Image {
var image = new Image(readable);
var isFloat = StringTools.endsWith(filename, ".hdr");
image.format = isFloat ? TextureFormat.RGBA128 : TextureFormat.RGBA32;
image.initFromFile(filename);
return image;
}
@:functionCode('texture = new Kore::Graphics4::Texture(filename.c_str(), readable);')
private function initFromFile(filename: String): Void {
}*/
public var g1(get, never): kha.graphics1.Graphics;
function get_g1(): kha.graphics1.Graphics {
if (graphics1 == null) {
graphics1 = new kha.graphics2.Graphics1(this);
}
return graphics1;
}
public var g2(get, never): kha.graphics2.Graphics;
function get_g2(): kha.graphics2.Graphics {
if (graphics2 == null) {
graphics2 = new kha.kore.graphics4.Graphics2(this);
}
return graphics2;
}
public var g4(get, never): kha.graphics4.Graphics;
function get_g4(): kha.graphics4.Graphics {
if (graphics4 == null) {
graphics4 = new kha.kore.graphics4.Graphics(this);
}
return graphics4;
}
public static var maxSize(get, never): Int;
static function get_maxSize(): Int {
return 4096;
}
public static var nonPow2Supported(get, never): Bool;
@:functionCode("return kinc_g4_supports_non_pow2_textures();")
static function get_nonPow2Supported(): Bool {
return false;
}
@:functionCode("return kinc_g4_render_targets_inverted_y();")
public static function renderTargetsInvertedY(): Bool {
return false;
}
public var width(get, never): Int;
@:functionCode("return originalWidth;")
function get_width(): Int {
return 0;
}
public var height(get, never): Int;
@:functionCode("return originalHeight;")
function get_height(): Int {
return 0;
}
public var depth(get, never): Int;
@:functionCode("if (imageType == KhaImageTypeTexture) return texture.tex_depth; else return 0;")
function get_depth(): Int {
return 0;
}
public var format(get, never): TextureFormat;
@:functionCode("if (imageType == KhaImageTypeTexture) return texture.format; else return 0;")
function get_format(): TextureFormat {
return TextureFormat.RGBA32;
}
public var realWidth(get, never): Int;
@:functionCode("if (imageType == KhaImageTypeTexture) return texture.tex_width; else if (imageType == KhaImageTypeRenderTarget) return renderTarget.width; else return 0;")
function get_realWidth(): Int {
return 0;
}
public var realHeight(get, never): Int;
@:functionCode("if (imageType == KhaImageTypeTexture) return texture.tex_height; else if (imageType == KhaImageTypeRenderTarget) return renderTarget.height; else return 0;")
function get_realHeight(): Int {
return 0;
}
public function isOpaque(x: Int, y: Int): Bool {
return isOpaqueInternal(x, y, getTextureFormat(myFormat));
}
@:functionCode("
kinc_image_t image;
kinc_image_init(&image, imageData, originalWidth, originalHeight, (kinc_image_format_t)format);
bool opaque = (kinc_image_at(&image, x, y) & 0xff) != 0;
kinc_image_destroy(&image);
return opaque;
")
function isOpaqueInternal(x: Int, y: Int, format: Int): Bool {
return true;
}
public inline function at(x: Int, y: Int): Color {
return Color.fromValue(atInternal(x, y, getTextureFormat(myFormat)));
}
@:functionCode("
kinc_image_t image;
kinc_image_init(&image, imageData, originalWidth, originalHeight, (kinc_image_format_t)format);
int value = kinc_image_at(&image, x, y);
kinc_image_destroy(&image);
return value;
")
function atInternal(x: Int, y: Int, format: Int): Int {
return 0;
}
@:keep
@:functionCode("
if (imageType == KhaImageTypeTexture) {
kinc_g4_texture_destroy(&texture);
}
else if (imageType == KhaImageTypeRenderTarget) {
kinc_g4_render_target_destroy(&renderTarget);
}
else if (imageType == KhaImageTypeTextureArray) {
kinc_g4_texture_array_destroy(&textureArray);
}
else {
assert(false);
}
if (ownsImageData) {
free(imageData);
}
imageData = NULL;
imageType = KhaImageTypeNone;
")
public function unload(): Void {}
var bytes: Bytes = null;
@:functionCode("
int size = kinc_image_format_sizeof(texture.format) * originalWidth * originalHeight;
this->bytes = ::haxe::io::Bytes_obj::alloc(size);
return this->bytes;
")
public function lock(level: Int = 0): Bytes {
return null;
}
@:functionCode("
uint8_t *b = bytes->b->Pointer();
uint8_t *tex = kinc_g4_texture_lock(&texture);
int size = kinc_image_format_sizeof(texture.format);
int stride = kinc_g4_texture_stride(&texture);
for (int y = 0; y < texture.tex_height; ++y) {
for (int x = 0; x < texture.tex_width; ++x) {
#ifdef KORE_DIRECT3D
if (texture.format == KINC_IMAGE_FORMAT_RGBA32) {
//RBGA->BGRA
tex[y * stride + x * size + 0] = b[(y * originalWidth + x) * size + 2];
tex[y * stride + x * size + 1] = b[(y * originalWidth + x) * size + 1];
tex[y * stride + x * size + 2] = b[(y * originalWidth + x) * size + 0];
tex[y * stride + x * size + 3] = b[(y * originalWidth + x) * size + 3];
}
else
#endif
{
for (int i = 0; i < size; ++i) {
tex[y * stride + x * size + i] = b[(y * originalWidth + x) * size + i];
}
}
}
}
kinc_g4_texture_unlock(&texture);
")
public function unlock(): Void {
bytes = null;
}
@:ifFeature("kha.Image.getPixelsInternal")
var pixels: Bytes = null;
@:ifFeature("kha.Image.getPixelsInternal")
var pixelsAllocated: Bool = false;
@:functionCode("
if (imageType != KhaImageTypeRenderTarget) return NULL;
if (!this->pixelsAllocated) {
int size = formatSize * renderTarget.width * renderTarget.height;
this->pixels = ::haxe::io::Bytes_obj::alloc(size);
this->pixelsAllocated = true;
}
uint8_t *b = this->pixels->b->Pointer();
kinc_g4_render_target_get_pixels(&renderTarget, b);
return this->pixels;
")
function getPixelsInternal(formatSize: Int): Bytes {
return null;
}
public function getPixels(): Bytes {
return getPixelsInternal(formatByteSize(myFormat));
}
static function formatByteSize(format: TextureFormat): Int {
return switch (format) {
case RGBA32: 4;
case L8: 1;
case RGBA128: 16;
case DEPTH16: 2;
case RGBA64: 8;
case A32: 4;
case A16: 2;
default: 4;
}
}
public function generateMipmaps(levels: Int): Void {
untyped __cpp__("if (imageType == KhaImageTypeTexture) kinc_g4_texture_generate_mipmaps(&texture, levels); else if (imageType == KhaImageTypeRenderTarget) kinc_g4_render_target_generate_mipmaps(&renderTarget, levels)");
}
public function setMipmaps(mipmaps: Array<Image>): Void {
for (i in 0...mipmaps.length) {
var khaImage = mipmaps[i];
var level = i + 1;
var format = getTextureFormat(this.format);
untyped __cpp__("
kinc_image_t image;
kinc_image_init(&image, {0}->imageData, {0}->originalWidth, {0}->originalHeight, (kinc_image_format_t){2});
kinc_g4_texture_set_mipmap(&texture, &image, {1});
kinc_image_destroy(&image);
", khaImage, level, format);
}
}
public function setDepthStencilFrom(image: Image): Void {
untyped __cpp__("kinc_g4_render_target_set_depth_stencil_from(&renderTarget, &image->renderTarget)");
}
@:functionCode("if (imageType == KhaImageTypeTexture) kinc_g4_texture_clear(&texture, x, y, z, width, height, depth, color);")
public function clear(x: Int, y: Int, z: Int, width: Int, height: Int, depth: Int, color: Color): Void {}
public var stride(get, never): Int;
@:functionCode("if (imageType == KhaImageTypeTexture) return kinc_g4_texture_stride(&texture); else if (imageType == KhaImageTypeRenderTarget) return formatByteSize(myFormat) * renderTarget.width; else return 0;")
function get_stride(): Int {
return 0;
}
}

View File

@ -0,0 +1,220 @@
package kha;
import kha.arrays.Float32Array;
import haxe.io.Bytes;
import haxe.io.BytesData;
@:headerCode("
#include <kinc/input/keyboard.h>
#include <kinc/system.h>
#include <kinc/video.h>
#include <khalib/loader.h>
")
class BlobCallback {
public var success: Blob->Void;
public var error: AssetError->Void;
public function new(success: Blob->Void, error: AssetError->Void) {
this.success = success;
this.error = error;
}
}
class ImageCallback {
public var success: Image->Void;
public var error: AssetError->Void;
public function new(success: Image->Void, error: AssetError->Void) {
this.success = success;
this.error = error;
}
}
class SoundCallback {
public var success: Sound->Void;
public var error: AssetError->Void;
public function new(success: Sound->Void, error: AssetError->Void) {
this.success = success;
this.error = error;
}
}
class LoaderImpl {
static var blobCallbacks = new Map<haxe.Int64, BlobCallback>();
static var imageCallbacks = new Map<haxe.Int64, ImageCallback>();
static var soundCallbacks = new Map<haxe.Int64, SoundCallback>();
public static function loadSoundFromDescription(desc: Dynamic, done: kha.Sound->Void, failed: AssetError->Void) {
soundCallbacks[loadSound(desc.files[0])] = new SoundCallback(done, failed);
}
@:functionCode("return kha_loader_load_sound(filename);")
static function loadSound(filename: String): haxe.Int64 {
return 0;
}
public static function getSoundFormats(): Array<String> {
return ["wav", "ogg"];
}
public static function loadImageFromDescription(desc: Dynamic, done: kha.Image->Void, failed: AssetError->Void) {
var readable = Reflect.hasField(desc, "readable") ? desc.readable : false;
// done(kha.Image.fromFile(desc.files[0], readable));
imageCallbacks[loadImage(desc.files[0], readable)] = new ImageCallback(done, failed);
}
@:functionCode("return kha_loader_load_image(filename, readable);")
static function loadImage(filename: String, readable: Bool): haxe.Int64 {
return 0;
}
public static function getImageFormats(): Array<String> {
return ["png", "jpg", "hdr"];
}
public static function loadBlobFromDescription(desc: Dynamic, done: Blob->Void, failed: AssetError->Void) {
blobCallbacks[loadBlob(desc.files[0])] = new BlobCallback(done, failed);
}
@:functionCode("return kha_loader_load_blob(filename);")
static function loadBlob(filename: String): haxe.Int64 {
return 0;
}
public static function loadFontFromDescription(desc: Dynamic, done: Font->Void, failed: AssetError->Void): Void {
loadBlobFromDescription(desc, function(blob: Blob) {
done(new Kravur(blob));
}, failed);
}
public static function loadVideoFromDescription(desc: Dynamic, done: Video->Void, failed: AssetError->Void) {
done(new kha.kore.Video(desc.files[0]));
}
@:functionCode("return ::String(kinc_video_formats()[0]);")
static function videoFormat(): String {
return "";
}
public static function getVideoFormats(): Array<String> {
return [videoFormat()];
}
@:functionCode("kinc_keyboard_show();")
public static function showKeyboard(): Void {}
@:functionCode("kinc_keyboard_hide();")
public static function hideKeyboard(): Void {}
@:functionCode("kinc_load_url(url);")
public static function loadURL(url: String): Void {}
@:keep static function blobLoaded(index: haxe.Int64, bytes: BytesData) {
blobCallbacks[index].success(new Blob(Bytes.ofData(bytes)));
}
@:keep static function blobErrored(index: haxe.Int64, filename: String) {
blobCallbacks[index].error({url: filename});
}
@:keep static function soundLoadedCompressed(index: haxe.Int64, bytes: BytesData) {
var sound = new Sound();
sound.compressedData = Bytes.ofData(bytes);
sound.uncompressedData = null;
sound.channels = 0;
sound.sampleRate = 0;
sound.length = 0;
soundCallbacks[index].success(sound);
}
@:keep static function soundLoadedUncompressed(index: haxe.Int64, samples: Float32Array, channels: Int, sampleRate: Int, length: Float) {
var sound = new Sound();
sound.compressedData = null;
sound.uncompressedData = samples;
sound.channels = channels;
sound.sampleRate = sampleRate;
sound.length = length;
soundCallbacks[index].success(sound);
}
@:keep static function soundErrored(index: haxe.Int64, filename: String) {
soundCallbacks[index].error({url: filename});
}
@:keep static function createFloat32Array() {
return new Float32Array(0);
}
@:keep static function createEmptyImage(readable: Bool, floatFormat: Bool) {
return Image.createEmpty(readable, floatFormat);
}
@:keep static function imageLoaded(index: haxe.Int64, image: Image) {
imageCallbacks[index].success(image);
}
@:keep static function imageErrored(index: haxe.Int64, filename: String) {
imageCallbacks[index].error({url: filename});
}
@:functionCode("
kha_file_reference_t file = kha_loader_get_file();
while (file.index != 0) {
switch (file.type) {
case KHA_FILE_TYPE_BLOB:
if (file.error) {
blobErrored(file.index, file.name);
}
else {
Array<unsigned char> buffer = Array_obj<unsigned char>::fromData(file.data.blob.bytes, file.data.blob.size);
blobLoaded(file.index, buffer);
kha_loader_cleanup_blob(file.data.blob);
}
break;
case KHA_FILE_TYPE_IMAGE:
if (file.error) {
imageErrored(file.index, file.name);
}
else {
::kha::Image image = createEmptyImage(file.data.image.readable, file.data.image.image.format == KINC_IMAGE_FORMAT_RGBA128);
kinc_image_t kincImage;
kinc_image_init(&kincImage, file.data.image.image.data, file.data.image.image.width, file.data.image.image.height, (kinc_image_format_t)file.data.image.image.format);
kinc_g4_texture_init_from_image(&image->texture, &kincImage);
if (file.data.image.readable) {
image->imageData = (uint8_t*)kincImage.data;
}
else {
free(file.data.image.image.data);
}
kinc_image_destroy(&kincImage);
image->imageType = KhaImageTypeTexture;
image->originalWidth = file.data.image.image.width;
image->originalHeight = file.data.image.image.height;
imageLoaded(file.index, image);
}
break;
case KHA_FILE_TYPE_SOUND:
if (file.error) {
soundErrored(file.index, file.name);
}
else if (file.data.sound.samples != NULL) {
::kha::arrays::ByteArrayPrivate buffer = createFloat32Array();
buffer->self.data = (uint8_t*)file.data.sound.samples;
buffer->byteArrayLength = file.data.sound.size * 4;
buffer->byteArrayOffset = 0;
soundLoadedUncompressed(file.index, buffer, file.data.sound.channels, file.data.sound.sample_rate, file.data.sound.length);
}
else {
Array<unsigned char> buffer = Array_obj<unsigned char>::fromData(file.data.sound.compressed_samples, file.data.sound.size);
soundLoadedCompressed(file.index, buffer);
kha_loader_cleanup_sound(file.data.sound);
}
break;
}
file = kha_loader_get_file();
}
")
public static function tick(): Void {}
}

View File

@ -0,0 +1,65 @@
package kha;
import haxe.io.Bytes;
using StringTools;
@:headerCode("
#include <kinc/io/filereader.h>
#include <kinc/io/filewriter.h>
")
@:ifFeature("kha.Storage.*")
class KoreStorageFile extends StorageFile {
var name: String;
public function new(name: String) {
this.name = name;
}
@:functionCode("
kinc_file_reader_t file;
if (!kinc_file_reader_open(&file, name, KINC_FILE_TYPE_SAVE)) return null();
::kha::internal::BytesBlob blob = createBlob(kinc_file_reader_size(&file));
kinc_file_reader_read(&file, blob->bytes->b->Pointer(), kinc_file_reader_size(&file));
kinc_file_reader_close(&file);
return blob;
")
override public function read(): Blob {
return null;
}
@:functionCode("
kinc_file_writer_t file;
if (!kinc_file_writer_open(&file, name)) return;
kinc_file_writer_write(&file, data->bytes->b->Pointer(), data->get_length());
kinc_file_writer_close(&file);
")
function writeInternal(data: Blob): Void {}
override public function write(data: Blob): Void {
if (data != null) {
writeInternal(data);
}
}
@:keep
static function createBlob(size: Int): Blob {
return Blob.alloc(size);
}
static function unused(): Void {
Bytes.alloc(0);
}
}
class Storage {
public static function namedFile(name: String): StorageFile {
name = name.replace("\\", ".");
name = name.replace("/", ".");
return new KoreStorageFile(name);
}
public static function defaultFile(): StorageFile {
return namedFile("default.kha");
}
}

View File

@ -0,0 +1,519 @@
package kha;
import kha.input.Gamepad;
import kha.input.KeyCode;
import kha.input.Keyboard;
import kha.input.Mouse;
import kha.input.Pen;
import kha.input.Sensor;
import kha.input.SensorType;
import kha.input.Surface;
import kha.System;
import kha.graphics4.TextureFormat;
import kha.graphics4.DepthStencilFormat;
#if ANDROID
#if VR_CARDBOARD
import kha.kore.vr.CardboardVrInterface;
#end
#if !VR_CARDBOARD
import kha.kore.vr.VrInterface;
#end
#end
#if !ANDROID
#if VR_RIFT
import kha.kore.vr.VrInterfaceRift;
#end
#if !VR_RIFT
import kha.vr.VrInterfaceEmulated;
#end
#end
@:headerCode("
#include <kinc/system.h>
#include <kinc/input/gamepad.h>
#include <kinc/input/mouse.h>
#include <kinc/input/pen.h>
#include <kinc/display.h>
#include <kinc/window.h>
kinc_window_options_t convertWindowOptions(::kha::WindowOptions win);
kinc_framebuffer_options_t convertFramebufferOptions(::kha::FramebufferOptions frame);
void init_kinc(const char *name, int width, int height, kinc_window_options_t *win, kinc_framebuffer_options_t *frame);
void post_kinc_init();
void kha_kinc_init_audio(void);
void run_kinc();
const char *getGamepadId(int index);
const char *getGamepadVendor(int index);
void setGamepadRumble(int index, float left, float right);
")
@:keep
class SystemImpl {
public static var needs3d: Bool = false;
public static function getMouse(num: Int): Mouse {
if (num != 0)
return null;
return mouse;
}
public static function getPen(num: Int): Pen {
if (num != 0)
return null;
return pen;
}
public static function getKeyboard(num: Int): Keyboard {
if (num != 0)
return null;
return keyboard;
}
@:functionCode("return kinc_time();")
public static function getTime(): Float {
return 0;
}
public static function windowWidth(windowId: Int): Int {
return untyped __cpp__("kinc_window_width(windowId)");
}
public static function windowHeight(windowId: Int): Int {
return untyped __cpp__("kinc_window_height(windowId)");
}
public static function screenDpi(): Int {
return untyped __cpp__("kinc_display_current_mode(kinc_primary_display()).pixels_per_inch");
}
public static function getVsync(): Bool {
return true;
}
public static function getRefreshRate(): Int {
return 60;
}
public static function getScreenRotation(): ScreenRotation {
return ScreenRotation.RotationNone;
}
@:functionCode("return ::String(kinc_system_id());")
public static function getSystemId(): String {
return "";
}
public static function vibrate(ms: Int): Void {
untyped __cpp__("kinc_vibrate(ms)");
}
@:functionCode("return ::String(kinc_language());")
public static function getLanguage(): String {
return "en";
}
public static function requestShutdown(): Bool {
untyped __cpp__("kinc_stop()");
return true;
}
static var framebuffers: Array<Framebuffer> = new Array();
static var keyboard: Keyboard;
static var mouse: kha.input.Mouse;
static var pen: kha.input.Pen;
static var gamepads: Array<Gamepad>;
static var surface: Surface;
static var mouseLockListeners: Array<Void->Void>;
public static function init(options: SystemOptions, callback: Window->Void): Void {
initKinc(options.title, options.width, options.height, options.window, options.framebuffer);
Window._init();
kha.Worker._mainThread = sys.thread.Thread.current();
untyped __cpp__("post_kinc_init()");
Shaders.init();
#if (!VR_GEAR_VR && !VR_RIFT)
var g4 = new kha.kore.graphics4.Graphics();
g4.window = 0;
// var g5 = new kha.kore.graphics5.Graphics();
var framebuffer = new Framebuffer(0, null, null, g4 /*, g5*/);
framebuffer.init(new kha.graphics2.Graphics1(framebuffer), new kha.kore.graphics4.Graphics2(framebuffer), g4 /*, g5*/);
framebuffers.push(framebuffer);
#end
postInit(callback);
}
static function onWindowCreated(index: Int) {
var g4 = new kha.kore.graphics4.Graphics();
g4.window = index;
var framebuffer = new Framebuffer(index, null, null, g4);
framebuffer.init(new kha.graphics2.Graphics1(framebuffer), new kha.kore.graphics4.Graphics2(framebuffer), g4);
framebuffers.push(framebuffer);
}
static function postInit(callback: Window->Void) {
mouseLockListeners = new Array();
haxe.Timer.stamp();
Sensor.get(SensorType.Accelerometer); // force compilation
keyboard = new kha.kore.Keyboard();
mouse = new kha.input.MouseImpl();
pen = new kha.input.Pen();
gamepads = new Array<Gamepad>();
for (i in 0...4) {
gamepads[i] = new Gamepad(i);
gamepads[i].connected = checkGamepadConnected(i);
}
surface = new Surface();
kha.audio2.Audio._init();
kha.audio1.Audio._init();
untyped __cpp__("kha_kinc_init_audio()");
Scheduler.init();
loadFinished();
callback(Window.get(0));
untyped __cpp__("run_kinc()");
}
static function loadFinished() {
Scheduler.start();
/*
#if ANDROID
#if VR_GEAR_VR
kha.vr.VrInterface.instance = new kha.kore.vr.VrInterface();
#end
#if !VR_GEAR_VR
kha.vr.VrInterface.instance = new CardboardVrInterface();
#end
#end
#if !ANDROID
#if VR_RIFT
kha.vr.VrInterface.instance = new VrInterfaceRift();
#end
#if !VR_RIFT
kha.vr.VrInterface.instance = new kha.vr.VrInterfaceEmulated();
#end
#end
*/
// (DK) moved
/*Shaders.init();
#if (!VR_GEAR_VR && !VR_RIFT)
var g4 = new kha.kore.graphics4.Graphics();
framebuffers.push(new Framebuffer(null, null, g4));
framebuffers[0].init(new kha.graphics2.Graphics1(framebuffers[0]), new kha.kore.graphics4.Graphics2(framebuffers[0]), g4);
g4 = new kha.kore.graphics4.Graphics();
framebuffers.push(new Framebuffer(null, null, g4));
framebuffers[1].init(new kha.graphics2.Graphics1(framebuffers[1]), new kha.kore.graphics4.Graphics2(framebuffers[1]), g4);
#end
*/}
public static function lockMouse(windowId: Int = 0): Void {
if (!isMouseLocked()) {
untyped __cpp__("kinc_mouse_lock(windowId);");
for (listener in mouseLockListeners) {
listener();
}
}
}
public static function unlockMouse(windowId: Int = 0): Void {
if (isMouseLocked()) {
untyped __cpp__("kinc_mouse_unlock();");
for (listener in mouseLockListeners) {
listener();
}
}
}
public static function canLockMouse(windowId: Int = 0): Bool {
return untyped __cpp__("kinc_mouse_can_lock()");
}
public static function isMouseLocked(windowId: Int = 0): Bool {
return untyped __cpp__("kinc_mouse_is_locked()");
}
public static function notifyOfMouseLockChange(func: Void->Void, error: Void->Void, windowId: Int = 0): Void {
if (canLockMouse(windowId) && func != null) {
mouseLockListeners.push(func);
}
}
public static function removeFromMouseLockChange(func: Void->Void, error: Void->Void, windowId: Int = 0): Void {
if (canLockMouse(windowId) && func != null) {
mouseLockListeners.remove(func);
}
}
public static function hideSystemCursor(): Void {
untyped __cpp__("kinc_mouse_hide();");
}
public static function showSystemCursor(): Void {
untyped __cpp__("kinc_mouse_show();");
}
public static function setSystemCursor(cursor: Int): Void {
untyped __cpp__("kinc_mouse_set_cursor(cursor)");
}
public static function frame() {
/*
#if !ANDROID
#if !VR_RIFT
if (framebuffer == null) return;
var vrInterface: VrInterfaceEmulated = cast(VrInterface.instance, VrInterfaceEmulated);
vrInterface.framebuffer = framebuffer;
#end
#else
#if VR_CARDBOARD
var vrInterface: CardboardVrInterface = cast(VrInterface.instance, CardboardVrInterface);
vrInterface.framebuffer = framebuffer;
#end
#end
*/
LoaderImpl.tick();
Scheduler.executeFrame();
System.render(framebuffers);
if (kha.kore.graphics4.Graphics.lastWindow != -1) {
var win = kha.kore.graphics4.Graphics.lastWindow;
untyped __cpp__("kinc_g4_end({0})", win);
}
else {
untyped __cpp__("kinc_g4_begin(0)");
untyped __cpp__("kinc_g4_clear(KINC_G4_CLEAR_COLOR | KINC_G4_CLEAR_DEPTH | KINC_G4_CLEAR_STENCIL, 0, 0.0f, 0)");
untyped __cpp__("kinc_g4_end(0)");
}
kha.kore.graphics4.Graphics.lastWindow = -1;
for (i in 0...4) {
if (gamepads[i].connected && !checkGamepadConnected(i)) {
Gamepad.sendDisconnectEvent(i);
}
else if (!gamepads[i].connected && checkGamepadConnected(i)) {
Gamepad.sendConnectEvent(i);
}
}
}
@:functionCode("return kinc_gamepad_connected(i);")
static function checkGamepadConnected(i: Int): Bool {
return true;
}
public static function keyDown(code: KeyCode): Void {
keyboard.sendDownEvent(code);
}
public static function keyUp(code: KeyCode): Void {
keyboard.sendUpEvent(code);
}
public static function keyPress(char: Int): Void {
keyboard.sendPressEvent(String.fromCharCode(char));
}
public static var mouseX: Int;
public static var mouseY: Int;
public static function mouseDown(windowId: Int, button: Int, x: Int, y: Int): Void {
mouseX = x;
mouseY = y;
mouse.sendDownEvent(windowId, button, x, y);
}
public static function mouseUp(windowId: Int, button: Int, x: Int, y: Int): Void {
mouseX = x;
mouseY = y;
mouse.sendUpEvent(windowId, button, x, y);
}
public static function mouseMove(windowId: Int, x: Int, y: Int, movementX: Int, movementY: Int): Void {
// var movementX = x - mouseX;
// var movementY = y - mouseY;
mouseX = x;
mouseY = y;
mouse.sendMoveEvent(windowId, x, y, movementX, movementY);
}
public static function mouseWheel(windowId: Int, delta: Int): Void {
mouse.sendWheelEvent(windowId, delta);
}
public static function mouseLeave(windowId: Int): Void {
mouse.sendLeaveEvent(windowId);
}
public static function penDown(windowId: Int, x: Int, y: Int, pressure: Float): Void {
pen.sendDownEvent(windowId, x, y, pressure);
}
public static function penUp(windowId: Int, x: Int, y: Int, pressure: Float): Void {
pen.sendUpEvent(windowId, x, y, pressure);
}
public static function penMove(windowId: Int, x: Int, y: Int, pressure: Float): Void {
pen.sendMoveEvent(windowId, x, y, pressure);
}
public static function penEraserDown(windowId: Int, x: Int, y: Int, pressure: Float): Void {
pen.sendEraserDownEvent(windowId, x, y, pressure);
}
public static function penEraserUp(windowId: Int, x: Int, y: Int, pressure: Float): Void {
pen.sendEraserUpEvent(windowId, x, y, pressure);
}
public static function penEraserMove(windowId: Int, x: Int, y: Int, pressure: Float): Void {
pen.sendEraserMoveEvent(windowId, x, y, pressure);
}
public static function gamepadAxis(gamepad: Int, axis: Int, value: Float): Void {
gamepads[gamepad].sendAxisEvent(axis, value);
}
public static function gamepadButton(gamepad: Int, button: Int, value: Float): Void {
gamepads[gamepad].sendButtonEvent(button, value);
}
public static function touchStart(index: Int, x: Int, y: Int): Void {
surface.sendTouchStartEvent(index, x, y);
}
public static function touchEnd(index: Int, x: Int, y: Int): Void {
surface.sendTouchEndEvent(index, x, y);
}
public static function touchMove(index: Int, x: Int, y: Int): Void {
surface.sendMoveEvent(index, x, y);
}
public static function foreground(): Void {
System.foreground();
}
public static function resume(): Void {
System.resume();
}
public static function pause(): Void {
System.pause();
}
public static function background(): Void {
System.background();
}
public static function shutdown(): Void {
System.shutdown();
}
public static function dropFiles(filePath: String): Void {
System.dropFiles(filePath);
}
public static function copy(): String {
if (System.copyListener != null) {
return System.copyListener();
}
else {
return null;
}
}
public static function cut(): String {
if (System.cutListener != null) {
return System.cutListener();
}
else {
return null;
}
}
public static function paste(data: String): Void {
if (System.pasteListener != null) {
System.pasteListener(data);
}
}
@:functionCode("kinc_copy_to_clipboard(text.c_str());")
public static function copyToClipboard(text: String) {}
@:functionCode("kinc_login();")
public static function login(): Void {}
@:functionCode("return kinc_waiting_for_login();")
public static function waitingForLogin(): Bool {
return false;
}
@:functionCode("kinc_disallow_user_change();")
public static function disallowUserChange(): Void {}
@:functionCode("kinc_allow_user_change();")
public static function allowUserChange(): Void {}
public static function loginevent(): Void {
if (System.loginListener != null) {
System.loginListener();
}
}
public static function logoutevent(): Void {
if (System.logoutListener != null) {
System.logoutListener();
}
}
@:functionCode("
kinc_window_options_t window = convertWindowOptions(win);
kinc_framebuffer_options_t framebuffer = convertFramebufferOptions(frame);
init_kinc(name, width, height, &window, &framebuffer);
")
static function initKinc(name: String, width: Int, height: Int, win: WindowOptions, frame: FramebufferOptions): Void {}
public static function setKeepScreenOn(on: Bool): Void {
untyped __cpp__("kinc_set_keep_screen_on(on)");
}
public static function loadUrl(url: String): Void {
untyped __cpp__("kinc_load_url(url)");
}
@:functionCode("return ::String(::getGamepadId(index));")
public static function getGamepadId(index: Int): String {
return "unknown";
}
@:functionCode("return ::String(::getGamepadVendor(index));")
public static function getGamepadVendor(index: Int): String {
return "unknown";
}
public static function setGamepadRumble(index: Int, leftAmount: Float, rightAmount: Float): Void {
untyped __cpp__("::setGamepadRumble(index, leftAmount, rightAmount)");
}
public static function safeZone(): Float {
return untyped __cpp__("kinc_safe_zone()");
}
public static function automaticSafeZone(): Bool {
return untyped __cpp__("kinc_automatic_safe_zone()");
}
public static function setSafeZone(value: Float): Void {
untyped __cpp__("kinc_set_safe_zone(value)");
}
public static function unlockAchievement(id: Int): Void {
untyped __cpp__("kinc_unlock_achievement(id)");
}
}

View File

@ -0,0 +1,251 @@
package kha;
@:headerCode("
#include <kinc/window.h>
")
@:cppFileCode("
namespace {
char windowTitles[10][256];
int titleIndex = 0;
void resizeCallback(int width, int height, void* data) {
::kha::Window_obj::callResizeCallbacks(*((int*)&data), width, height);
}
void ppiCallback(int ppi, void* data) {
::kha::Window_obj::callPpiCallbacks(*((int*)&data), ppi);
}
}
kinc_window_options_t convertWindowOptions(::kha::WindowOptions win) {
kinc_window_options_t window;
strcpy(windowTitles[titleIndex], win->title.c_str());
window.title = windowTitles[titleIndex];
++titleIndex;
window.x = win->x;
window.y = win->y;
window.width = win->width;
window.height = win->height;
window.display_index = win->display;
window.visible = win->visible;
window.window_features = win->windowFeatures;
window.mode = (kinc_window_mode_t)win->mode;
return window;
}
kinc_framebuffer_options_t convertFramebufferOptions(::kha::FramebufferOptions frame) {
kinc_framebuffer_options_t framebuffer;
framebuffer.frequency = frame->frequency;
framebuffer.vertical_sync = frame->verticalSync;
framebuffer.color_bits = frame->colorBufferBits;
framebuffer.depth_bits = frame->depthBufferBits;
framebuffer.stencil_bits = frame->stencilBufferBits;
framebuffer.samples_per_pixel = frame->samplesPerPixel;
return framebuffer;
}
")
class Window {
static var windows: Array<Window> = [];
static var resizeCallbacks: Array<Array<Int->Int->Void>> = [];
static var ppiCallbacks: Array<Array<Int->Void>> = [];
var num: Int;
var visibility: Bool;
var windowTitle: String;
@:noCompletion
@:noDoc
public function new(num: Int, win: WindowOptions) {
this.num = num;
visibility = win != null && win.visible;
windowTitle = win == null ? "Kha" : (win.title == null ? "Kha" : win.title);
resizeCallbacks[num] = [];
ppiCallbacks[num] = [];
}
@:noCompletion
@:noDoc
@:keep
static function unused(): Void {
Display.primary.x;
}
@:noCompletion
@:noDoc
public static function _init(win: WindowOptions = null, frame: FramebufferOptions = null): Void {
var window = new Window(windows.length, win);
windows.push(window);
}
@:access(kha.SystemImpl)
public static function create(win: WindowOptions = null, frame: FramebufferOptions = null): Window {
koreCreate(win == null ? {} : win, frame == null ? {} : frame);
var window = new Window(windows.length, win);
var index = windows.push(window) - 1;
kha.SystemImpl.onWindowCreated(index);
return window;
}
@:functionCode("
kinc_window_options_t window = convertWindowOptions(win);
kinc_framebuffer_options_t framebuffer = convertFramebufferOptions(frame);
kinc_window_create(&window, &framebuffer);
")
static function koreCreate(win: WindowOptions, frame: FramebufferOptions) {}
public static function destroy(window: Window): Void {
koreDestroy(window.num);
windows.remove(window);
}
@:functionCode("kinc_window_destroy(num);")
static function koreDestroy(num: Int) {}
public static function get(index: Int): Window {
return windows[index];
}
public static var all(get, never): Array<Window>;
static function get_all(): Array<Window> {
return windows;
}
@:functionCode("kinc_window_resize(num, width, height);")
public function resize(width: Int, height: Int): Void {}
@:functionCode("kinc_window_move(num, x, y);")
public function move(x: Int, y: Int): Void {}
@:functionCode("kinc_window_change_features(num, features);")
public function changeWindowFeatures(features: Int): Void {}
@:functionCode("
kinc_framebuffer_options_t framebuffer = convertFramebufferOptions(frame);
kinc_window_change_framebuffer(num, &framebuffer);
")
public function changeFramebuffer(frame: FramebufferOptions): Void {}
public var x(get, set): Int;
@:functionCode("return kinc_window_x(num);")
function get_x(): Int {
return 0;
}
@:functionCode("int y = kinc_window_y(num); kinc_window_move(num, value, y);")
function set_x(value: Int): Int {
return 0;
}
public var y(get, set): Int;
@:functionCode("return kinc_window_y(num);")
function get_y(): Int {
return 0;
}
@:functionCode("int x = kinc_window_x(num); kinc_window_move(num, x, value);")
function set_y(value: Int): Int {
return 0;
}
public var width(get, set): Int;
@:functionCode("return kinc_window_width(num);")
function get_width(): Int {
return 800;
}
@:functionCode("int height = kinc_window_height(num); kinc_window_resize(num, value, height);")
function set_width(value: Int): Int {
return 800;
}
public var height(get, set): Int;
@:functionCode("return kinc_window_height(num);")
function get_height(): Int {
return 600;
}
@:functionCode("int width = kinc_window_width(num); kinc_window_move(num, width, value);")
function set_height(value: Int): Int {
return 600;
}
public var mode(get, set): WindowMode;
function get_mode(): WindowMode {
return cast getKincMode();
}
@:functionCode("return kinc_window_get_mode(num);")
function getKincMode(): Int {
return 0;
}
@:functionCode("kinc_window_change_mode(num, (kinc_window_mode_t)mode); return mode;")
function set_mode(mode: WindowMode): WindowMode {
return mode;
}
public var visible(get, set): Bool;
function get_visible(): Bool {
return visibility;
}
@:functionCode("if (value) kinc_window_show(num); else kinc_window_hide(num);")
function set_visible(value: Bool): Bool {
visibility = value;
return value;
}
public var title(get, set): String;
function get_title(): String {
return windowTitle;
}
@:functionCode("kinc_window_set_title(num, value.c_str());")
function set_title(value: String): String {
windowTitle = value;
return windowTitle;
}
@:functionCode("kinc_window_set_resize_callback(num, resizeCallback, (void*)this->num);")
public function notifyOnResize(callback: Int->Int->Void): Void {
resizeCallbacks[num].push(callback);
}
@:noCompletion
@:noDoc
@:keep
public static function callResizeCallbacks(num: Int, width: Int, height: Int) {
for (callback in resizeCallbacks[num]) {
callback(width, height);
}
}
@:functionCode("kinc_window_set_ppi_changed_callback(num, ppiCallback, (void*)this->num);")
public function notifyOnPpiChange(callback: Int->Void): Void {
ppiCallbacks[num].push(callback);
}
@:noCompletion
@:noDoc
@:keep
public static function callPpiCallbacks(num: Int, ppi: Int) {
for (callback in ppiCallbacks[num]) {
callback(ppi);
}
}
public var vSynced(get, never): Bool;
@:functionCode("return kinc_window_vsynced(num);")
function get_vSynced(): Bool {
return true;
}
}

View File

@ -0,0 +1,366 @@
package kha.arrays;
import cpp.vm.Gc;
class ByteArrayPrivate {
public var self: ByteBuffer;
public var byteArrayOffset: Int;
public var byteArrayLength: Int;
public inline function new(offset: Int, length: Int) {
this.byteArrayOffset = offset;
this.byteArrayLength = length;
Gc.setFinalizer(this, cpp.Function.fromStaticFunction(finalize));
}
@:void static function finalize(arr: ByteArrayPrivate): Void {
arr.self.subRef();
}
}
abstract ByteArray(ByteArrayPrivate) {
public var buffer(get, never): ByteBuffer;
inline function get_buffer(): ByteBuffer {
return this.self;
}
public var byteLength(get, never): Int;
inline function get_byteLength(): Int {
return this.byteArrayLength;
}
public var byteOffset(get, never): Int;
inline function get_byteOffset(): Int {
return this.byteArrayOffset;
}
public inline function new(buffer: ByteBuffer, byteOffset: Int, byteLength: Int): Void {
this = new ByteArrayPrivate(byteOffset, byteLength);
this.self = buffer;
this.self.addRef();
}
public static inline function make(byteLength: Int): ByteArray {
var buffer = ByteBuffer.create();
if (byteLength > 0) {
buffer.alloc(byteLength);
}
return new ByteArray(buffer, 0, byteLength);
}
public inline function getInt8(byteOffset: Int): Int {
return untyped __cpp__("*(int8_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
}
public inline function getUint8(byteOffset: Int): Int {
return untyped __cpp__("*(uint8_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
}
public inline function getInt16(byteOffset: Int): Int {
return untyped __cpp__("*(int16_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
}
public inline function getUint16(byteOffset: Int): Int {
return untyped __cpp__("*(uint16_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
}
public inline function getInt32(byteOffset: Int): Int {
return untyped __cpp__("*(int32_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
}
public inline function getUint32(byteOffset: Int): Int {
return untyped __cpp__("*(uint32_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
}
public inline function getFloat32(byteOffset: Int): FastFloat {
return untyped __cpp__("*(float *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
}
public inline function getFloat64(byteOffset: Int): Float {
return untyped __cpp__("*(double *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
}
public inline function setInt8(byteOffset: Int, value: Int): Void {
untyped __cpp__("*((int8_t *)&{0}.data[{1} + {2}]) = {3}", this.self, this.byteArrayOffset, byteOffset, value);
}
public inline function setUint8(byteOffset: Int, value: Int): Void {
untyped __cpp__("*((uint8_t *)&{0}.data[{1} + {2}]) = {3}", this.self, this.byteArrayOffset, byteOffset, value);
}
public inline function setInt16(byteOffset: Int, value: Int): Void {
untyped __cpp__("*((int16_t *)&{0}.data[{1} + {2}]) = {3}", this.self, this.byteArrayOffset, byteOffset, value);
}
public inline function setUint16(byteOffset: Int, value: Int): Void {
untyped __cpp__("*((uint16_t *)&{0}.data[{1} + {2}]) = {3}", this.self, this.byteArrayOffset, byteOffset, value);
}
public inline function setInt32(byteOffset: Int, value: Int): Void {
untyped __cpp__("*((int32_t *)&{0}.data[{1} + {2}]) = {3}", this.self, this.byteArrayOffset, byteOffset, value);
}
public inline function setUint32(byteOffset: Int, value: Int): Void {
untyped __cpp__("*((uint32_t *)&{0}.data[{1} + {2}]) = {3}", this.self, this.byteArrayOffset, byteOffset, value);
}
public inline function setFloat32(byteOffset: Int, value: FastFloat): Void {
untyped __cpp__("*((float *)&{0}.data[{1} + {2}]) = {3}", this.self, this.byteArrayOffset, byteOffset, value);
}
public inline function setFloat64(byteOffset: Int, value: Float): Void {
untyped __cpp__("*((double *)&{0}.data[{1} + {2}]) = {3}", this.self, this.byteArrayOffset, byteOffset, value);
}
public inline function getInt16LE(byteOffset: Int): Int {
#if !sys_bigendian
return untyped __cpp__("*(int16_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
return untyped __cpp__("({0}.data[{1} + {2} + 0] << 0) | ({0}.data[{1} + {2} + 1] << 8)", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function getUint16LE(byteOffset: Int): Int {
#if !sys_bigendian
return untyped __cpp__("*(uint16_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
return untyped __cpp__("({0}.data[{1} + {2} + 0] << 0) | ({0}.data[{1} + {2} + 1] << 8)", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function getInt32LE(byteOffset: Int): Int {
#if !sys_bigendian
return untyped __cpp__("*(int32_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
return
untyped __cpp__("({0}.data[{1} + {2} + 0] << 0) | ({0}.data[{1} + {2} + 1] << 8) | ({0}.data[{1} + {2} + 2] << 16) | ({0}.data[{1} + {2} + 3] << 24)",
this.self,
this.byteArrayOffset, byteOffset);
#end
}
public inline function getUint32LE(byteOffset: Int): Int {
#if !sys_bigendian
return untyped __cpp__("*(uint32_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
return
untyped __cpp__("({0}.data[{1} + {2} + 0] << 0) | ({0}.data[{1} + {2} + 1] << 8) | ({0}.data[{1} + {2} + 2] << 16) | ({0}.data[{1} + {2} + 3] << 24)",
this.self,
this.byteArrayOffset, byteOffset);
#end
}
public inline function getFloat32LE(byteOffset: Int): FastFloat {
#if !sys_bigendian
return untyped __cpp__("*(float *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
untyped __cpp__("int32_t i = ({0}.data[{1} + {2} + 0] << 0) | ({0}.data[{1} + {2} + 1] << 8) | ({0}.data[{1} + {2} + 2] << 16) | ({0}.data[{1} + {2} + 3] << 24)",
this.self, this.byteArrayOffset, byteOffset);
return untyped __cpp__("*(float *)&i");
#end
}
public inline function getFloat64LE(byteOffset: Int): Float {
#if !sys_bigendian
return untyped __cpp__("*(double *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
untyped __cpp__("int64_t i = ((int64_t){0}.data[{1} + {2} + 0] << 0) | ((int64_t){0}.data[{1} + {2} + 1] << 8) | ((int64_t){0}.data[{1} + {2} + 2] << 16) | ((int64_t){0}.data[{1} + {2} + 3] << 24) | ((int64_t){0}.data[{1} + {2} + 4] << 32) | ((int64_t){0}.data[{1} + {2} + 5] << 40) | ((int64_t){0}.data[{1} + {2} + 6] << 48) | ((int64_t){0}.data[{1} + {2} + 7] << 56)",
this.self, this.byteArrayOffset, byteOffset);
return untyped __cpp__("*(double *)&i");
#end
}
public inline function setInt16LE(byteOffset: Int, value: Int): Void {
#if !sys_bigendian
untyped __cpp__("*(int16_t *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("int16_t levalue = data[0] << 8 | data[1] << 0");
untyped __cpp__("*(int16_t *)&{0}.data[{1} + {2}] = levalue", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function setUint16LE(byteOffset: Int, value: Int): Void {
#if !sys_bigendian
untyped __cpp__("*(uint16_t *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("uint16_t levalue = data[0] << 8 | data[1] << 0");
untyped __cpp__("*(uint16_t *)&{0}.data[{1} + {2}] = levalue", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function setInt32LE(byteOffset: Int, value: Int): Void {
#if !sys_bigendian
untyped __cpp__("*(int32_t *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("int32_t levalue = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3] << 0");
untyped __cpp__("*(int32_t *)&{0}.data[{1} + {2}] = levalue", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function setUint32LE(byteOffset: Int, value: Int): Void {
#if !sys_bigendian
untyped __cpp__("*(uint32_t *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("uint32_t levalue = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3] << 0");
untyped __cpp__("*(uint32_t *)&{0}.data[{1} + {2}] = levalue", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function setFloat32LE(byteOffset: Int, value: FastFloat): Void {
#if !sys_bigendian
untyped __cpp__("*(float *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("int32_t levalue = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3] << 0");
untyped __cpp__("float lefloat = *(float*)&levalue");
untyped __cpp__("*(float *)&{0}.data[{1} + {2}] = lefloat", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function setFloat64LE(byteOffset: Int, value: Float): Void {
#if !sys_bigendian
untyped __cpp__("*(double *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("int64_t levalue = (int64_t)data[0] << 56 | (int64_t)data[1] << 48 | (int64_t)data[2] << 40 | (int64_t)data[3] << 32 | (int64_t)data[4] << 24 | (int64_t)data[5] << 16 | (int64_t)data[6] << 8 | (int64_t)data[7] << 0");
untyped __cpp__("double lefloat = *(double*)&levalue");
untyped __cpp__("*(double *)&{0}.data[{1} + {2}] = lefloat", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function getInt16BE(byteOffset: Int): Int {
#if sys_bigendian
return untyped __cpp__("*(int16_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
untyped __cpp__("int i = ({0}.data[{1} + {2} + 1] << 0) | ({0}.data[{1} + {2} + 0] << 8)", this.self, this.byteArrayOffset, byteOffset);
return untyped __cpp__("*(float *)&i;");
#end
}
public inline function getUint16BE(byteOffset: Int): Int {
#if sys_bigendian
return untyped __cpp__("*(uint16_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
untyped __cpp__("int i = ({0}.data[{1} + {2} + 1] << 0) | ({0}.data[{1} + {2} + 0] << 8)", this.self, this.byteArrayOffset, byteOffset);
return untyped __cpp__("*(float *)&i;");
#end
}
public inline function getInt32BE(byteOffset: Int): Int {
#if sys_bigendian
return untyped __cpp__("*(int32_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
return
untyped __cpp__("({0}.data[{1} + {2} + 3] << 0) | ({0}.data[{1} + {2} + 2] << 8) | ({0}.data[{1} + {2} + 1] << 16) | ({0}.data[{1} + {2} + 0] << 24)",
this.self,
this.byteArrayOffset, byteOffset);
#end
}
public inline function getUint32BE(byteOffset: Int): Int {
#if sys_bigendian
return untyped __cpp__("*(uint32_t *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
return
untyped __cpp__("({0}.data[{1} + {2} + 3] << 0) | ({0}.data[{1} + {2} + 2] << 8) | ({0}.data[{1} + {2} + 1] << 16) | ({0}.data[{1} + {2} + 0] << 24)",
this.self,
this.byteArrayOffset, byteOffset);
#end
}
public inline function getFloat32BE(byteOffset: Int): FastFloat {
#if sys_bigendian
return untyped __cpp__("*(float *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
untyped __cpp__("int32_t i = ({0}.data[{1} + {2} + 3] << 0) | ({0}.data[{1} + {2} + 2] << 8) | ({0}.data[{1} + {2} + 1] << 16) | ({0}.data[{1} + {2} + 0] << 24)",
this.self, this.byteArrayOffset, byteOffset);
return untyped __cpp__("*(float *)&i;");
#end
}
public inline function getFloat64BE(byteOffset: Int): Float {
#if sys_bigendian
return untyped __cpp__("*(double *)&{0}.data[{1} + {2}]", this.self, this.byteArrayOffset, byteOffset);
#else
untyped __cpp__("int64_t i = ((int64_t){0}.data[{1} + {2} + 7] << 0) | ((int64_t){0}.data[{1} + {2} + 6] << 8) | ((int64_t){0}.data[{1} + {2} + 5] << 16) | ((int64_t){0}.data[{1} + {2} + 4] << 24) | ((int64_t){0}.data[{1} + {2} + 3] << 32) | ((int64_t){0}.data[{1} + {2} + 2] << 40) | ((int64_t){0}.data[{1} + {2} + 1] << 48) | ((int64_t){0}.data[{1} + {2} + 0] << 56)",
this.self, this.byteArrayOffset, byteOffset);
return untyped __cpp__("*(double *)&i;");
#end
}
public inline function setInt16BE(byteOffset: Int, value: Int): Void {
#if sys_bigendian
untyped __cpp__("*(int16_t *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("int16_t levalue = data[0] << 8 | data[1] << 0");
untyped __cpp__("*(int16_t *)&{0}.data[{1} + {2}] = levalue", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function setUint16BE(byteOffset: Int, value: Int): Void {
#if sys_bigendian
untyped __cpp__("*(uint16_t *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("uint16_t levalue = data[0] << 8 | data[1] << 0");
untyped __cpp__("*(uint16_t *)&{0}.data[{1} + {2}] = levalue", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function setInt32BE(byteOffset: Int, value: Int): Void {
#if sys_bigendian
untyped __cpp__("*(int32_t *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("int32_t levalue = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3] << 0");
untyped __cpp__("*(int32_t *)&{0}.data[{1} + {2}] = levalue", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function setUint32BE(byteOffset: Int, value: Int): Void {
#if sys_bigendian
untyped __cpp__("*(uint32_t *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("uint32_t levalue = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3] << 0");
untyped __cpp__("*(uint32_t *)&{0}.data[{1} + {2}] = levalue", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function setFloat32BE(byteOffset: Int, value: FastFloat): Void {
#if sys_bigendian
untyped __cpp__("*(float *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("int32_t levalue = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3] << 0");
untyped __cpp__("float lefloat = *(float*)&levalue");
untyped __cpp__("*(float *)&{0}.data[{1} + {2}] = lefloat", this.self, this.byteArrayOffset, byteOffset);
#end
}
public inline function setFloat64BE(byteOffset: Int, value: Float): Void {
#if sys_bigendian
untyped __cpp__("*(double *)&{0}.data[{1} + {2}] = {3}", this.self, this.byteArrayOffset, byteOffset, value);
#else
untyped __cpp__("int8_t * data = (int8_t *)&{0}", value);
untyped __cpp__("int64_t levalue = (int64_t)data[0] << 56 | (int64_t)data[1] << 48 | (int64_t)data[2] << 40 | (int64_t)data[3] << 32 | (int64_t)data[4] << 24 | (int64_t)data[5] << 16 | (int64_t)data[6] << 8 | (int64_t)data[7] << 0");
untyped __cpp__("double lefloat = *(double*)&levalue");
untyped __cpp__("*(double *)&{0}.data[{1} + {2}] = lefloat", this.self, this.byteArrayOffset, byteOffset);
#end
}
public function subarray(start: Int, ?end: Int): ByteArray {
var offset: Int = this.byteArrayOffset + start;
var length: Int = end == null ? this.byteArrayLength - start : end - start;
return new ByteArray(this.self, offset, length);
}
}

View File

@ -0,0 +1,20 @@
package kha.arrays;
@:unreflective
@:structAccess
@:include("cpp_bytearray.h")
@:native("bytearray")
extern class ByteBuffer {
@:native("bytearray")
public static function create(): ByteBuffer;
public function alloc(length: Int): Void;
public function addRef(): Void;
public function subRef(): Void;
public function get(index: Int): FastFloat;
public function set(index: Int, value: FastFloat): FastFloat;
}

View File

@ -0,0 +1,3 @@
package kha.audio1;
typedef Audio = kha.audio2.Audio1;

View File

@ -0,0 +1,58 @@
package kha.audio2;
import kha.Sound;
import kha.internal.IntBox;
@:keep
class Audio {
static var buffer: Buffer;
static var intBox: IntBox = new IntBox(0);
@:noCompletion
public static function _init() {
var bufferSize = 1024 * 2;
buffer = new Buffer(bufferSize * 4, 2, 44100);
}
@:noCompletion
public static function _callCallback(samples: Int, sampleRate: Int): Void {
if (buffer == null)
return;
buffer.samplesPerSecond = sampleRate;
if (audioCallback != null) {
intBox.value = samples;
audioCallback(intBox, buffer);
}
else {
for (i in 0...samples) {
buffer.data.set(buffer.writeLocation, 0);
buffer.writeLocation += 1;
if (buffer.writeLocation >= buffer.size) {
buffer.writeLocation = 0;
}
}
}
}
@:noCompletion
public static function _readSample(): Float {
if (buffer == null)
return 0;
var value = buffer.data.get(buffer.readLocation);
++buffer.readLocation;
if (buffer.readLocation >= buffer.size) {
buffer.readLocation = 0;
}
return value;
}
public static var disableGcInteractions = false;
public static var samplesPerSecond: Int;
public static var audioCallback: IntBox->Buffer->Void;
public static function stream(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel {
return null;
}
}

View File

@ -0,0 +1,108 @@
package kha.audio2;
import haxe.io.Bytes;
@:headerCode("#define STB_VORBIS_HEADER_ONLY\n#include <kinc/libs/stb_vorbis.c>")
@:headerClassCode("stb_vorbis* vorbis;")
class StreamChannel implements kha.audio1.AudioChannel {
var atend: Bool = false;
@:keep var loop: Bool;
var myVolume: Float;
var paused: Bool = false;
public function new(data: Bytes, loop: Bool) {
myVolume = 1;
this.loop = loop;
initVorbis(data);
}
@:functionCode("vorbis = stb_vorbis_open_memory(data->b->Pointer(), data->length, NULL, NULL);")
function initVorbis(data: Bytes): Void {}
@:functionCode("
int read = stb_vorbis_get_samples_float_interleaved(vorbis, 2, (float*)samples->self.data, length);
if (read < length / 2) {
if (loop) {
stb_vorbis_seek_start(vorbis);
}
else {
atend = true;
}
for (int i = read * 2; i < length; ++i) {
samples->self.data[i] = 0;
}
}
")
function nextVorbisSamples(samples: kha.arrays.Float32Array, length: Int): Void {}
public function nextSamples(samples: kha.arrays.Float32Array, length: Int, sampleRate: Int): Void {
if (paused) {
for (i in 0...length) {
samples[i] = 0;
}
return;
}
nextVorbisSamples(samples, length);
}
public function play(): Void {
paused = false;
}
public function pause(): Void {
paused = true;
}
public function stop(): Void {
atend = true;
}
public var length(get, never): Float; // Seconds
@:functionCode("
if (vorbis == NULL) return 0;
return stb_vorbis_stream_length_in_seconds(vorbis);
")
function get_length(): Int {
return 0;
}
public var position(get, set): Float; // Seconds
@:functionCode("
if (vorbis == NULL) return 0;
return stb_vorbis_get_sample_offset(vorbis) /
(float)stb_vorbis_stream_length_in_samples(vorbis) *
stb_vorbis_stream_length_in_seconds(vorbis);
")
function get_position(): Float {
return 0;
}
@:functionCode("
if (vorbis == NULL) return value;
unsigned int rate = stb_vorbis_get_info(vorbis).sample_rate;
stb_vorbis_seek_frame(vorbis, rate * value);
return value;
")
function set_position(value: Float): Float {
return value;
}
public var volume(get, set): Float;
function get_volume(): Float {
return myVolume;
}
function set_volume(value: Float): Float {
return myVolume = value;
}
public var finished(get, never): Bool;
function get_finished(): Bool {
return atend;
}
}

View File

@ -0,0 +1,11 @@
package kha.capture;
import kha.audio2.Buffer;
class AudioCapture {
public static var audioCallback: Int->Buffer->Void;
public static function init(initialized: Void->Void, error: Void->Void): Void {
error();
}
}

View File

@ -0,0 +1,176 @@
package kha.compute;
import kha.arrays.Float32Array;
import kha.Image;
import kha.FastFloat;
import kha.math.FastMatrix3;
import kha.math.FastMatrix4;
import kha.math.FastVector2;
import kha.math.FastVector3;
import kha.math.FastVector4;
import kha.graphics4.CubeMap;
import kha.graphics4.TextureAddressing;
import kha.graphics4.TextureFilter;
import kha.graphics4.MipMapFilter;
@:headerCode("
#include <kinc/compute/compute.h>
")
class Compute {
public static function setBool(location: ConstantLocation, value: Bool) {
untyped __cpp__("kinc_compute_set_bool(location->location, value);");
}
public static function setInt(location: ConstantLocation, value: Int) {
untyped __cpp__("kinc_compute_set_int(location->location, value);");
}
public static function setFloat(location: ConstantLocation, value: FastFloat) {
untyped __cpp__("kinc_compute_set_float(location->location, value);");
}
public static function setFloat2(location: ConstantLocation, value1: FastFloat, value2: FastFloat) {
untyped __cpp__("kinc_compute_set_float2(location->location, value1, value2);");
}
public static function setFloat3(location: ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat) {
untyped __cpp__("kinc_compute_set_float3(location->location, value1, value2, value3);");
}
public static function setFloat4(location: ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat, value4: FastFloat) {
untyped __cpp__("kinc_compute_set_float4(location->location, value1, value2, value3, value4);");
}
public static function setFloats(location: ConstantLocation, values: Float32Array) {
untyped __cpp__("kinc_compute_set_floats(location->location, (float *)&values->self.data[values->byteArrayOffset], values->byteArrayLength);");
}
public static function setVector2(location: ConstantLocation, value: FastVector2): Void {
Compute.setFloat2(location, value.x, value.y);
}
public static function setVector3(location: ConstantLocation, value: FastVector3): Void {
Compute.setFloat3(location, value.x, value.y, value.z);
}
public static function setVector4(location: ConstantLocation, value: FastVector4): Void {
Compute.setFloat4(location, value.x, value.y, value.z, value.w);
}
public static function setMatrix(location: ConstantLocation, value: FastMatrix4): Void {
setMatrixPrivate(location, value);
}
public static function setMatrix3(location: ConstantLocation, value: FastMatrix3): Void {
setMatrix3Private(location, value);
}
@:functionCode("
kinc_matrix4x4_t value;
kinc_matrix4x4_set(&value, 0, 0, matrix->_00); kinc_matrix4x4_set(&value, 0, 1, matrix->_10); kinc_matrix4x4_set(&value, 0, 2, matrix->_20); kinc_matrix4x4_set(&value, 0, 3, matrix->_30);
kinc_matrix4x4_set(&value, 1, 0, matrix->_01); kinc_matrix4x4_set(&value, 1, 1, matrix->_11); kinc_matrix4x4_set(&value, 1, 2, matrix->_21); kinc_matrix4x4_set(&value, 1, 3, matrix->_31);
kinc_matrix4x4_set(&value, 2, 0, matrix->_02); kinc_matrix4x4_set(&value, 2, 1, matrix->_12); kinc_matrix4x4_set(&value, 2, 2, matrix->_22); kinc_matrix4x4_set(&value, 2, 3, matrix->_32);
kinc_matrix4x4_set(&value, 3, 0, matrix->_03); kinc_matrix4x4_set(&value, 3, 1, matrix->_13); kinc_matrix4x4_set(&value, 3, 2, matrix->_23); kinc_matrix4x4_set(&value, 3, 3, matrix->_33);
kinc_compute_set_matrix4(location->location, &value);
")
static function setMatrixPrivate(location: ConstantLocation, matrix: FastMatrix4): Void {}
@:functionCode("
kinc_matrix3x3_t value;
kinc_matrix3x3_set(&value, 0, 0, matrix->_00); kinc_matrix3x3_set(&value, 0, 1, matrix->_10); kinc_matrix3x3_set(&value, 0, 2, matrix->_20);
kinc_matrix3x3_set(&value, 1, 0, matrix->_01); kinc_matrix3x3_set(&value, 1, 1, matrix->_11); kinc_matrix3x3_set(&value, 1, 2, matrix->_21);
kinc_matrix3x3_set(&value, 2, 0, matrix->_02); kinc_matrix3x3_set(&value, 2, 1, matrix->_12); kinc_matrix3x3_set(&value, 2, 2, matrix->_22);
kinc_compute_set_matrix3(location->location, &value);
")
static function setMatrix3Private(location: ConstantLocation, matrix: FastMatrix3): Void {}
public static function setBuffer(buffer: ShaderStorageBuffer, index: Int) {
untyped __cpp__("
#ifdef KORE_OPENGL
kinc_compute_set_buffer(&buffer->buffer, index);
#endif
");
}
public static function setTexture(unit: TextureUnit, texture: Image, access: Access) {
setTexturePrivate(unit, texture, access);
}
@:functionCode("
if (texture->imageType == KhaImageTypeTexture) kinc_compute_set_texture(unit->unit, &texture->texture, (kinc_compute_access_t)access);
else if (texture->imageType == KhaImageTypeRenderTarget) kinc_compute_set_render_target(unit->unit, &texture->renderTarget, (kinc_compute_access_t)access);
")
static function setTexturePrivate(unit: TextureUnit, texture: Image, access: Int): Void {}
public static function setSampledTexture(unit: TextureUnit, texture: Image) {
setSampledTexturePrivate(unit, texture);
}
@:functionCode("
if (texture->imageType == KhaImageTypeTexture) kinc_compute_set_sampled_texture(unit->unit, &texture->texture);
else if (texture->imageType == KhaImageTypeRenderTarget) kinc_compute_set_sampled_render_target(unit->unit, &texture->renderTarget);
")
static function setSampledTexturePrivate(unit: TextureUnit, texture: Image): Void {}
public static function setSampledDepthTexture(unit: TextureUnit, texture: Image) {
untyped __cpp__("if (texture->imageType == KhaImageTypeRenderTarget) kinc_compute_set_sampled_depth_from_render_target(unit->unit, &texture->renderTarget);");
}
public static function setSampledCubeMap(unit: TextureUnit, cubeMap: CubeMap) {
setSampledCubeMapPrivate(unit, cubeMap);
}
@:functionCode("kinc_compute_set_sampled_render_target(unit->unit, &cubeMap->renderTarget);")
static function setSampledCubeMapPrivate(unit: TextureUnit, cubeMap: CubeMap): Void {}
public static function setSampledDepthCubeMap(unit: TextureUnit, cubeMap: CubeMap) {
untyped __cpp__("kinc_compute_set_sampled_depth_from_render_target(unit->unit, &cubeMap->renderTarget);");
}
@:functionCode("
kinc_compute_set_texture_addressing(unit->unit, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)uWrap);
kinc_compute_set_texture_addressing(unit->unit, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)vWrap);
")
static function setTextureWrapNative(unit: TextureUnit, uWrap: Int, vWrap: Int): Void {}
@:functionCode("
kinc_compute_set_texture3d_addressing(unit->unit, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)uWrap);
kinc_compute_set_texture3d_addressing(unit->unit, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)vWrap);
kinc_compute_set_texture3d_addressing(unit->unit, KINC_G4_TEXTURE_DIRECTION_W, (kinc_g4_texture_addressing_t)wWrap);
")
static function setTexture3DWrapNative(unit: TextureUnit, uWrap: Int, vWrap: Int, wWrap: Int): Void {}
@:functionCode("
kinc_compute_set_texture_minification_filter(unit->unit, (kinc_g4_texture_filter_t)minificationFilter);
kinc_compute_set_texture_magnification_filter(unit->unit, (kinc_g4_texture_filter_t)magnificationFilter);
kinc_compute_set_texture_mipmap_filter(unit->unit, (kinc_g4_mipmap_filter_t)mipMapFilter);
")
static function setTextureFiltersNative(unit: TextureUnit, minificationFilter: Int, magnificationFilter: Int, mipMapFilter: Int): Void {}
@:functionCode("
kinc_compute_set_texture3d_minification_filter(unit->unit, (kinc_g4_texture_filter_t)minificationFilter);
kinc_compute_set_texture3d_magnification_filter(unit->unit, (kinc_g4_texture_filter_t)magnificationFilter);
kinc_compute_set_texture3d_mipmap_filter(unit->unit, (kinc_g4_mipmap_filter_t)mipMapFilter);
")
static function setTexture3DFiltersNative(unit: TextureUnit, minificationFilter: Int, magnificationFilter: Int, mipMapFilter: Int): Void {}
public static function setTextureParameters(unit: TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing,
minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void {
setTextureWrapNative(unit, uAddressing, vAddressing);
setTextureFiltersNative(unit, minificationFilter, magnificationFilter, mipmapFilter);
}
public static function setTexture3DParameters(unit: TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing,
wAddressing: TextureAddressing, minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void {
setTexture3DWrapNative(unit, uAddressing, vAddressing, wAddressing);
setTexture3DFiltersNative(unit, minificationFilter, magnificationFilter, mipmapFilter);
}
public static function setShader(shader: Shader) {
untyped __cpp__("kinc_compute_set_shader(&shader->shader);");
}
public static function compute(x: Int, y: Int, z: Int) {
untyped __cpp__("kinc_compute(x, y, z);");
}
}

View File

@ -0,0 +1,9 @@
package kha.compute;
@:headerCode("
#include <kinc/compute/compute.h>
")
@:headerClassCode("kinc_compute_constant_location location;")
class ConstantLocation {
public function new() {}
}

View File

@ -0,0 +1,45 @@
package kha.compute;
import haxe.io.Bytes;
import kha.Blob;
@:headerCode("
#include <kinc/compute/compute.h>
")
@:headerClassCode("kinc_compute_shader shader;")
class Shader {
public function new(sources: Array<Blob>, files: Array<String>) {
init(sources[0], files[0]);
}
function init(source: Blob, file: String): Void {
untyped __cpp__("kinc_compute_shader_init(&shader, source->bytes->b->Pointer(), source->get_length());");
}
public function delete(): Void {
untyped __cpp__("kinc_compute_shader_destroy(&shader);");
}
public function getConstantLocation(name: String): ConstantLocation {
var location = new ConstantLocation();
initConstantLocation(location, name);
return location;
}
@:functionCode("location->location = kinc_compute_shader_get_constant_location(&shader, name.c_str());")
function initConstantLocation(location: ConstantLocation, name: String): Void {}
public function getTextureUnit(name: String): TextureUnit {
var unit = new TextureUnit();
initTextureUnit(unit, name);
return unit;
}
@:functionCode("unit->unit = kinc_compute_shader_get_texture_unit(&shader, name.c_str());")
function initTextureUnit(unit: TextureUnit, name: String): Void {}
@:keep
function _forceInclude(): Void {
Bytes.alloc(0);
}
}

View File

@ -0,0 +1,77 @@
package kha.compute;
import kha.graphics4.VertexData;
@:headerCode("
#include <kinc/compute/compute.h>
")
@:headerClassCode("
#ifdef KORE_OPENGL
kinc_shader_storage_buffer buffer;
#endif")
class ShaderStorageBuffer {
var data: Array<Int>;
var myCount: Int;
public function new(indexCount: Int, type: VertexData) {
myCount = indexCount;
data = new Array<Int>();
data[myCount - 1] = 0;
init(indexCount, type);
}
@:functionCode("
#ifdef KORE_OPENGL
kinc_g4_vertex_data type2;
switch (type) {
case 0:
type2 = KINC_G4_VERTEX_DATA_FLOAT1;
break;
case 1:
type2 = KINC_G4_VERTEX_DATA_FLOAT2;
break;
case 2:
type2 = KINC_G4_VERTEX_DATA_FLOAT3;
break;
case 3:
type2 = KINC_G4_VERTEX_DATA_FLOAT4;
break;
case 4:
type2 = KINC_G4_VERTEX_DATA_FLOAT4X4;
break;
}
kinc_shader_storage_buffer_init(&buffer, indexCount, type2);
#endif
")
function init(indexCount: Int, type: VertexData) {
myCount = indexCount;
data = new Array<Int>();
data[myCount - 1] = 0;
}
@:functionCode("
#ifdef KORE_OPENGL
kinc_shader_storage_buffer_destroy(&buffer);
#endif
")
public function delete(): Void {}
public function lock(): Array<Int> {
return data;
}
@:functionCode("
#ifdef KORE_OPENGL
int* indices = kinc_shader_storage_buffer_lock(&buffer);
for (int i = 0; i < myCount; ++i) {
indices[i] = data[i];
}
kinc_shader_storage_buffer_unlock(&buffer);
#endif
")
public function unlock(): Void {}
public function count(): Int {
return myCount;
}
}

View File

@ -0,0 +1,9 @@
package kha.compute;
@:headerCode("
#include <kinc/compute/compute.h>
")
@:headerClassCode("kinc_compute_texture_unit unit;")
class TextureUnit {
public function new() {}
}

View File

@ -0,0 +1,123 @@
package kha.graphics4;
import haxe.io.Bytes;
@:headerCode("
#include <kinc/graphics4/rendertarget.h>
")
@:headerClassCode("kinc_g4_render_target_t renderTarget;")
class CubeMap implements Canvas implements Resource {
var format: TextureFormat;
var graphics4: kha.graphics4.Graphics;
function new() {}
public static function createRenderTarget(size: Int, format: TextureFormat = null, depthStencil: DepthStencilFormat = null): CubeMap {
return create2(size, format == null ? TextureFormat.RGBA32 : format, false, true, depthStencil);
}
public static function create2(size: Int, format: TextureFormat, readable: Bool, renderTarget: Bool, depthStencil: DepthStencilFormat): CubeMap {
var cubeMap = new CubeMap();
cubeMap.format = format;
if (renderTarget)
cubeMap.initRenderTarget(size, getRenderTargetFormat(format), getDepthBufferBits(depthStencil), getStencilBufferBits(depthStencil));
return cubeMap;
}
@:functionCode("kinc_g4_render_target_init_cube(&renderTarget, cubeMapSize, (kinc_g4_render_target_format_t)format, depthBufferBits, stencilBufferBits);")
function initRenderTarget(cubeMapSize: Int, format: Int, depthBufferBits: Int, stencilBufferBits: Int): Void {}
static function getRenderTargetFormat(format: TextureFormat): Int {
switch (format) {
case RGBA32: // Target32Bit
return 0;
case RGBA64: // Target64BitFloat
return 1;
case RGBA128: // Target128BitFloat
return 3;
case DEPTH16: // Target16BitDepth
return 4;
default:
return 0;
}
}
static function getDepthBufferBits(depthAndStencil: DepthStencilFormat): Int {
return switch (depthAndStencil) {
case NoDepthAndStencil: -1;
case DepthOnly: 24;
case DepthAutoStencilAuto: 24;
case Depth24Stencil8: 24;
case Depth32Stencil8: 32;
case Depth16: 16;
}
}
static function getStencilBufferBits(depthAndStencil: DepthStencilFormat): Int {
return switch (depthAndStencil) {
case NoDepthAndStencil: -1;
case DepthOnly: -1;
case DepthAutoStencilAuto: 8;
case Depth24Stencil8: 8;
case Depth32Stencil8: 8;
case Depth16: 0;
}
}
static function getTextureFormat(format: TextureFormat): Int {
switch (format) {
case RGBA32:
return 0;
case RGBA128:
return 3;
case RGBA64:
return 4;
case A32:
return 5;
default:
return 1; // Grey 8
}
}
public function unload(): Void {}
public function lock(level: Int = 0): Bytes {
return null;
}
public function unlock(): Void {}
public var width(get, never): Int;
public var height(get, never): Int;
@:functionCode("return renderTarget.width;")
function get_width(): Int {
return 0;
}
@:functionCode("return renderTarget.height;")
function get_height(): Int {
return 0;
}
public var g1(get, never): kha.graphics1.Graphics;
function get_g1(): kha.graphics1.Graphics {
return null;
}
public var g2(get, never): kha.graphics2.Graphics;
function get_g2(): kha.graphics2.Graphics {
return null;
}
public var g4(get, never): kha.graphics4.Graphics;
function get_g4(): kha.graphics4.Graphics {
if (graphics4 == null) {
graphics4 = new kha.kore.graphics4.Graphics(this);
}
return graphics4;
}
}

View File

@ -0,0 +1,35 @@
package kha.graphics4;
import haxe.io.Bytes;
import kha.Blob;
@:headerCode("
#include <kinc/graphics4/shader.h>
")
@:headerClassCode("kinc_g4_shader_t shader;")
class FragmentShader {
public function new(sources: Array<Blob>, files: Array<String>) {
if (sources != null) {
init(sources[0], files[0]);
}
}
function init(source: Blob, file: String): Void {
untyped __cpp__("kinc_g4_shader_init(&shader, source->bytes->b->Pointer(), source->get_length(), KINC_G4_SHADER_TYPE_FRAGMENT);");
}
public static function fromSource(source: String): FragmentShader {
var fragmentShader = new FragmentShader(null, null);
untyped __cpp__("kinc_g4_shader_init_from_source(&fragmentShader->shader, source, KINC_G4_SHADER_TYPE_FRAGMENT);");
return fragmentShader;
}
public function delete(): Void {
untyped __cpp__("kinc_g4_shader_destroy(&shader);");
}
@:keep
function _forceInclude(): Void {
Bytes.alloc(0);
}
}

View File

@ -0,0 +1,27 @@
package kha.graphics4;
import haxe.io.Bytes;
import kha.Blob;
@:headerCode("
#include <kinc/graphics4/shader.h>
")
@:headerClassCode("kinc_g4_shader_t shader;")
class GeometryShader {
public function new(sources: Array<Blob>, files: Array<String>) {
init(sources[0], files[0]);
}
function init(source: Blob, file: String): Void {
untyped __cpp__("kinc_g4_shader_init(&shader, source->bytes->b->Pointer(), source->get_length(), KINC_G4_SHADER_TYPE_GEOMETRY);");
}
public function delete(): Void {
untyped __cpp__("kinc_g4_shader_destroy(&shader);");
}
@:keep
function _forceInclude(): Void {
Bytes.alloc(0);
}
}

View File

@ -0,0 +1,53 @@
package kha.graphics4;
import kha.arrays.Uint32Array;
@:headerCode("
#include <kinc/graphics4/indexbuffer.h>
")
@:headerClassCode("kinc_g4_index_buffer_t buffer;")
class IndexBuffer {
var data: Uint32Array;
var myCount: Int;
public function new(indexCount: Int, usage: Usage, canRead: Bool = false) {
myCount = indexCount;
data = new Uint32Array(0);
untyped __cpp__("kinc_g4_index_buffer_init(&buffer, indexCount, KINC_G4_INDEX_BUFFER_FORMAT_32BIT, (kinc_g4_usage_t)usage);");
}
public function delete(): Void {
untyped __cpp__("kinc_g4_index_buffer_destroy(&buffer);");
}
@:functionCode("
data->self.data = (uint8_t*)kinc_g4_index_buffer_lock(&buffer, start, count);
data->byteArrayLength = count * 4;
data->byteArrayOffset = 0;
return data;
")
function lockPrivate(start: Int, count: Int): Uint32Array {
return data;
}
public function lock(?start: Int, ?count: Int): Uint32Array {
if (start == null)
start = 0;
if (count == null)
count = this.count();
return lockPrivate(start, count);
}
@:functionCode("kinc_g4_index_buffer_unlock(&buffer, count); data->self.data = nullptr;")
public function unlockPrivate(count: Int): Void {}
public function unlock(?count: Int): Void {
if (count == null)
count = this.count();
unlockPrivate(count);
}
public function count(): Int {
return myCount;
}
}

View File

@ -0,0 +1,313 @@
package kha.graphics4;
import kha.graphics4.FragmentShader;
import kha.graphics4.VertexData;
import kha.graphics4.VertexElement;
import kha.graphics4.VertexShader;
import kha.graphics4.VertexStructure;
@:headerCode("
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/pipeline.h>
#include <kinc/graphics4/vertexstructure.h>
#include <khalib/g4.h>
")
@:cppFileCode("
static kinc_g4_compare_mode_t convertCompareMode(int mode) {
switch (mode) {
case 0:
return KINC_G4_COMPARE_ALWAYS;
case 1:
return KINC_G4_COMPARE_NEVER;
case 2:
return KINC_G4_COMPARE_EQUAL;
case 3:
return KINC_G4_COMPARE_NOT_EQUAL;
case 4:
return KINC_G4_COMPARE_LESS;
case 5:
return KINC_G4_COMPARE_LESS_EQUAL;
case 6:
return KINC_G4_COMPARE_GREATER;
case 7:
default:
return KINC_G4_COMPARE_GREATER_EQUAL;
}
}
static kinc_g4_stencil_action_t convertStencilAction(int action) {
switch (action) {
case 0:
return KINC_G4_STENCIL_KEEP;
case 1:
return KINC_G4_STENCIL_ZERO;
case 2:
return KINC_G4_STENCIL_REPLACE;
case 3:
return KINC_G4_STENCIL_INCREMENT;
case 4:
return KINC_G4_STENCIL_INCREMENT_WRAP;
case 5:
return KINC_G4_STENCIL_DECREMENT;
case 6:
return KINC_G4_STENCIL_DECREMENT_WRAP;
case 7:
default:
return KINC_G4_STENCIL_INVERT;
}
}
static kinc_g4_render_target_format_t convertColorAttachment(int format) {
switch (format) {
case 0:
return KINC_G4_RENDER_TARGET_FORMAT_32BIT;
case 1:
return KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED;
case 2:
return KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT;
case 3:
return KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH;
case 4:
return KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT;
case 5:
return KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT;
case 6:
default:
return KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT;
}
}
")
@:headerClassCode("kinc_g4_pipeline_t pipeline;")
@:keep
class PipelineState extends PipelineStateBase {
public function new() {
super();
untyped __cpp__("kinc_g4_pipeline_init(&pipeline);");
}
public function delete(): Void {
untyped __cpp__("kinc_g4_pipeline_destroy(&pipeline);");
}
@:functionCode("
pipeline.vertex_shader = &vertexShader->shader;
pipeline.fragment_shader = &fragmentShader->shader;
if (geometryShader != null()) pipeline.geometry_shader = &geometryShader->shader;
if (tessellationControlShader != null()) pipeline.tessellation_control_shader = &tessellationControlShader->shader;
if (tessellationEvaluationShader != null()) pipeline.tessellation_evaluation_shader = &tessellationEvaluationShader->shader;
kinc_g4_vertex_structure_t s0, s1, s2, s3;
kinc_g4_vertex_structure_t* structures2[4] = { &s0, &s1, &s2, &s3 };
::kha::graphics4::VertexStructure* structures[4] = { &structure0, &structure1, &structure2, &structure3 };
for (int i1 = 0; i1 < size; ++i1) {
kinc_g4_vertex_structure_init(structures2[i1]);
structures2[i1]->instanced = (*structures[i1])->instanced;
for (int i2 = 0; i2 < (*structures[i1])->size(); ++i2) {
kinc_g4_vertex_data_t data = kha_convert_vertex_data((*structures[i1])->get(i2)->data);
pipeline.input_layout[i1] = structures2[i1];
kinc_g4_vertex_structure_add(pipeline.input_layout[i1], (*structures[i1])->get(i2)->name, data);
}
}
for (int i = size; i < 16; ++i) {
pipeline.input_layout[i] = nullptr;
}
kinc_g4_pipeline_compile(&pipeline);
")
function linkWithStructures2(structure0: VertexStructure, structure1: VertexStructure, structure2: VertexStructure, structure3: VertexStructure,
size: Int): Void {}
static function getDepthBufferBits(depthAndStencil: DepthStencilFormat): Int {
return switch (depthAndStencil) {
case NoDepthAndStencil: 0;
case DepthOnly: 24;
case DepthAutoStencilAuto: 24;
case Depth24Stencil8: 24;
case Depth32Stencil8: 32;
case Depth16: 16;
}
}
static function getStencilBufferBits(depthAndStencil: DepthStencilFormat): Int {
return switch (depthAndStencil) {
case NoDepthAndStencil: 0;
case DepthOnly: 0;
case DepthAutoStencilAuto: 8;
case Depth24Stencil8: 8;
case Depth32Stencil8: 8;
case Depth16: 0;
}
}
public function compile(): Void {
var stencilReferenceValue = switch (this.stencilReferenceValue) {
case Static(value): value;
default: 0;
}
setStates(cullMode, depthMode, stencilFrontMode, stencilFrontBothPass, stencilFrontDepthFail, stencilFrontFail, stencilBackMode, stencilBackBothPass,
stencilBackDepthFail, stencilBackFail, depthWrite, stencilReferenceValue, getBlendFactor(blendSource), getBlendFactor(blendDestination),
getBlendOperation(blendOperation), getBlendFactor(alphaBlendSource), getBlendFactor(alphaBlendDestination),
getBlendOperation(alphaBlendOperation), getDepthBufferBits(depthStencilAttachment), getStencilBufferBits(depthStencilAttachment));
linkWithStructures2(inputLayout.length > 0 ? inputLayout[0] : null, inputLayout.length > 1 ? inputLayout[1] : null,
inputLayout.length > 2 ? inputLayout[2] : null, inputLayout.length > 3 ? inputLayout[3] : null, inputLayout.length);
}
public function getConstantLocation(name: String): kha.graphics4.ConstantLocation {
var location = new kha.kore.graphics4.ConstantLocation();
initConstantLocation(location, name);
return location;
}
@:functionCode("location->location = kinc_g4_pipeline_get_constant_location(&pipeline, name.c_str());")
function initConstantLocation(location: kha.kore.graphics4.ConstantLocation, name: String): Void {}
public function getTextureUnit(name: String): kha.graphics4.TextureUnit {
var unit = new kha.kore.graphics4.TextureUnit();
initTextureUnit(unit, name);
return unit;
}
@:functionCode("unit->unit = kinc_g4_pipeline_get_texture_unit(&pipeline, name.c_str());")
function initTextureUnit(unit: kha.kore.graphics4.TextureUnit, name: String): Void {}
static function getBlendFactor(factor: BlendingFactor): Int {
switch (factor) {
case BlendOne, Undefined:
return 0;
case BlendZero:
return 1;
case SourceAlpha:
return 2;
case DestinationAlpha:
return 3;
case InverseSourceAlpha:
return 4;
case InverseDestinationAlpha:
return 5;
case SourceColor:
return 6;
case DestinationColor:
return 7;
case InverseSourceColor:
return 8;
case InverseDestinationColor:
return 9;
default:
return 0;
}
}
static function getBlendOperation(factor: BlendingOperation): Int {
switch (factor) {
case Add:
return 0;
case Subtract:
return 1;
case ReverseSubtract:
return 2;
case Min:
return 3;
case Max:
return 4;
default:
return 0;
}
}
@:functionCode("
switch (cullMode) {
case 0:
pipeline.cull_mode = KINC_G4_CULL_CLOCKWISE;
break;
case 1:
pipeline.cull_mode = KINC_G4_CULL_COUNTER_CLOCKWISE;
break;
case 2:
pipeline.cull_mode = KINC_G4_CULL_NOTHING;
break;
}
pipeline.depth_mode = convertCompareMode(depthMode);
pipeline.depth_write = depthWrite;
pipeline.stencil_front_mode = convertCompareMode(stencilFrontMode);
pipeline.stencil_front_both_pass = convertStencilAction(stencilFrontBothPass);
pipeline.stencil_front_depth_fail = convertStencilAction(stencilFrontDepthFail);
pipeline.stencil_front_fail = convertStencilAction(stencilFrontFail);
pipeline.stencil_back_mode = convertCompareMode(stencilBackMode);
pipeline.stencil_back_both_pass = convertStencilAction(stencilBackBothPass);
pipeline.stencil_back_depth_fail = convertStencilAction(stencilBackDepthFail);
pipeline.stencil_back_fail = convertStencilAction(stencilBackFail);
pipeline.stencil_reference_value = stencilReferenceValue;
pipeline.stencil_read_mask = stencilReadMask;
pipeline.stencil_write_mask = stencilWriteMask;
pipeline.blend_source = (kinc_g4_blending_factor_t)blendSource;
pipeline.blend_destination = (kinc_g4_blending_factor_t)blendDestination;
pipeline.blend_operation = (kinc_g4_blending_operation_t)blendOperation;
pipeline.alpha_blend_source = (kinc_g4_blending_factor_t)alphaBlendSource;
pipeline.alpha_blend_destination = (kinc_g4_blending_factor_t)alphaBlendDestination;
pipeline.alpha_blend_operation = (kinc_g4_blending_operation_t)alphaBlendOperation;
for (int i = 0; i < 8; ++i) {
pipeline.color_write_mask_red[i] = colorWriteMasksRed[i];
pipeline.color_write_mask_green[i] = colorWriteMasksGreen[i];
pipeline.color_write_mask_blue[i] = colorWriteMasksBlue[i];
pipeline.color_write_mask_alpha[i] = colorWriteMasksAlpha[i];
}
pipeline.color_attachment_count = colorAttachmentCount;
for (int i = 0; i < 8; ++i) {
pipeline.color_attachment[i] = convertColorAttachment(colorAttachments[i]);
}
pipeline.depth_attachment_bits = depthAttachmentBits;
pipeline.stencil_attachment_bits = stencilAttachmentBits;
pipeline.conservative_rasterization = conservativeRasterization;
")
function setStates(cullMode: Int, depthMode: Int, stencilFrontMode: Int, stencilFrontBothPass: Int, stencilFrontDepthFail: Int, stencilFrontFail: Int,
stencilBackMode: Int, stencilBackBothPass: Int, stencilBackDepthFail: Int, stencilBackFail: Int, depthWrite: Bool, stencilReferenceValue: Int,
blendSource: Int, blendDestination: Int, blendOperation: Int, alphaBlendSource: Int, alphaBlendDestination: Int, alphaBlendOperation: Int,
depthAttachmentBits: Int, stencilAttachmentBits: Int): Void {}
@:functionCode("kinc_g4_set_pipeline(&pipeline);")
function set2(): Void {}
public function set(): Void {
set2();
}
@:noCompletion
public static function _unused1(): VertexElement {
return null;
}
@:noCompletion
public static function _unused2(): VertexData {
return VertexData.Float32_1X;
}
@:noCompletion
public static function _unused3(): VertexShader {
return null;
}
@:noCompletion
public static function _unused4(): FragmentShader {
return null;
}
@:noCompletion
public static function _unused5(): GeometryShader {
return null;
}
@:noCompletion
public static function _unused6(): TessellationControlShader {
return null;
}
@:noCompletion
public static function _unused7(): TessellationEvaluationShader {
return null;
}
}

View File

@ -0,0 +1,27 @@
package kha.graphics4;
import haxe.io.Bytes;
import kha.Blob;
@:headerCode("
#include <kinc/graphics4/shader.h>
")
@:headerClassCode("kinc_g4_shader_t shader;")
class TessellationControlShader {
public function new(sources: Array<Blob>, files: Array<String>) {
init(sources[0], files[0]);
}
function init(source: Blob, file: String): Void {
untyped __cpp__("kinc_g4_shader_init(&shader, source->bytes->b->Pointer(), source->get_length(), KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL);");
}
public function delete(): Void {
untyped __cpp__("kinc_g4_shader_destroy(&shader);");
}
@:keep
function _forceInclude(): Void {
Bytes.alloc(0);
}
}

View File

@ -0,0 +1,27 @@
package kha.graphics4;
import haxe.io.Bytes;
import kha.Blob;
@:headerCode("
#include <kinc/graphics4/shader.h>
")
@:headerClassCode("kinc_g4_shader_t shader;")
class TessellationEvaluationShader {
public function new(sources: Array<Blob>, files: Array<String>) {
init(sources[0], files[0]);
}
function init(source: Blob, file: String): Void {
untyped __cpp__("kinc_g4_shader_init(&shader, source->bytes->b->Pointer(), source->get_length(), KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION);");
}
public function delete(): Void {
untyped __cpp__("kinc_g4_shader_destroy(&shader);");
}
@:keep
function _forceInclude(): Void {
Bytes.alloc(0);
}
}

View File

@ -0,0 +1,108 @@
package kha.graphics4;
import kha.arrays.Float32Array;
import kha.arrays.Int16Array;
import kha.graphics4.VertexData;
import kha.graphics4.VertexElement;
import kha.graphics4.VertexStructure;
@:headerCode("
#include <kinc/graphics4/vertexbuffer.h>
#include <khalib/g4.h>
")
@:headerClassCode("kinc_g4_vertex_buffer_t buffer;")
class VertexBuffer {
var data: Float32Array;
@:keep var dataInt16: Int16Array;
public function new(vertexCount: Int, structure: VertexStructure, usage: Usage, instanceDataStepRate: Int = 0, canRead: Bool = false) {
init(vertexCount, structure, usage, instanceDataStepRate);
data = new Float32Array(0);
}
public function delete(): Void {
untyped __cpp__("kinc_g4_vertex_buffer_destroy(&buffer);");
}
@:functionCode("
kinc_g4_vertex_structure_t structure2;
kinc_g4_vertex_structure_init(&structure2);
for (int i = 0; i < structure->size(); ++i) {
kinc_g4_vertex_data_t data = kha_convert_vertex_data(structure->get(i)->data);
kinc_g4_vertex_structure_add(&structure2, structure->get(i)->name, data);
}
kinc_g4_vertex_buffer_init(&buffer, vertexCount, &structure2, (kinc_g4_usage_t)usage, instanceDataStepRate);
")
function init(vertexCount: Int, structure: VertexStructure, usage: Int, instanceDataStepRate: Int) {}
@:functionCode("
data->self.data = (uint8_t*)kinc_g4_vertex_buffer_lock(&buffer, start, count);
data->byteArrayLength = count * kinc_g4_vertex_buffer_stride(&buffer);
data->byteArrayOffset = 0;
return data;
")
function lockPrivate(start: Int, count: Int): Float32Array {
return data;
}
var lastLockCount: Int = 0;
public function lock(?start: Int, ?count: Int): Float32Array {
if (start == null)
start = 0;
if (count == null)
count = this.count() - start;
lastLockCount = count;
return lockPrivate(start, count);
}
@:functionCode("
dataInt16->self.data = (uint8_t*)kinc_g4_vertex_buffer_lock(&buffer, start, count);
dataInt16->byteArrayLength = count * kinc_g4_vertex_buffer_stride(&buffer);
dataInt16->byteArrayOffset = 0;
return dataInt16;
")
function lockInt16Private(start: Int, count: Int): Int16Array {
return dataInt16;
}
public function lockInt16(?start: Int, ?count: Int): Int16Array {
if (start == null)
start = 0;
if (count == null)
count = this.count();
lastLockCount = count;
if (dataInt16 == null)
dataInt16 = new Int16Array(0);
return lockInt16Private(start, count);
}
@:functionCode("kinc_g4_vertex_buffer_unlock(&buffer, count); data->self.data = nullptr; if (!hx::IsNull(dataInt16)) dataInt16->self.data = nullptr;")
function unlockPrivate(count: Int): Void {}
public function unlock(?count: Int): Void {
unlockPrivate(count == null ? lastLockCount : count);
}
@:functionCode("return kinc_g4_vertex_buffer_stride(&buffer);")
public function stride(): Int {
return 0;
}
@:functionCode("return kinc_g4_vertex_buffer_count(&buffer);")
public function count(): Int {
return 0;
}
@:noCompletion
@:keep
public static function _unused1(): VertexElement {
return null;
}
@:noCompletion
@:keep
public static function _unused2(): VertexData {
return VertexData.Float32_1X;
}
}

View File

@ -0,0 +1,35 @@
package kha.graphics4;
import haxe.io.Bytes;
import kha.Blob;
@:headerCode("
#include <kinc/graphics4/shader.h>
")
@:headerClassCode("kinc_g4_shader_t shader;")
class VertexShader {
public function new(sources: Array<Blob>, files: Array<String>) {
if (sources != null) {
init(sources[0], files[0]);
}
}
function init(source: Blob, file: String): Void {
untyped __cpp__("kinc_g4_shader_init(&shader, source->bytes->b->Pointer(), source->get_length(), KINC_G4_SHADER_TYPE_VERTEX);");
}
public static function fromSource(source: String): VertexShader {
var vertexShader = new VertexShader(null, null);
untyped __cpp__("kinc_g4_shader_init_from_source(&vertexShader->shader, source, KINC_G4_SHADER_TYPE_VERTEX);");
return vertexShader;
}
public function delete(): Void {
untyped __cpp__("kinc_g4_shader_destroy(&shader);");
}
@:keep
function _forceInclude(): Void {
Bytes.alloc(0);
}
}

View File

@ -0,0 +1,17 @@
package kha.graphics5;
#if kha_dxr
@:headerCode('
#include <Kore/Graphics5/RayTrace.h>
')
@:headerClassCode("Kore::Graphics5::AccelerationStructure* accel;")
class AccelerationStructure {
public function new(commandList: CommandList, vb: VertexBuffer, ib: IndexBuffer) {
init(commandList, vb, ib);
}
function init(commandList: CommandList, vb: VertexBuffer, ib: IndexBuffer) {
untyped __cpp__("accel = new Kore::Graphics5::AccelerationStructure(commandList->commandList, vb->buffer, ib->buffer);");
}
}
#end

View File

@ -0,0 +1,71 @@
package kha.graphics5;
@:headerCode('
#include <Kore/Graphics5/CommandList.h>
')
@:headerClassCode("Kore::Graphics5::CommandList* commandList;")
class CommandList {
public function new() {
init();
}
@:functionCode('commandList = new Kore::Graphics5::CommandList();')
private function init(): Void {}
public function begin(): Void {
untyped __cpp__("commandList->begin();");
}
public function end(): Void {
untyped __cpp__("commandList->end();");
}
public function renderTargetToFramebufferBarrier(renderTarget: RenderTarget): Void {
untyped __cpp__("commandList->renderTargetToFramebufferBarrier(renderTarget->renderTarget);");
}
public function framebufferToRenderTargetBarrier(renderTarget: RenderTarget): Void {
untyped __cpp__("commandList->framebufferToRenderTargetBarrier(renderTarget->renderTarget);");
}
public function setRenderTargets(targets: Array<RenderTarget>): Void {
var len = targets.length;
var image1 = targets[0];
var image2 = targets[1];
var image3 = targets[2];
var image4 = targets[3];
var image5 = targets[4];
var image6 = targets[5];
var image7 = targets[6];
untyped __cpp__("Kore::Graphics5::RenderTarget* renderTargets[8] = { image1 == null() ? nullptr : image1->renderTarget, image2 == null() ? nullptr : image2->renderTarget, image3 == null() ? nullptr : image3->renderTarget, image4 == null() ? nullptr : image4->renderTarget, image5 == null() ? nullptr : image5->renderTarget, image6 == null() ? nullptr : image6->renderTarget, image7 == null() ? nullptr : image7->renderTarget }; commandList->setRenderTargets(renderTargets, len);");
}
public function drawIndexedVertices(start: Int = 0, count: Int = -1): Void {
untyped __cpp__("commandList->drawIndexedVertices();");
}
public function setIndexBuffer(indexBuffer: IndexBuffer): Void {
untyped __cpp__("commandList->setIndexBuffer(*indexBuffer->buffer);");
}
public function setVertexBuffers(vertexBuffers: Array<VertexBuffer>, offsets: Array<Int>): Void {
var vb = vertexBuffers[0];
untyped __cpp__("int offs[1] = { 0 }; Kore::Graphics5::VertexBuffer* buffers[1] = { vb->buffer }; commandList->setVertexBuffers(buffers, offs, 1);");
}
public function setPipelineLayout(): Void {
untyped __cpp__("commandList->setPipelineLayout();");
}
public function setPipeline(pipeline: PipelineState): Void {
untyped __cpp__("commandList->setPipeline(pipeline->pipeline);");
}
public function clear(target: RenderTarget, ?color: Color, ?depth: Float, ?stencil: Int): Void {
untyped __cpp__("commandList->clear(target->renderTarget, Kore::Graphics5::ClearColorFlag);");
}
public function upload(indexBuffer: IndexBuffer): Void {
untyped __cpp__("commandList->upload(indexBuffer->buffer);");
}
}

View File

@ -0,0 +1,27 @@
package kha.graphics5;
@:headerCode('
#include <Kore/Graphics5/ConstantBuffer.h>
')
@:headerClassCode("Kore::Graphics5::ConstantBuffer* buffer;")
class ConstantBuffer {
public function new(size: Int) {
init(size);
}
function init(size: Int) {
untyped __cpp__("buffer = new Kore::Graphics5::ConstantBuffer(size)");
}
public function lock(): Void {
untyped __cpp__("buffer->lock()");
}
public function unlock(): Void {
untyped __cpp__("buffer->unlock()");
}
public function setFloat(offset: Int, value: FastFloat): Void {
untyped __cpp__("buffer->setFloat(offset, value)");
}
}

View File

@ -0,0 +1,35 @@
package kha.graphics5;
import haxe.io.Bytes;
import kha.Blob;
@:headerCode('
#include <Kore/Graphics5/Graphics.h>
')
@:headerClassCode("Kore::Graphics5::Shader* shader;")
class FragmentShader {
public function new(sources: Array<Blob>, files: Array<String>) {
if (sources != null) {
init(sources[0], files[0]);
}
}
private function init(source: Blob, file: String): Void {
untyped __cpp__('shader = new Kore::Graphics5::Shader(source->bytes->b->Pointer(), source->get_length(), Kore::Graphics5::FragmentShader);');
}
// public static function fromSource(source: String): FragmentShader {
// var fragmentShader = new FragmentShader(null, null);
// untyped __cpp__('fragmentShader->shader = new Kore::Graphics5::Shader(source, Kore::Graphics5::FragmentShader);');
// return fragmentShader;
// }
public function delete(): Void {
untyped __cpp__('delete shader; shader = nullptr;');
}
@:keep
function _forceInclude(): Void {
Bytes.alloc(0);
}
}

View File

@ -0,0 +1,46 @@
package kha.graphics5;
import kha.arrays.Uint32Array;
@:headerCode('
#include <Kore/Graphics5/Graphics.h>
')
@:headerClassCode("Kore::Graphics5::IndexBuffer* buffer;")
class IndexBuffer {
private var data: Uint32Array;
private var myCount: Int;
public function new(indexCount: Int, usage: Usage, canRead: Bool = false) {
myCount = indexCount;
data = new Uint32Array();
untyped __cpp__('buffer = new Kore::Graphics5::IndexBuffer(indexCount, true);');
}
public function delete(): Void {
untyped __cpp__('delete buffer; buffer = nullptr;');
}
@:functionCode('
data->self.data = (unsigned int*)buffer->lock() + start;
data->self.myLength = count;
return data;
')
private function lock2(start: Int, count: Int): Uint32Array {
return data;
}
public function lock(?start: Int, ?count: Int): Uint32Array {
if (start == null)
start = 0;
if (count == null)
count = this.count();
return lock2(start, count);
}
@:functionCode('buffer->unlock();')
public function unlock(): Void {}
public function count(): Int {
return myCount;
}
}

View File

@ -0,0 +1,277 @@
package kha.graphics5;
import kha.graphics5.FragmentShader;
import kha.graphics5.VertexData;
import kha.graphics5.VertexElement;
import kha.graphics5.VertexShader;
import kha.graphics5.VertexStructure;
@:headerCode('
#include <Kore/Graphics5/Graphics.h>
#include <Kore/Graphics5/PipelineState.h>
')
@:cppFileCode('
static Kore::Graphics5::ZCompareMode convertCompareMode(int mode) {
switch (mode) {
case 0:
return Kore::Graphics5::ZCompareAlways;
case 1:
return Kore::Graphics5::ZCompareNever;
case 2:
return Kore::Graphics5::ZCompareEqual;
case 3:
return Kore::Graphics5::ZCompareNotEqual;
case 4:
return Kore::Graphics5::ZCompareLess;
case 5:
return Kore::Graphics5::ZCompareLessEqual;
case 6:
return Kore::Graphics5::ZCompareGreater;
case 7:
default:
return Kore::Graphics5::ZCompareGreaterEqual;
}
}
static Kore::Graphics5::StencilAction convertStencilAction(int action) {
switch (action) {
case 0:
return Kore::Graphics5::Keep;
case 1:
return Kore::Graphics5::Zero;
case 2:
return Kore::Graphics5::Replace;
case 3:
return Kore::Graphics5::Increment;
case 4:
return Kore::Graphics5::IncrementWrap;
case 5:
return Kore::Graphics5::Decrement;
case 6:
return Kore::Graphics5::DecrementWrap;
case 7:
default:
return Kore::Graphics5::Invert;
}
}
')
@:headerClassCode("Kore::Graphics5::PipelineState* pipeline;")
@:keep
class PipelineState extends PipelineStateBase {
public function new() {
super();
untyped __cpp__('pipeline = new Kore::Graphics5::PipelineState;');
}
public function delete(): Void {
untyped __cpp__('delete pipeline; pipeline = nullptr;');
}
@:functionCode('
pipeline->vertexShader = vertexShader->shader;
pipeline->fragmentShader = fragmentShader->shader;
// if (geometryShader != null()) pipeline->geometryShader = geometryShader->shader;
// if (tessellationControlShader != null()) pipeline->tessellationControlShader = tessellationControlShader->shader;
// if (tessellationEvaluationShader != null()) pipeline->tessellationEvaluationShader = tessellationEvaluationShader->shader;
Kore::Graphics4::VertexStructure s0, s1, s2, s3;
Kore::Graphics4::VertexStructure* structures2[4] = { &s0, &s1, &s2, &s3 };
::kha::graphics4::VertexStructure* structures[4] = { &structure0, &structure1, &structure2, &structure3 };
for (int i1 = 0; i1 < size; ++i1) {
structures2[i1]->instanced = (*structures[i1])->instanced;
for (int i2 = 0; i2 < (*structures[i1])->size(); ++i2) {
Kore::Graphics4::VertexData data;
switch ((*structures[i1])->get(i2)->data) {
case 0:
data = Kore::Graphics4::Float1VertexData;
break;
case 1:
data = Kore::Graphics4::Float2VertexData;
break;
case 2:
data = Kore::Graphics4::Float3VertexData;
break;
case 3:
data = Kore::Graphics4::Float4VertexData;
break;
case 4:
data = Kore::Graphics4::Float4x4VertexData;
break;
case 5:
data = Kore::Graphics4::Short2NormVertexData;
break;
case 6:
data = Kore::Graphics4::Short4NormVertexData;
break;
}
pipeline->inputLayout[i1] = structures2[i1];
pipeline->inputLayout[i1]->add((*structures[i1])->get(i2)->name, data);
}
}
for (int i = size; i < 16; ++i) {
pipeline->inputLayout[i] = nullptr;
}
pipeline->compile();
')
private function linkWithStructures2(structure0: VertexStructure, structure1: VertexStructure, structure2: VertexStructure, structure3: VertexStructure,
size: Int): Void {}
public function compile(): Void {
setStates(cullMode, depthMode, stencilMode, stencilBothPass, stencilDepthFail, stencilFail, getBlendFunc(blendSource), getBlendFunc(blendDestination),
getBlendFunc(alphaBlendSource), getBlendFunc(alphaBlendDestination));
linkWithStructures2(inputLayout.length > 0 ? inputLayout[0] : null, inputLayout.length > 1 ? inputLayout[1] : null,
inputLayout.length > 2 ? inputLayout[2] : null, inputLayout.length > 3 ? inputLayout[3] : null, inputLayout.length);
}
public function getConstantLocation(name: String): kha.graphics4.ConstantLocation {
var location = new kha.kore.graphics4.ConstantLocation();
initConstantLocation(location, name);
return location;
}
// @:functionCode('location->location = pipeline->getConstantLocation(name.c_str());')
private function initConstantLocation(location: kha.kore.graphics4.ConstantLocation, name: String): Void {}
public function getTextureUnit(name: String): kha.graphics4.TextureUnit {
var unit = new kha.kore.graphics4.TextureUnit();
initTextureUnit(unit, name);
return unit;
}
// @:functionCode('unit->unit = pipeline->getTextureUnit(name.c_str());')
private function initTextureUnit(unit: kha.kore.graphics4.TextureUnit, name: String): Void {}
private static function getBlendFunc(factor: BlendingFactor): Int {
switch (factor) {
case BlendOne, Undefined:
return 0;
case BlendZero:
return 1;
case SourceAlpha:
return 2;
case DestinationAlpha:
return 3;
case InverseSourceAlpha:
return 4;
case InverseDestinationAlpha:
return 5;
case SourceColor:
return 6;
case DestinationColor:
return 7;
case InverseSourceColor:
return 8;
case InverseDestinationColor:
return 9;
default:
return 0;
}
}
@:functionCode('
switch (cullMode) {
case 0:
pipeline->cullMode = Kore::Graphics5::Clockwise;
break;
case 1:
pipeline->cullMode = Kore::Graphics5::CounterClockwise;
break;
case 2:
pipeline->cullMode = Kore::Graphics5::NoCulling;
break;
}
switch (depthMode) {
case 0:
pipeline->depthMode = Kore::Graphics5::ZCompareAlways;
break;
case 1:
pipeline->depthMode = Kore::Graphics5::ZCompareNever;
break;
case 2:
pipeline->depthMode = Kore::Graphics5::ZCompareEqual;
break;
case 3:
pipeline->depthMode = Kore::Graphics5::ZCompareNotEqual;
break;
case 4:
pipeline->depthMode = Kore::Graphics5::ZCompareLess;
break;
case 5:
pipeline->depthMode = Kore::Graphics5::ZCompareLessEqual;
break;
case 6:
pipeline->depthMode = Kore::Graphics5::ZCompareGreater;
break;
case 7:
pipeline->depthMode = Kore::Graphics5::ZCompareGreaterEqual;
break;
}
pipeline->depthWrite = depthWrite;
pipeline->stencilMode = convertCompareMode(stencilMode);
pipeline->stencilBothPass = convertStencilAction(stencilBothPass);
pipeline->stencilDepthFail = convertStencilAction(stencilDepthFail);
pipeline->stencilFail = convertStencilAction(stencilFail);
pipeline->stencilReferenceValue = stencilReferenceValue;
pipeline->stencilReadMask = stencilReadMask;
pipeline->stencilWriteMask = stencilWriteMask;
pipeline->blendSource = (Kore::Graphics5::BlendingOperation)blendSource;
pipeline->blendDestination = (Kore::Graphics5::BlendingOperation)blendDestination;
pipeline->alphaBlendSource = (Kore::Graphics5::BlendingOperation)alphaBlendSource;
pipeline->alphaBlendDestination = (Kore::Graphics5::BlendingOperation)alphaBlendDestination;
for (int i = 0; i < 8; ++i) {
pipeline->colorWriteMaskRed[i] = colorWriteMasksRed[i];
pipeline->colorWriteMaskGreen[i] = colorWriteMasksGreen[i];
pipeline->colorWriteMaskBlue[i] = colorWriteMasksBlue[i];
pipeline->colorWriteMaskAlpha[i] = colorWriteMasksAlpha[i];
}
pipeline->conservativeRasterization = conservativeRasterization;
')
private function setStates(cullMode: Int, depthMode: Int, stencilMode: Int, stencilBothPass: Int, stencilDepthFail: Int, stencilFail: Int,
blendSource: Int, blendDestination: Int, alphaBlendSource: Int, alphaBlendDestination: Int): Void {}
// @:functionCode('Kore::Graphics4::setPipeline(pipeline);')
// private function set2(): Void {
// }
// public function set(): Void {
// set2();
// }
@:noCompletion
public static function _unused1(): VertexElement {
return null;
}
@:noCompletion
public static function _unused2(): VertexData {
return Float1;
}
@:noCompletion
public static function _unused3(): VertexShader {
return null;
}
@:noCompletion
public static function _unused4(): FragmentShader {
return null;
}
@:noCompletion
public static function _unused5(): GeometryShader {
return null;
}
@:noCompletion
public static function _unused6(): TessellationControlShader {
return null;
}
@:noCompletion
public static function _unused7(): TessellationEvaluationShader {
return null;
}
}

View File

@ -0,0 +1,18 @@
package kha.graphics5;
#if kha_dxr
@:headerCode('
#include <Kore/Graphics5/RayTrace.h>
')
@:headerClassCode("Kore::Graphics5::RayTracePipeline* pipeline;")
class RayTracePipeline {
public function new(commandList: CommandList, rayTraceShader: kha.Blob, constantBuffer: ConstantBuffer) {
untyped __cpp__("pipeline = new Kore::Graphics5::RayTracePipeline(commandList->commandList, rayTraceShader->bytes->b->Pointer(), rayTraceShader->get_length(), constantBuffer->buffer);");
}
@:keep
function _forceInclude(): Void {
haxe.io.Bytes.alloc(0);
}
}
#end

View File

@ -0,0 +1,17 @@
package kha.graphics5;
#if kha_dxr
@:headerCode('
#include <Kore/Graphics5/RayTrace.h>
')
@:headerClassCode("Kore::Graphics5::RayTraceTarget* target;")
class RayTraceTarget {
public function new(width: Int, height: Int) {
init(width, height);
}
function init(width: Int, height: Int) {
untyped __cpp__("target = new Kore::Graphics5::RayTraceTarget(width, height);");
}
}
#end

View File

@ -0,0 +1,35 @@
package kha.graphics5;
@:headerCode('
#include <Kore/Graphics5/Graphics.h>
')
@:headerClassCode("Kore::Graphics5::RenderTarget* renderTarget;")
class RenderTarget {
public function new(width: Int, height: Int, depthBufferBits: Int, antialiasing: Bool, format: TextureFormat, stencilBufferBits: Int, contextId: Int) {
init(width, height, depthBufferBits, antialiasing, getRenderTargetFormat(format), stencilBufferBits, contextId);
}
@:functionCode('renderTarget = new Kore::Graphics5::RenderTarget(width, height, depthBufferBits, antialiasing, (Kore::Graphics5::RenderTargetFormat)format, stencilBufferBits, contextId);')
private function init(width: Int, height: Int, depthBufferBits: Int, antialiasing: Bool, format: Int, stencilBufferBits: Int, contextId: Int): Void {}
private static function getRenderTargetFormat(format: TextureFormat): Int {
switch (format) {
case RGBA32: // Target32Bit
return 0;
case RGBA64: // Target64BitFloat
return 1;
case A32: // Target32BitRedFloat
return 2;
case RGBA128: // Target128BitFloat
return 3;
case DEPTH16: // Target16BitDepth
return 4;
case L8:
return 5; // Target8BitRed
case A16:
return 6; // Target16BitRedFloat
default:
return 0;
}
}
}

View File

@ -0,0 +1,92 @@
package kha.graphics5;
import kha.arrays.Float32Array;
import kha.graphics5.VertexData;
import kha.graphics5.VertexElement;
import kha.graphics5.VertexStructure;
@:headerCode('
#include <Kore/Graphics5/Graphics.h>
')
@:headerClassCode("Kore::Graphics5::VertexBuffer* buffer;")
class VertexBuffer {
private var data: Float32Array;
public function new(vertexCount: Int, structure: VertexStructure, usage: Usage, instanceDataStepRate: Int = 0, canRead: Bool = false) {
init(vertexCount, structure, usage, instanceDataStepRate);
data = new Float32Array();
}
public function delete(): Void {
untyped __cpp__('delete buffer; buffer = nullptr;');
}
@:functionCode("
Kore::Graphics4::VertexStructure structure2;
for (int i = 0; i < structure->size(); ++i) {
Kore::Graphics4::VertexData data;
switch (structure->get(i)->data) {
case 0:
data = Kore::Graphics4::Float1VertexData;
break;
case 1:
data = Kore::Graphics4::Float2VertexData;
break;
case 2:
data = Kore::Graphics4::Float3VertexData;
break;
case 3:
data = Kore::Graphics4::Float4VertexData;
break;
case 4:
data = Kore::Graphics4::Float4x4VertexData;
break;
}
structure2.add(structure->get(i)->name, data);
}
buffer = new Kore::Graphics5::VertexBuffer(vertexCount, structure2, false);
")
private function init(vertexCount: Int, structure: VertexStructure, usage: Int, instanceDataStepRate: Int) {}
@:functionCode('
data->self.data = buffer->lock() + start * buffer->stride() / 4;
data->self.myLength = count * buffer->stride() / 4;
return data;
')
private function lock2(start: Int, count: Int): Float32Array {
return data;
}
public function lock(?start: Int, ?count: Int): Float32Array {
if (start == null)
start = 0;
if (count == null)
count = this.count();
return lock2(start, count);
}
@:functionCode('buffer->unlock();')
public function unlock(): Void {}
@:functionCode("return buffer->stride();")
public function stride(): Int {
return 0;
}
@:functionCode("return buffer->count();")
public function count(): Int {
return 0;
}
@:noCompletion
@:keep
public static function _unused1(): VertexElement {
return null;
}
@:noCompletion
@:keep
public static function _unused2(): VertexData {
return Float1;
}
}

View File

@ -0,0 +1,35 @@
package kha.graphics5;
import haxe.io.Bytes;
import kha.Blob;
@:headerCode('
#include <Kore/Graphics5/Graphics.h>
')
@:headerClassCode("Kore::Graphics5::Shader* shader;")
class VertexShader {
public function new(sources: Array<Blob>, files: Array<String>) {
if (sources != null) {
init(sources[0], files[0]);
}
}
private function init(source: Blob, file: String): Void {
untyped __cpp__('shader = new Kore::Graphics5::Shader(source->bytes->b->Pointer(), source->get_length(), Kore::Graphics5::VertexShader);');
}
// public static function fromSource(source: String): VertexShader {
// var vertexShader = new VertexShader(null, null);
// untyped __cpp__('vertexShader->shader = new Kore::Graphics5::Shader(source, Kore::Graphics5::VertexShader);');
// return vertexShader;
// }
public function delete(): Void {
untyped __cpp__('delete shader; shader = nullptr;');
}
@:keep
function _forceInclude(): Void {
Bytes.alloc(0);
}
}

View File

@ -0,0 +1,46 @@
package kha.input;
import kha.SystemImpl;
import kha.input.Mouse;
class MouseImpl extends kha.input.Mouse {
public function new() {
super();
}
override public function lock(): Void {
SystemImpl.lockMouse();
}
override public function unlock(): Void {
SystemImpl.unlockMouse();
}
override public function canLock(): Bool {
return SystemImpl.canLockMouse();
}
override public function isLocked(): Bool {
return SystemImpl.isMouseLocked();
}
override public function notifyOnLockChange(func: Void->Void, error: Void->Void): Void {
SystemImpl.notifyOfMouseLockChange(func, error);
}
override public function removeFromLockChange(func: Void->Void, error: Void->Void): Void {
SystemImpl.removeFromMouseLockChange(func, error);
}
override public function hideSystemCursor(): Void {
SystemImpl.hideSystemCursor();
}
override public function showSystemCursor(): Void {
SystemImpl.showSystemCursor();
}
override public function setSystemCursor(cursor: MouseCursor): Void {
SystemImpl.setSystemCursor(cursor.getIndex());
}
}

View File

@ -0,0 +1,31 @@
package kha.input;
@:keep
class Sensor {
static var accelerometer: Sensor = new Sensor();
static var gyroscope: Sensor = new Sensor();
var listeners: Array<Float->Float->Float->Void> = new Array();
public static function get(type: SensorType): Sensor {
switch (type) {
case Accelerometer:
return accelerometer;
case Gyroscope:
return gyroscope;
}
}
public function notify(listener: Float->Float->Float->Void): Void {
listeners.push(listener);
}
function new() {}
public static function _changed(type: Int, x: Float, y: Float, z: Float): Void {
var sensor = get(type == 0 ? SensorType.Accelerometer : SensorType.Gyroscope);
for (listener in sensor.listeners) {
listener(x, y, z);
}
}
}

View File

@ -0,0 +1,17 @@
package kha.kore;
@:headerCode("
#include <kinc/input/keyboard.h>
")
@:allow(kha.SystemImpl)
class Keyboard extends kha.input.Keyboard {
function new() {
super();
}
@:functionCode("kinc_keyboard_show();")
override public function show(): Void {}
@:functionCode("kinc_keyboard_hide();")
override public function hide(): Void {}
}

View File

@ -0,0 +1,62 @@
package kha.kore;
@:headerCode("
#include <kinc/video.h>
")
@:headerClassCode("kinc_video_t video;")
class Video extends kha.Video {
public function new(filename: String) {
super();
init(filename);
}
@:functionCode("kinc_video_init(&video, filename.c_str());")
function init(filename: String) {}
@:functionCode("kinc_video_play(&video, loop);")
override public function play(loop: Bool = false): Void {}
@:functionCode("kinc_video_pause(&video);")
override public function pause(): Void {}
@:functionCode("kinc_video_stop(&video);")
override public function stop(): Void {}
override function update(time: Float) {
untyped __cpp__('kinc_video_update(&video, time)');
}
// @:functionCode("return static_cast<int>(video->duration * 1000.0);")
override public function getLength(): Int { // Miliseconds
return 0;
}
// @:functionCode("return static_cast<int>(video->position * 1000.0);")
override public function getCurrentPos(): Int { // Miliseconds
return 0;
}
override function get_position(): Int {
return getCurrentPos();
}
// @:functionCode("video->update(value / 1000.0); return value;")
override function set_position(value: Int): Int {
return 0;
}
override public function isFinished(): Bool {
return untyped __cpp__("kinc_video_finished(&video)");
}
override public function width(): Int {
return untyped __cpp__("kinc_video_width(&video)");
}
override public function height(): Int {
return untyped __cpp__("kinc_video_height(&video)");
}
@:functionCode("kinc_video_destroy(&video);")
override public function unload(): Void {}
}

View File

@ -0,0 +1,9 @@
package kha.kore.graphics4;
@:headerCode("
#include <kinc/graphics4/constantlocation.h>
")
@:headerClassCode("kinc_g4_constant_location_t location;")
class ConstantLocation implements kha.graphics4.ConstantLocation {
public function new() {}
}

View File

@ -0,0 +1,503 @@
package kha.kore.graphics4;
import kha.arrays.Float32Array;
import kha.Blob;
import kha.Canvas;
import kha.Color;
import kha.graphics4.CubeMap;
import kha.graphics4.CullMode;
import kha.graphics4.FragmentShader;
import kha.graphics4.BlendingFactor;
import kha.graphics4.BlendingOperation;
import kha.graphics4.CompareMode;
import kha.graphics4.MipMapFilter;
import kha.graphics4.PipelineState;
import kha.graphics4.StencilAction;
import kha.graphics4.TexDir;
import kha.graphics4.TextureAddressing;
import kha.graphics4.TextureFilter;
import kha.graphics4.TextureFormat;
import kha.graphics4.Usage;
import kha.graphics4.VertexBuffer;
import kha.graphics4.VertexShader;
import kha.graphics4.VertexStructure;
import kha.Image;
import kha.math.FastMatrix3;
import kha.math.FastMatrix4;
import kha.math.FastVector2;
import kha.math.FastVector3;
import kha.math.FastVector4;
import kha.math.Matrix4;
import kha.math.Vector2;
import kha.math.Vector3;
import kha.math.Vector4;
import kha.Video;
@:headerCode("
#include <kinc/display.h>
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/rendertarget.h>
#include <kinc/window.h>
")
@:headerClassCode("kinc_g4_render_target_t *renderTarget = nullptr;")
class Graphics implements kha.graphics4.Graphics {
var target: Canvas;
public var window: Null<Int>;
public static var lastWindow: Int = -1;
static var current: Graphics = null;
public function new(target: Canvas = null) {
this.target = target;
init();
}
function init() {
if (target == null)
return;
if (Std.isOfType(target, CubeMap)) {
var cubeMap = cast(target, CubeMap);
untyped __cpp__("renderTarget = &{0}->renderTarget", cubeMap);
}
else {
var image = cast(target, Image);
untyped __cpp__("renderTarget = &{0}->renderTarget", image);
}
}
@:functionCode("return kinc_window_vsynced(0);")
public function vsynced(): Bool {
return true;
}
@:functionCode("return kinc_display_current_mode(kinc_primary_display()).frequency;")
public function refreshRate(): Int {
return 0;
}
public function clear(?color: Color, ?z: Float, ?stencil: Int): Void {
var flags: Int = 0;
if (color != null)
flags |= 1;
if (z != null)
flags |= 2;
if (stencil != null)
flags |= 4;
clear2(flags, color == null ? 0 : color.value, z, stencil);
}
@:functionCode("kinc_g4_viewport(x, y, width, height);")
public function viewport(x: Int, y: Int, width: Int, height: Int): Void {}
@:functionCode("kinc_g4_clear(flags, color, z, stencil);")
function clear2(flags: Int, color: Int, z: Float, stencil: Int): Void {}
// public function createVertexBuffer(vertexCount: Int, structure: VertexStructure, usage: Usage, canRead: Bool = false): kha.graphics4.VertexBuffer {
// return new VertexBuffer(vertexCount, structure);
// }
@:functionCode("kinc_g4_set_vertex_buffer(&vertexBuffer->buffer);")
public function setVertexBuffer(vertexBuffer: kha.graphics4.VertexBuffer): Void {}
@:functionCode("
kinc_g4_vertex_buffer_t* vertexBuffers[4] = {
vb0 == null() ? nullptr : &vb0->buffer,
vb1 == null() ? nullptr : &vb1->buffer,
vb2 == null() ? nullptr : &vb2->buffer,
vb3 == null() ? nullptr : &vb3->buffer
};
kinc_g4_set_vertex_buffers(vertexBuffers, count);
")
function setVertexBuffersInternal(vb0: VertexBuffer, vb1: VertexBuffer, vb2: VertexBuffer, vb3: VertexBuffer, count: Int): Void {}
public function setVertexBuffers(vertexBuffers: Array<kha.graphics4.VertexBuffer>): Void {
setVertexBuffersInternal(vertexBuffers.length > 0 ? vertexBuffers[0] : null, vertexBuffers.length > 1 ? vertexBuffers[1] : null,
vertexBuffers.length > 2 ? vertexBuffers[2] : null, vertexBuffers.length > 3 ? vertexBuffers[3] : null, vertexBuffers.length);
}
// public function createIndexBuffer(indexCount: Int, usage: Usage, canRead: Bool = false): kha.graphics.IndexBuffer {
// return new IndexBuffer(indexCount);
// }
@:functionCode("kinc_g4_set_index_buffer(&indexBuffer->buffer);")
public function setIndexBuffer(indexBuffer: kha.graphics4.IndexBuffer): Void {}
// public function createTexture(width: Int, height: Int, format: TextureFormat, usage: Usage, canRead: Bool = false, levels: Int = 1): Texture {
// return Image.create(width, height, format, canRead, false, false);
// }
// public function createRenderTargetTexture(width: Int, height: Int, format: TextureFormat, depthStencil: Bool, antiAliasingSamples: Int = 1): Texture {
// return Image.create(width, height, format, false, true, depthStencil);
// }
public function maxTextureSize(): Int {
return 4096;
}
public function supportsNonPow2Textures(): Bool {
return false;
}
public function setCubeMap(unit: kha.graphics4.TextureUnit, cubeMap: kha.graphics4.CubeMap): Void {
if (cubeMap == null)
return;
var koreUnit = cast(unit, kha.kore.graphics4.TextureUnit);
untyped __cpp__("kinc_g4_render_target_use_color_as_texture(&cubeMap->renderTarget, {0}->unit)", koreUnit);
}
public function setCubeMapDepth(unit: kha.graphics4.TextureUnit, cubeMap: kha.graphics4.CubeMap): Void {
if (cubeMap == null)
return;
var koreUnit = cast(unit, kha.kore.graphics4.TextureUnit);
untyped __cpp__("kinc_g4_render_target_use_depth_as_texture(&cubeMap->renderTarget, {0}->unit);", koreUnit);
}
@:functionCode("kinc_g4_scissor(x, y, width, height);")
public function scissor(x: Int, y: Int, width: Int, height: Int): Void {}
@:functionCode("kinc_g4_disable_scissor();")
public function disableScissor(): Void {}
public function instancedRenderingAvailable(): Bool {
return true;
}
@:functionCode("
kinc_g4_set_texture_addressing(unit->unit, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)uWrap);
kinc_g4_set_texture_addressing(unit->unit, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)vWrap);
")
function setTextureWrapNative(unit: TextureUnit, uWrap: Int, vWrap: Int): Void {}
@:functionCode("
kinc_g4_set_texture3d_addressing(unit->unit, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)uWrap);
kinc_g4_set_texture3d_addressing(unit->unit, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)vWrap);
kinc_g4_set_texture3d_addressing(unit->unit, KINC_G4_TEXTURE_DIRECTION_W, (kinc_g4_texture_addressing_t)wWrap);
")
function setTexture3DWrapNative(unit: TextureUnit, uWrap: Int, vWrap: Int, wWrap: Int): Void {}
@:functionCode("
kinc_g4_set_texture_minification_filter(unit->unit, (kinc_g4_texture_filter_t)minificationFilter);
kinc_g4_set_texture_magnification_filter(unit->unit, (kinc_g4_texture_filter_t)magnificationFilter);
kinc_g4_set_texture_mipmap_filter(unit->unit, (kinc_g4_mipmap_filter_t)mipMapFilter);
")
function setTextureFiltersNative(unit: TextureUnit, minificationFilter: Int, magnificationFilter: Int, mipMapFilter: Int): Void {}
@:functionCode("
kinc_g4_set_texture3d_minification_filter(unit->unit, (kinc_g4_texture_filter_t)minificationFilter);
kinc_g4_set_texture3d_magnification_filter(unit->unit, (kinc_g4_texture_filter_t)magnificationFilter);
kinc_g4_set_texture3d_mipmap_filter(unit->unit, (kinc_g4_mipmap_filter_t)mipMapFilter);
")
function setTexture3DFiltersNative(unit: TextureUnit, minificationFilter: Int, magnificationFilter: Int, mipMapFilter: Int): Void {}
public function setTextureParameters(texunit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing,
minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void {
setTextureWrapNative(cast texunit, uAddressing, vAddressing);
setTextureFiltersNative(cast texunit, minificationFilter, magnificationFilter, mipmapFilter);
}
public function setTexture3DParameters(texunit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing,
wAddressing: TextureAddressing, minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void {
setTexture3DWrapNative(cast texunit, uAddressing, vAddressing, wAddressing);
setTexture3DFiltersNative(cast texunit, minificationFilter, magnificationFilter, mipmapFilter);
}
public function setTextureCompareMode(texunit: kha.graphics4.TextureUnit, enabled: Bool) {
var koreUnit = cast(texunit, kha.kore.graphics4.TextureUnit);
untyped __cpp__("kinc_g4_set_texture_compare_mode({0}->unit, enabled);", koreUnit);
}
public function setCubeMapCompareMode(texunit: kha.graphics4.TextureUnit, enabled: Bool) {
var koreUnit = cast(texunit, kha.kore.graphics4.TextureUnit);
untyped __cpp__("kinc_g4_set_cubemap_compare_mode({0}->unit, enabled);", koreUnit);
}
@:functionCode("
if (texture->imageType == KhaImageTypeTexture) kinc_g4_set_texture(unit->unit, &texture->texture);
else if (texture->imageType == KhaImageTypeRenderTarget) kinc_g4_render_target_use_color_as_texture(&texture->renderTarget, unit->unit);
")
function setTextureInternal(unit: kha.kore.graphics4.TextureUnit, texture: kha.Image): Void {}
public function setTexture(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
if (texture == null)
return;
setTextureInternal(cast unit, texture);
}
public function setTextureDepth(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
if (texture == null)
return;
var koreUnit = cast(unit, kha.kore.graphics4.TextureUnit);
untyped __cpp__("kinc_g4_render_target_use_depth_as_texture(&texture->renderTarget, {0}->unit);", koreUnit);
}
public function setTextureArray(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
if (texture == null)
return;
var koreUnit = cast(unit, kha.kore.graphics4.TextureUnit);
untyped __cpp__("if (texture->imageType == KhaImageTypeTextureArray) kinc_g4_set_texture_array({0}->unit, &texture->textureArray);", koreUnit);
}
public function setVideoTexture(unit: kha.graphics4.TextureUnit, texture: kha.Video): Void {
if (texture == null)
return;
setTextureInternal(cast unit, Image.fromVideo(texture));
}
@:functionCode("kinc_g4_set_image_texture(unit->unit, &texture->texture);")
function setImageTextureInternal(unit: kha.kore.graphics4.TextureUnit, texture: kha.Image): Void {}
public function setImageTexture(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
if (texture == null)
return;
setImageTextureInternal(cast unit, texture);
}
@:functionCode("return kinc_g4_max_bound_textures();")
public function maxBoundTextures(): Int {
return 0;
}
// public function createVertexShader(source: Blob): VertexShader {
// return new Shader(source, ShaderType.VertexShader);
// }
// public function createFragmentShader(source: Blob): FragmentShader {
// return new Shader(source, ShaderType.FragmentShader);
// }
// public function createProgram(): kha.graphics4.Program {
// return new Program();
// }
public function setPipeline(pipe: PipelineState): Void {
pipe.set();
}
@:functionCode("kinc_g4_set_stencil_reference_value(value);")
public function setStencilReferenceValue(value: Int): Void {}
public function setBool(location: kha.graphics4.ConstantLocation, value: Bool): Void {
setBoolPrivate(cast location, value);
}
@:functionCode("kinc_g4_set_bool(location->location, value);")
function setBoolPrivate(location: kha.kore.graphics4.ConstantLocation, value: Bool): Void {}
public function setInt(location: kha.graphics4.ConstantLocation, value: Int): Void {
setIntPrivate(cast location, value);
}
@:functionCode("kinc_g4_set_int(location->location, value);")
function setIntPrivate(location: ConstantLocation, value: Int): Void {}
public function setInt2(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int): Void {
setInt2Private(cast location, value1, value2);
}
@:functionCode("kinc_g4_set_int2(location->location, value1, value2);")
function setInt2Private(location: ConstantLocation, value1: Int, value2: Int): Void {}
public function setInt3(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int, value3: Int): Void {
setInt3Private(cast location, value1, value2, value3);
}
@:functionCode("kinc_g4_set_int3(location->location, value1, value2, value3);")
function setInt3Private(location: ConstantLocation, value1: Int, value2: Int, value3: Int): Void {}
public function setInt4(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int, value3: Int, value4: Int): Void {
setInt4Private(cast location, value1, value2, value3, value4);
}
@:functionCode("kinc_g4_set_int4(location->location, value1, value2, value3, value4);")
function setInt4Private(location: ConstantLocation, value1: Int, value2: Int, value3: Int, value4: Int): Void {}
public function setInts(location: kha.graphics4.ConstantLocation, values: kha.arrays.Int32Array): Void {
setIntsPrivate(cast location, values);
}
@:functionCode("kinc_g4_set_ints(location->location, (int*)values->self.data, values->byteArrayLength / 4);")
function setIntsPrivate(location: ConstantLocation, values: kha.arrays.Int32Array): Void {}
public function setFloat(location: kha.graphics4.ConstantLocation, value: FastFloat): Void {
setFloatPrivate(cast location, value);
}
@:functionCode("kinc_g4_set_float(location->location, value);")
function setFloatPrivate(location: ConstantLocation, value: FastFloat): Void {}
public function setFloat2(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat): Void {
setFloat2Private(cast location, value1, value2);
}
@:functionCode("kinc_g4_set_float2(location->location, value1, value2);")
function setFloat2Private(location: ConstantLocation, value1: FastFloat, value2: FastFloat): Void {}
public function setFloat3(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat): Void {
setFloat3Private(cast location, value1, value2, value3);
}
@:functionCode("kinc_g4_set_float3(location->location, value1, value2, value3);")
function setFloat3Private(location: ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat): Void {}
public function setFloat4(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat, value4: FastFloat): Void {
setFloat4Private(cast location, value1, value2, value3, value4);
}
@:functionCode("kinc_g4_set_float4(location->location, value1, value2, value3, value4);")
function setFloat4Private(location: ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat, value4: FastFloat): Void {}
public function setVector2(location: kha.graphics4.ConstantLocation, value: FastVector2): Void {
setVector2Private(cast location, value.x, value.y);
}
@:functionCode("kinc_g4_set_float2(location->location, x, y);")
function setVector2Private(location: ConstantLocation, x: FastFloat, y: FastFloat): Void {}
public function setVector3(location: kha.graphics4.ConstantLocation, value: FastVector3): Void {
setVector3Private(cast location, value.x, value.y, value.z);
}
@:functionCode("kinc_g4_set_float3(location->location, x, y, z);")
function setVector3Private(location: ConstantLocation, x: FastFloat, y: FastFloat, z: FastFloat): Void {}
public function setVector4(location: kha.graphics4.ConstantLocation, value: FastVector4): Void {
setVector4Private(cast location, value.x, value.y, value.z, value.w);
}
@:functionCode("kinc_g4_set_float4(location->location, x, y, z, w);")
function setVector4Private(location: ConstantLocation, x: FastFloat, y: FastFloat, z: FastFloat, w: FastFloat): Void {}
public function setFloats(location: kha.graphics4.ConstantLocation, values: Float32Array): Void {
setFloatsPrivate(cast location, values);
}
@:functionCode("kinc_g4_set_floats(location->location, (float*)values->self.data, values->byteArrayLength / 4);")
function setFloatsPrivate(location: ConstantLocation, values: Float32Array): Void {}
public function setMatrix(location: kha.graphics4.ConstantLocation, matrix: FastMatrix4): Void {
setMatrixPrivate(cast location, matrix);
}
@:functionCode("
kinc_matrix4x4_t value;
kinc_matrix4x4_set(&value, 0, 0, matrix->_00); kinc_matrix4x4_set(&value, 1, 0, matrix->_10); kinc_matrix4x4_set(&value, 2, 0, matrix->_20); kinc_matrix4x4_set(&value, 3, 0, matrix->_30);
kinc_matrix4x4_set(&value, 0, 1, matrix->_01); kinc_matrix4x4_set(&value, 1, 1, matrix->_11); kinc_matrix4x4_set(&value, 2, 1, matrix->_21); kinc_matrix4x4_set(&value, 3, 1, matrix->_31);
kinc_matrix4x4_set(&value, 0, 2, matrix->_02); kinc_matrix4x4_set(&value, 1, 2, matrix->_12); kinc_matrix4x4_set(&value, 2, 2, matrix->_22); kinc_matrix4x4_set(&value, 3, 2, matrix->_32);
kinc_matrix4x4_set(&value, 0, 3, matrix->_03); kinc_matrix4x4_set(&value, 1, 3, matrix->_13); kinc_matrix4x4_set(&value, 2, 3, matrix->_23); kinc_matrix4x4_set(&value, 3, 3, matrix->_33);
kinc_g4_set_matrix4(location->location, &value);
")
function setMatrixPrivate(location: ConstantLocation, matrix: FastMatrix4): Void {}
public function setMatrix3(location: kha.graphics4.ConstantLocation, matrix: FastMatrix3): Void {
setMatrix3Private(cast location, matrix);
}
@:functionCode("
kinc_matrix3x3_t value;
kinc_matrix3x3_set(&value, 0, 0, matrix->_00); kinc_matrix3x3_set(&value, 1, 0, matrix->_10); kinc_matrix3x3_set(&value, 2, 0, matrix->_20);
kinc_matrix3x3_set(&value, 0, 1, matrix->_01); kinc_matrix3x3_set(&value, 1, 1, matrix->_11); kinc_matrix3x3_set(&value, 2, 1, matrix->_21);
kinc_matrix3x3_set(&value, 0, 2, matrix->_02); kinc_matrix3x3_set(&value, 1, 2, matrix->_12); kinc_matrix3x3_set(&value, 2, 2, matrix->_22);
kinc_g4_set_matrix3(location->location, &value);
")
function setMatrix3Private(location: ConstantLocation, matrix: FastMatrix3): Void {}
public function drawIndexedVertices(start: Int = 0, count: Int = -1): Void {
if (count < 0)
drawAllIndexedVertices();
else
drawSomeIndexedVertices(start, count);
}
@:functionCode("kinc_g4_draw_indexed_vertices();")
function drawAllIndexedVertices(): Void {}
@:functionCode("kinc_g4_draw_indexed_vertices_from_to(start, count);")
public function drawSomeIndexedVertices(start: Int, count: Int): Void {}
public function drawIndexedVerticesInstanced(instanceCount: Int, start: Int = 0, count: Int = -1): Void {
if (count < 0)
drawAllIndexedVerticesInstanced(instanceCount);
else
drawSomeIndexedVerticesInstanced(instanceCount, start, count);
}
@:functionCode("kinc_g4_draw_indexed_vertices_instanced(instanceCount);")
function drawAllIndexedVerticesInstanced(instanceCount: Int): Void {}
@:functionCode("kinc_g4_draw_indexed_vertices_instanced_from_to(instanceCount, start, count);")
function drawSomeIndexedVerticesInstanced(instanceCount: Int, start: Int, count: Int): Void {}
function renderToTexture(additionalRenderTargets: Array<Canvas>): Void {
if (additionalRenderTargets != null) {
var len = additionalRenderTargets.length;
var image1 = cast(additionalRenderTargets[0], Image);
var image2 = cast(additionalRenderTargets[1], Image);
var image3 = cast(additionalRenderTargets[2], Image);
var image4 = cast(additionalRenderTargets[3], Image);
var image5 = cast(additionalRenderTargets[4], Image);
var image6 = cast(additionalRenderTargets[5], Image);
var image7 = cast(additionalRenderTargets[6], Image);
untyped __cpp__("
kinc_g4_render_target_t *renderTargets[8] = { renderTarget, {1} == null() ? nullptr : &{1}->renderTarget, {2} == null() ? nullptr : &{2}->renderTarget, image3 == null() ? nullptr : &{3}->renderTarget, {4} == null() ? nullptr : &{4}->renderTarget, {5} == null() ? nullptr : &{5}->renderTarget, {6} == null() ? nullptr : &{6}->renderTarget, {7} == null() ? nullptr : &{7}->renderTarget };
kinc_g4_set_render_targets(renderTargets, {0} + 1);
", len, image1, image2, image3, image4, image5, image6, image7);
}
else {
untyped __cpp__("
kinc_g4_render_target_t *renderTargets[1] = { renderTarget };
kinc_g4_set_render_targets(renderTargets, 1)
");
}
}
@:functionCode("kinc_g4_restore_render_target();")
function renderToBackbuffer(): Void {}
public function begin(additionalRenderTargets: Array<Canvas> = null): Void {
if (current == null) {
current = this;
}
else {
throw "End before you begin";
}
var win: Int = window == null ? 0 : window;
if (win != lastWindow) {
if (lastWindow != -1) {
untyped __cpp__("kinc_g4_end(lastWindow);");
}
untyped __cpp__("kinc_g4_begin(win);");
lastWindow = win;
}
if (target == null) {
renderToBackbuffer();
}
else
renderToTexture(additionalRenderTargets);
}
public function beginFace(face: Int): Void {
if (current == null) {
current = this;
}
else {
throw "End before you begin";
}
untyped __cpp__("kinc_g4_set_render_target_face(renderTarget, face)");
}
public function beginEye(eye: Int): Void {}
public function end(): Void {
if (current == this) {
current = null;
}
else {
throw "Begin before you end";
}
}
@:functionCode("kinc_g4_flush();")
public function flush(): Void {}
}

View File

@ -0,0 +1,11 @@
package kha.kore.graphics4;
class Graphics2 extends kha.graphics4.Graphics2 {
override public function drawVideoInternal(video: kha.Video, x: Float, y: Float, width: Float, height: Float): Void {
// color = Color.Blue;
// fillRect(x, y, width, height);
color = Color.White;
drawScaledSubImage(Image.fromVideo(video), 0, 0, video.width(), video.height() * 0.66, x, y, width, height);
}
}

View File

@ -0,0 +1,6 @@
package kha.kore.graphics4;
enum abstract ShaderType(Int) {
var FragmentShader;
var VertexShader;
}

View File

@ -0,0 +1,9 @@
package kha.kore.graphics4;
@:headerCode("
#include <kinc/graphics4/textureunit.h>
")
@:headerClassCode("kinc_g4_texture_unit_t unit;")
class TextureUnit implements kha.graphics4.TextureUnit {
public function new() {}
}

View File

@ -0,0 +1,55 @@
package kha.kore.graphics5;
import kha.graphics5.RenderTarget;
import kha.graphics5.CommandList;
#if kha_dxr
import kha.graphics5.AccelerationStructure;
import kha.graphics5.RayTraceTarget;
import kha.graphics5.RayTracePipeline;
#end
@:headerCode('
#include <Kore/Graphics5/Graphics.h>
#include <Kore/Graphics5/RayTrace.h>
')
class Graphics implements kha.graphics5.Graphics {
private var target: Canvas;
public function new(target: Canvas = null) {
this.target = target;
}
public function begin(target: RenderTarget): Void {
untyped __cpp__("Kore::Graphics5::begin(target->renderTarget);");
}
public function end(): Void {
untyped __cpp__("Kore::Graphics5::end();");
}
public function swapBuffers(): Void {
untyped __cpp__("Kore::Graphics5::swapBuffers();");
}
#if kha_dxr
public function setAccelerationStructure(accel: AccelerationStructure): Void {
untyped __cpp__("Kore::Graphics5::setAccelerationStructure(accel->accel);");
}
public function setRayTracePipeline(pipe: RayTracePipeline): Void {
untyped __cpp__("Kore::Graphics5::setRayTracePipeline(pipe->pipeline);");
}
public function setRayTraceTarget(target: RayTraceTarget): Void {
untyped __cpp__("Kore::Graphics5::setRayTraceTarget(target->target);");
}
public function dispatchRays(commandList: CommandList): Void {
untyped __cpp__("Kore::Graphics5::dispatchRays(commandList->commandList);");
}
public function copyRayTraceTarget(commandList: CommandList, renderTarget: RenderTarget, output: RayTraceTarget): Void {
untyped __cpp__("Kore::Graphics5::copyRayTraceTarget(commandList->commandList, renderTarget->renderTarget, output->target);");
}
#end
}

View File

@ -0,0 +1,186 @@
package kha.kore.vr;
import kha.graphics4.FragmentShader;
import kha.graphics4.Graphics;
import kha.graphics4.ConstantLocation;
import kha.graphics4.TextureUnit;
import kha.Framebuffer;
import kha.graphics4.IndexBuffer;
import kha.graphics4.Program;
import kha.graphics4.Usage;
import kha.graphics4.VertexBuffer;
import kha.graphics4.VertexData;
import kha.graphics4.VertexShader;
import kha.graphics4.VertexStructure;
import kha.graphics4.TextureFormat;
import kha.graphics4.CullMode;
import kha.graphics4.BlendingOperation;
import kha.Image;
import kha.math.Matrix4;
import kha.math.Quaternion;
import kha.math.Vector2;
import kha.math.Vector3;
import kha.math.Vector4;
import kha.vr.Pose;
import kha.vr.PoseState;
import kha.vr.SensorState;
import kha.vr.TimeWarpParms;
import kha.Loader;
#if ANDROID
@:headerCode('
#include <Kore/Vr/VrInterface.h>
')
#end
#if VR_CARDBOARD
class CardboardVrInterfaceTest extends kha.vr.VrInterface {
// We draw directly to the screen
public var framebuffer: Framebuffer;
private var image: Image;
@:functionCode('
return Kore::VrInterface::getGaze();
')
private function GetGaze(): Quaternion {
return null;
}
public override function GetSensorState(): SensorState {
// Return from cardboard api
var s: SensorState = new SensorState();
s.Predicted = s.Recorded = new PoseState();
s.Predicted.Pose = new Pose();
s.Predicted.Pose.Orientation = GetGaze();
return s;
}
public override function GetPredictedSensorState(time: Float): SensorState {
// Return using cardboard api
return GetSensorState();
}
public override function WarpSwapBlack(): Void {
// Oculus-specific
}
public override function WarpSwapLoadingIcon(): Void {
// Oculus-specific
}
public override function WarpSwap(parms: TimeWarpParms): Void {
// Draw the two images, side-by-side
// parms.LeftImage.Image = Loader.the.getImage("use.png");
if (image == null) {
image = Image.createRenderTarget(Sys.pixelWidth, Sys.pixelHeight, TextureFormat.RGBA32);
}
var g: Graphics = image.g4;
g.begin();
g.clear(Color.Orange);
g.setCullMode(CullMode.None);
// g.setBlendingMode(BlendingOperation.BlendOne, BlendingOperation.BlendZero);
g.setProgram(program);
g.setVertexBuffer(vb);
g.setIndexBuffer(ib);
var texture: TextureUnit = program.getTextureUnit("tex");
var matrixLocation: ConstantLocation = program.getConstantLocation("projectionMatrix");
var t: Matrix4 = Matrix4.translation(-0.5, 0, 0);
var s: Matrix4 = Matrix4.scale(0.5, 1, 1);
var m: Matrix4 = s.multmat(t);
g.setMatrix(matrixLocation, m);
g.setTexture(texture, parms.LeftImage.Image);
g.drawIndexedVertices();
t = Matrix4.translation(0.5, 0, 0);
m = s.multmat(t);
g.setMatrix(matrixLocation, m);
g.setTexture(texture, parms.RightImage.Image);
g.drawIndexedVertices();
g.end();
framebuffer.g4.begin();
SendTextureToDistortion(image);
framebuffer.g4.end();
}
@:functionCode('Kore::VrInterface::DistortTexture(image.mPtr);')
private function SendTextureToDistortion(image: Image) {
// TODO: Add a function to CPP VrInterface
// TODO: Check how large the texture should be
}
public override function GetTimeInSeconds(): Float {
return Sys.getTime();
}
var vb: VertexBuffer;
var ib: IndexBuffer;
var program: Program;
private function setVertex(a: Array<Float>, index: Int, pos: Vector3, uv: Vector2, color: Vector4) {
var base: Int = index * 9;
a[base + 0] = pos.x;
a[base + 1] = pos.y;
a[base + 2] = pos.z;
base += 3;
a[base + 0] = uv.x;
a[base + 1] = uv.y;
base += 2;
for (i in 0...4) {
a[base + i] = color.get(i);
}
}
public function new() {
super();
var structure: VertexStructure = new VertexStructure();
structure.add("vertexPosition", VertexData.Float3);
structure.add("vertexUV", VertexData.Float2);
structure.add("vertexColor", VertexData.Float4);
vb = new VertexBuffer(4, structure, Usage.StaticUsage);
var verts: Array<Float> = vb.lock();
setVertex(verts, 0, new Vector3(-1, -1, 0), new Vector2(0, 0), new Vector4(1, 1, 1, 1));
setVertex(verts, 1, new Vector3(-1, 1, 0), new Vector2(0, 1), new Vector4(1, 1, 1, 1));
setVertex(verts, 2, new Vector3(1, -1, 0), new Vector2(1, 0), new Vector4(1, 1, 1, 1));
setVertex(verts, 3, new Vector3(1, 1, 0), new Vector2(1, 1), new Vector4(1, 1, 1, 1));
vb.unlock();
ib = new IndexBuffer(6, Usage.StaticUsage);
var indices: Array<Int> = ib.lock();
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 1;
indices[4] = 3;
indices[5] = 2;
ib.unlock();
program = new Program();
program.setVertexShader(new VertexShader(Loader.the.getShader("painter-image.vert")));
program.setFragmentShader(new FragmentShader(Loader.the.getShader("painter-image.frag")));
program.link(structure);
}
}
#end

View File

@ -0,0 +1,75 @@
package kha.kore.vr;
import kha.vr.SensorState;
import kha.vr.TimeWarpParms;
#if ANDROID
@:headerCode('
#include <Kore/Vr/VrInterface.h>
')
#end
class VrInterface extends kha.vr.VrInterface {
#if ANDROID
// Returns the current sensor state
// Returns the predicted sensor state at the specified time
@:functionCode('return Kore::VrInterface::GetSensorState();')
public override function GetSensorState(): SensorState {
return null;
}
// Returns the predicted sensor state at the specified time
@:functionCode('return Kore::VrInterface::GetPredictedSensorState(time);')
public override function GetPredictedSensorState(time: Float): SensorState {
return null;
}
// Sends a black image to the warp swap thread
@:functionCode('Kore::VrInterface::WarpSwapBlack();')
public override function WarpSwapBlack(): Void {}
// Sends the Oculus loading symbol to the warp swap thread
@:functionCode('Kore::VrInterface::WarpSwapLoadingIcon();')
public override function WarpSwapLoadingIcon(): Void {}
// Sends the set of images to the warp swap thread
@:functionCode('Kore::VrInterface::WarpSwap(parms.mPtr);')
public override function WarpSwap(parms: TimeWarpParms): Void {}
@:functionCode('return Kore::VrInterface::GetTimeInSeconds();')
public override function GetTimeInSeconds(): Float {
return 0.0;
}
#else
// Returns the current sensor state
// Returns the predicted sensor state at the specified time
public override function GetSensorState(): SensorState {
return null;
}
// Returns the predicted sensor state at the specified time
public override function GetPredictedSensorState(time: Float): SensorState {
return null;
}
// Sends a black image to the warp swap thread
public override function WarpSwapBlack(): Void {}
// Sends the Oculus loading symbol to the warp swap thread
public override function WarpSwapLoadingIcon(): Void {}
// Sends the set of images to the warp swap thread
public override function WarpSwap(parms: TimeWarpParms): Void {}
public override function GetTimeInSeconds(): Float {
return 0.0;
}
#end
public function new() {
super();
}
}

View File

@ -0,0 +1,62 @@
package kha.kore.vr;
import kha.math.Quaternion;
import kha.math.Vector3;
import kha.vr.Pose;
import kha.vr.PoseState;
import kha.vr.SensorState;
import kha.vr.TimeWarpParms;
@:headerCode('
#include <Kore/Vr/VrInterface.h>
')
/**
* ...
* @author Florian Mehm
*/
class VrInterfaceRift extends VrInterface {
// Returns the current sensor state
#if VR_RIFT
@:functionCode('
return Kore::VrInterface::GetSensorState();
')
#end
public override function GetSensorState(): SensorState {
return null;
}
// Returns the predicted sensor state at the specified time
public override function GetPredictedSensorState(time: Float): SensorState {
return GetSensorState();
}
// Sends a black image to the warp swap thread
public override function WarpSwapBlack(): Void {
return;
}
// Sends the Oculus loading symbol to the warp swap thread
public override function WarpSwapLoadingIcon(): Void {
return;
}
// Sends the set of images to the warp swap thread
#if VR_RIFT
@:functionCode('
Kore::VrInterface::WarpSwap(parms.mPtr);
')
#end
public override function WarpSwap(parms: TimeWarpParms): Void {
return;
}
// This returns the time that the TimeWarp thread uses
// Since it is created from the library's vsync counting code, we should use this
public override function GetTimeInSeconds(): Float {
return System.time;
}
public function new() {
super();
}
}

View File

@ -0,0 +1,77 @@
package kha.netsync;
import haxe.io.Bytes;
@:headerCode("
#include <kinc/network/socket.h>
")
@:headerClassCode("kinc_socket_t socket;")
class Network {
var url: String;
var port: Int;
var bufferPos: Int;
var buffer: Bytes;
var tempBuffer: Bytes;
var listener: Bytes->Void;
public function new(url: String, port: Int, errorCallback: Void->Void, closeCallback: Void->Void) {
this.url = url;
this.port = port + 1; // TODO: This is somewhat ugly, but necessary to maintain both websocket and UPD connections at the same time (see also Server.hx)
bufferPos = 0;
buffer = Bytes.alloc(256); // TODO: Size
tempBuffer = Bytes.alloc(256); // TODO: Size
init(url, port);
kha.Scheduler.addFrameTask(update, 0);
}
@:functionCode("
kinc_socket_init(&socket);
kinc_socket_options options;
kinc_socket_options_set_defaults(&options);
kinc_socket_set(&socket, \"127.0.0.1\", port, KINC_SOCKET_FAMILY_IP4, KINC_SOCKET_PROTOCOL_UDP);
kinc_socket_open(&socket, &options);
")
public function init(url: String, port: Int) {
send(Bytes.ofString("JOIN"), true); // TODO: Discuss, dependency with Server.hx
}
@:functionCode("
// TODO: mandatory
kinc_socket_send_url(&socket, url, port, (const unsigned char*)bytes->b->getBase(), bytes->length);
")
public function send(bytes: Bytes, mandatory: Bool): Void {}
public function listen(listener: Bytes->Void): Void {
this.listener = listener;
}
function update() {
var received = getBytesFromSocket(tempBuffer);
buffer.blit(bufferPos, tempBuffer, 0, received);
bufferPos += received;
// if (received > 0) trace("received " + received + " bytes");
// TODO: Handle partial packets, don't choke on garbage
if (listener != null && bufferPos > 0) {
var result = Bytes.alloc(bufferPos);
result.blit(0, buffer, 0, bufferPos);
listener(result);
bufferPos = 0;
}
}
@:functionCode("
unsigned int recAddr;
unsigned int recPort;
int size = kinc_socket_receive(&socket, (unsigned char*)inBuffer->b->getBase(), inBuffer->length, &recAddr, &recPort);
if (size >= 0) {
return size;
}
else {
return 0;
}
")
function getBytesFromSocket(inBuffer: Bytes): Int {
return 0;
}
}

View File

@ -0,0 +1,45 @@
package kha.network;
@:headerCode("
#include <kinc/network/http.h>
")
@:headerClassCode("
static void internalCallback(int error, int response, const char* body, void* data) {
int callbackindex = (int)(intptr_t)data;
if (error == 0) {
size_t length = strlen(body);
HX_CHAR* chars = hx::NewString(length);
for (int i = 0; i < length; ++i) {
chars[i] = body[i];
}
internalCallback2(error, response, String(chars, length), callbackindex);
}
else {
internalCallback2(error, response, null(), callbackindex);
}
}
")
class Http {
static var callbacks: Array<Int->Int->String->Void>;
@:functionCode("kinc_http_request(url, path, data, port, secure, method, header, internalCallback, (void*)callbackindex);")
static function request2(url: String, path: String, data: String, port: Int, secure: Bool, method: Int, header: String, callbackindex: Int): Void {}
static function internalCallback2(error: Int, response: Int, body: String, callbackindex: Int): Void {
callbacks[callbackindex](error, response, body);
}
public static function request(url: String, path: String, data: String, port: Int, secure: Bool, method: HttpMethod, headers: Map<String, String>,
callback: Int->Int->String->Void /*error, response, body*/): Void {
if (callbacks == null) {
callbacks = new Array<Int->Int->String->Void>();
}
var index = callbacks.length;
callbacks.push(callback);
var header = "";
for (key in headers.keys()) {
header += key + ": " + headers[key] + "\r\n";
}
request2(url, path, data, port, secure, method, header, index);
}
}

View File

@ -0,0 +1,2 @@
DisableFormat: true
SortIncludes: false

View File

@ -0,0 +1,650 @@
4.3
------------------------------------------------------------
* Bug fixes
* Upgrade to 4.3 API
* Use PCRE v2
4.2
------------------------------------------------------------
* Update MIN_IOS_VERSION
* Bug fixes
* Upgrade to 4.2 API
* Fixed mysql_select_db failing for newer mariadb versions due to extra 0x00 byte after database
* Fixed mysql_close not sending COM_QUIT before closing socket
4.1.15
------------------------------------------------------------
* Added Arm64 suport on windows
* Fixed crash with zero-sized alloc and generational GC
* Fixed crash with generational GC when old objects come back to life
* Fixed compile error with @:fixed Anons and arrays (socket select)
* Fixed lastIndexOf
* Optimized some equality functions
4.1.1
------------------------------------------------------------
* Added functions for haxe 4.1 Api.
* Added HXCPP_DEBUG_LINK_AND_STRIP to preserve symbolic information when creating android release binaries.
* Added optional HXCPP_SIGNAL_THROW to convert memory errors to haxe exceptions without needing additional code
* Added string_hash_map_substr and __hxcpp_parse_substr_float/int to allow some substring processing without extra allocation
4.0.64
------------------------------------------------------------
* Upgrade buildserver to 4.01
* Better generational collection in high fragmentation case
* typeinfo include fix for MSVC
* Fix MySQL connections
* Fix bugs with HXCPP_GC_GENERATIONAL
* Add map.clear
* Better c++11 iOS support
4.0.19
------------------------------------------------------------
* Add Array.keyValueIterator
* General Utf16 string improvements
* Limit the amount of recursion in toString function
* Add float32 support to cppia
* Fix Gc race condition
* Throw exceptions according to the spec when casting
* Introduce hxcpp_smart_strings for unicode text
4.0.4
------------------------------------------------------------
* Compile Cppia against haxe 4.0 preview 4
4.0.2
------------------------------------------------------------
* Default Cppia to 64 bits on windows
4.0.1
------------------------------------------------------------
* More logic for determining the android NDK version
* Updated various opensource libraries (thanks robocoder)
* Updated version of zlib
* Updated version of sljit
* Updated version of pcre
* Updated version of sqlit3
* Updated version of mbedtls
* Some work on supporting utf16 strings (hx_smart_strings)
* Added process_kill
* Change root when calculating haxelib in build.xml files
* Fix cppia super calls across cpp boundary
* Add Array.resize
* Be consistent with mod in cppia
* Fix Sys.stderr
* Add 'embedName' file attribute to allow text to cpp conversion
* Updates for Msvc
* Updates for Xcode
3.4.188
------------------------------------------------------------
* Fix some threading crashes
3.4.185
------------------------------------------------------------
* Do not ship static libraries
* Use more lock-free structures in GC processing
* Added some documentation
* Added HXCPP_GC_SUMMARY option
* Added HXCPP_GC_GENERATIONAL option
* Added HXCPP_GC_DYNAMIC_SIZE option
* Some MSVC 2017 support
* Compile Cppia with JIT as an option by default
3.4.64
------------------------------------------------------------
* Fixed cppia native interface implementation
* Fixed debugger breakpoints
* More compatibility for inet_pton and inet_ntop
* Correct the order of thread housekeeping data
3.4.49
------------------------------------------------------------
* Fixed 2d-Arrays and unserialize
3.4.43
------------------------------------------------------------
* Added more options for code-size optimizations on android (thanks madrazo)
* Added version of stpcpy on android to allow building with platform > 21, and running on older devices
* Added some initial support for ipv6
* Experimental support for Cppia JIT
* Fixed issue with stale objects that use new pch files in cache
* Rethrowing exception now preserves stack correctly
3.4.2
------------------------------------------------------------
* Align float reads from memory for Arm architecture
* Removed some virtual functions not needed by newer versions of haxe
* Reworked the logic for compacting fragmented heaps with HXCPP_GC_MOVING
* Expose StackContext to allow inlining of allocation routine, and combine with Cppia context
* Fix some compare-with-dynamic issues
* Added WatchOs support
* Fixed for android NDK 13
* Fix Array closure equality
* Refactor the Cppia code
* Fix return codes for atomic decrease
* Fix some GC zone issues in the standard library
* Set minimum MacOS deployment target to 10.6
* Do not use typedefs for 'Int' and 'Bool' for newer api levels
* Added dll_link to create output dll
* Improved ObjC support
* Make Cppia order of operations of '+=' et al consistent with other targets
* Added NO_RECURSE flag to PCRE
* Fix bsd_signal undefines on android
* Add create/free abstract
3.3.49
------------------------------------------------------------
* Fix Dynamic != for haxe 3.2.1
* Fix Command line parsing on windows for triple quotes
3.3.45
------------------------------------------------------------
* Much better compile cache support
* Added tags to compiler flags to allow better targeting
* Added UCP support to regexp
* Added Array::fromData
* Added AtomicInt operations
* Added _hx_imod
* More improvements for tvos
* Fix blocking deque issue
* Improved native testing
* Added 'hxcpp run hxcpp cache ...' commands for managing cache
* Added cpp.Variant class for query of field values to avoid boxing
* Added more efficient version of finalizer
* Add non allocating version of __hxcpp_print
* More WinRT fixes
* Output 'HxcppConfig.h' with defines included for easier external integration
* Output list of output files if requested
* Add support functions for StdLib - alloc/free/sizeof
* Fix crash when marking stack names from GCRoots
* Add bitcode support for iOS
* Rename RegisterClass to avoid conflicts with windows
* Added 'VirtualArray' for arrays of unknown types
* Split Macros.tpl
* Added optional ShowParam to process_run
* Added inline functions for Int64 externs
* Add error check for allocating from a finalizer
* Fix null strings on Cffi Prime
* Use slow path if required for Win64 Tls
* Expand logic for detecting android toolchain from NDK name
* Remove the need for hxcpp binaries by compiling source directly into target
* Adjust the default verbosity level, and add HXCPP_VERBOSE/HXCPP_QUIET/HXCPP_SILENT
* Added some control options for copyFile directive
* Fix cppia decrement
* Add Array.removeRange, which does not require a return value
* Do not call setbuf(0) on stdin, since it messes with readLine
* Cppia now throws an error if loading fails
* Allocate EnumParam data inline to cut down on allocations
* Allow anonymous object data to be allocated inline to avoid allocations
* Add SSL library code
* Add NativeGen framework for interfaces
* Add macros to allow neater generated code
* Allow larger memory space with -D HXCPP_GC_BIG_BLOCKS
* Improve Array.join speed
3.2.205
------------------------------------------------------------
* Initial support for HXCPP_OPTIMIZE_FOR_SIZE
* Support HXCPP_DEBUG_LINK on more targets
* Support for cross compiling to windows from linux
* Added array removeAt
* Some telemety fixes (thanks Jeff)
* Check contents when comparing Dynamics with same pointer (Math.Nan!=Math.Nan)
* Numerous WinRT fixes (thanks madrazo)
* Fixed bug causing GC to crash marking constant strings (eg, resources)
* Updated default SDK for Tizen (thanks Joshua)
* Fixed command line args on linux (thanks Andy)
3.2.193
------------------------------------------------------------
* Some improvements for tvos
* Start on some GC defragging code
* Fix android thread access to GC structures
* Add socket socket_recv_from and socket_send_to
* Fixed memory leak in GC collection code
* Allow cross-compile to windows via MINGW
* Fix overflow error that meant GC would work with a too-small buffer in some cases
3.2.180
------------------------------------------------------------
* Initial support for tvos
* Change name of ObjectType to hxObjectType to avoid clashes with iOS
* Try to keep windows.h out of haxe-generated code
* Fix null access bug in array-of-array
* Create separate library for msvc 19
------------------------------------------------------------
* Try to get the pdb server working better for MSVS 2015
* So not export symbols on windows unless HXCPP_DLL_EXPORT is set (-D dll_export) - makes exe smaller
* Avoid dynamic-cast if possible when converting 2D arrays
* Some RPi fixes
* Some CFFI Prime fixes (thanks Joshua)
* Fix build tool for next version of neko
* Improve msvc cl.exe version checking for non-English environments
* Add more control over how much Gc memory is used
* Add faster(inline) thread local storage for Gc on windows.
* Add some Gc load balancing when marking large arrays with multiple threads
* Change the Gc memory layout to be a bit larger, but simpler. This allows most of the allocation to be simplified and inlined.
* Explicitly scan registers for Gc references because the stack scanning was missing them sometimes
* Some additions to Undefine.h for windows
* When static linking using MSVC 2015, compile the libraries directly into the exe to avoid compatibility issues
* Move standard libraries into their own build.xml files
* Make it easier to change the generated output filename
* Allow targets from one build.xml file to be merged into another
* Some more work on HXCPP_COMPILE_CACHE
* Allow automatic grouping of obj files into librarys to avoid linking all the symbols in all obj files
* Add implicit conversion to referenced type from cpp.Reference
* Allow build.xml files to be imported relative to importing file
* Allow '-' in command-line defines
* Fix warnings from Hash class
* Fix setsockopt for Mac
* Support to MSVC2015
* Fix for Blackberry 10.3
* Fix debug break by linenumber
* Better objc integration (thanks Caue)
* Increase number of variables captured in closures to 20
* Initial support for telemetry (thanks Jeff)
* Align allocations for better emscripten support
------------------------------------------------------------
* Fix gc_lock error in remove_dir
* Some cppia bug fixes - enum and resources overrides
* More android atof fixes
* Improved haxelib seek logic
Haxe 3.2.0
------------------------------------------------------------
* Improve testing
* Allow dll_load path to be set programatically and simplified the dll search sequence.
* Improved cffi_prime, and added String class
* Fixed static linking of mysql5
* Moved static link code in general to cpp.link package, not hxcpp package
* URL decode now does not need to performe reallocs
* Ensure HXCPP_API_LEVEL is always defined
* Added __hxcpp_unload_all_libraries to cleanly unload dlls
* Added some utc date functions
* Better support for non-console apps in windows XP 64
* Increased use of HXCPP_DEBUG_LINK for gcc based targets
* Class 'hasField' is now more consistent with other functions/targets
* 'haxelib run hxcpp test.cppia' will run Cppia on the specified file
* Add fast-select option for sockets
* Allow code to run without HXCPP_VISIT_ALLOCS defined
* Fix debugger thread deadlocks
* Allow up to 27 dynamic arguments
* Fixes for Emscripten - byte align access and disable threads
* Allow emscripten to generate 'executables' (.js/.html) and add options for specifying memory
* Allow spaces in exe names again
* Make cpp::Struct compare via memcmp, and mark correctly
* Fix catch block in cppia
* Treat '-debug' as an alias for "-Ddebug"
* Expose ArrayBase for use with some generic or external code
* Clarify the role of 'buffer' in cffi
------------------------------------------------------------
* Only put a minimal run.n in source-control, and use this to boot hxcpp.n
* Added cpp.Struct and cpp.Reference classes, which are handy for extern classes
* Moved Class to hx namespace
* Simplified 'main' logic
* Allow new android compilers to work for old devices (thanks google)
* Correctly read hxcpp_api_level from Build.xml
* Verbose logging prints which file is being compiled
* Handle undefining the INT_ constants differently to allow std::string to still compile
* Remove entries form Options.txt that do not influence the cpp build
* Add optional destination= command-line option to allow copying the result to named file
* Static libraries will be prefixed with 'lib' now
* val_is_buffer always returns false on neko
* Add val_iter_field_vals, which is like val_iter_fields but consistent with neko
* Remove NekoApi binaries
* Add Cppia binaries
* Add Windows64 binaries
* Make compares between Dynamic and numeric types false, unless the Dynamic is actaully numeric
------------------------------------------------------------
* Even more optimizations for hashes
* Some more optimizations for small hashes
* Fix for google changing inlining in platform21 headers (atof, rand, srand)
* Re-tuned Hash for small objects too (improves Anon object perforamce)
* Reverted change that automatically threw 'BadCast'. Now required HXCPP_STRICT_CASTS
------------------------------------------------------------
* Cached dynamic versions of small ints and 1-char-strings for speed
* Added support for weak hashes - needs latest haxe version
* Use internal hash structure for maps - now faster. New version of haxe makes it faster still.
* Changed the way development versions are bootstrapped to avoid committing binaries
* Improved mingw support
* Dont append -debug to dll name
* Reorder xml includes to allow early parts to correctly influence older parts
* Fix busy wait in semaphore lock
* Fixed GC issue when constructing exrernal primitive objects
* Added armv7s and arm64 targets for ios
* Some fixes for neko cffi - wstring and warning for neko_init
* Fix file read (and copy) from thread
------------------------------------------------------------
* Compile fix for blackberry
* Pass on haxe_api_level
* Add -nocolor flag
------------------------------------------------------------
* Add support for prelinker
* Cygwin toolchain fix
* Add HXCPP_NO_COLOUR and HXCPP_NO_M32
* Fix windows trace output
* Add initial support for GCWO compile
* Fix bug with losing GC references in Array.sort
* Fix bug with zombie marking
* Add support for optimised sort routines
* Add support for haxe.ds.Vector optimisation
* Add support for cpp.Pointer, cpp.NativeArray, cpp.NativeString
------------------------------------------------------------
* Add BlackBerry and Tizen binaries
* Fix issues when using names like ANDROID or IPHONE in an enum
* Added more info in verbose mode (setenv HXCPP_VERBOSE)
* Refactor build files to allow greater customisation
* Fix bug with 'lock' where some threads may not get released
* Add optimised arrays access
* Add optimised memory operations for arrays and haxe.io.Bytes
* Avoid blocking in gethostbyname
* Upgrade run tool output and layout
* Restore sys_time for windows
3.1.1
------------------------------------------------------------
* Fixed MSVC support for 64-bit targets (vc11, vc12)
* Initial work on cpp.Pointer (not fully functional)
* Fixed callstack when throwing from native function
3.1.0
------------------------------------------------------------
* VC 2013 support - used as default now
* Add winxp compatibility flags
* Allow cross-compiling from mac to linux
* Added NSString helper conversion
* Better auto-detection for android toolchain
* Allow foreign threads to easily attach and detach from GC system
* Weak references to closures keep object alive
* Added HXCPP_API_LEVEL define to allow for future compatibility
* Fixed clearing finalizers twice
* Int multiply and minus are performed with integers now
* Fix comparing +- infinities
* Use multiple threads in the mark phase of GC
* IOS now defaults cpp11 binary linkage
* Added HXCPP_VERBOSE environment var to enable extra output
* Fixed spin loop in pthread_cond_wait
* Added ability to link several .a files into a single .a file
* Removed dependence on STL runtime for supplied modules
* Renamed some directories to be more standard
* Moved some extra build files into obj directory
* Use sys.io.Process instead of Sys.command to avoid threading slowdown writing to console
* Add hxcpp.Builder to help with building multiple binaries
* Add android x86 support
* Drop pre-compiled support for everything excepth windows,mac,linux,ios and android
* Allow libraries and files to accumulated in the build.xml
* Supply pre-build lib files for static linking on supported platforms
* Support for static linking of all modules
* Support for hxcpp-debugger project
* Binaries have been removed from repo, and are built using a server
* Use build.n script to build all appropriate binaries
* Some initial support for mysql and sqlite databases
* Add free_abstract for safe releasing of data references
* Change process lauching to get better thread usage on mac
* Fix GC error in string resources
* Give obj files in libraries unique names
3.0.2
------------------------------------------------------------
* Fix Dynamic + Int logic
* Reverted linux compiler to older version
* Cast Array at call site if required
* Tweak Array.map return value
3.0.1
------------------------------------------------------------
* Added nekoapi for linux64
* Upgrade nekoapi to v2
* Added haxe vector support
* Added socket_set_fast_send
* Fixed android build
* Expanded native memory access methods
* Fix exception dump
* Added initial Emscriptm support
* Allow specification of ANDROID_HOST
* Inital work on auto-setup of win64
* Support call-site casting of Arrays
3.0.0
------------------------------------------------------------
* Support haxe3 syntax
* Added socket poll function
* Added some initial support for dll_import/dll_export
* Allow full path name when loading dynamic libraries
* Allow dynamic toString function
* Added initial support for Raspberry Pi
* Array sort now uses std::stable_sort
* Fixed Dynamic+null string output
* Fix splice size calculation
* Add object ids for use in maps
* Add map/filter functions to arrays
* GC will now collect more often when big arrays are used
* You can specify a number of args > 5 for cffi functions if you want
* Fix internal hash size variable
* Class static field list does not report super members now
* Fix casting of null to any object
* Do not read input twice in sys_getch
* Link in PCH generated obj data on msvs 2012
* Date is now consistent with UTC
* Hash 'remove' now returns correct value
* CPP native WeakRef now works, and has a 'set' function
* Fixed compile error when assigning to a base class
* Fixed compile error when using != and Dynamic
* Math/floor/ceil/trunc/min/max now pass unit tests
* More control over android sdk installation
* Regexp_match fix
* Fix val_callN CFFI
2.10.3
------------------------------------------------------------
* Added initial build support for WinRT
* Android toolchain improvements
* Minor compile fixes
* Other minor improvements
2.10.2
------------------------------------------------------------
* Fixes for BlackBerry 10 compatibility
* Fixes for iOS 6 compatibility
* CFFI improvements
* Minor Linux improvements
* Minor OS X improvements
2.10.1
------------------------------------------------------------
* Fix trace() output
* Clang options for OS X compiler
* Small fixes
2.10.0
------------------------------------------------------------
* GC upgrades - moving/defragging/releasing
* Built-in profiler
* Build-in debugger
* Fix mac ndll finding bug
* Add Int32 member functions
* Clang options for ios compiler
* Add a few pre-boxed constants
* Some general bug fixes
2.09.3
------------------------------------------------------------
* Fix Xml enum usage
2.09.2
------------------------------------------------------------
* Resolve library paths when launching Mac apps from Finder
* Compile fix for the BlackBerry toolchain
* Fix interface comparison
* Fix api_val_array_value for NekoApi
* Add workaround for optional Strings in interfaces
* Tweak the timing og the GC run
* Remove setProperty conditional compiles
* String charCodeAt only returns positive values
* Fix modulo for negative numbers
* Remove extra space from array output
* Treat '.' and '_' as literals in urlEncode
* Dynamically generated, 0 param, enum instances match the static version
2.09
------------------------------------------------------------
* Improved precision in random implementations
* Added some experimental support for float32
* Added some experimental support for generic getProcAddress
* String::fromCharCode generates single-byte strings
* Fix method compares
* Plug memory leak in finalizers
* Fix debug link flags
* Separate get/SetField from get/setProperty
* Added Null<T> for optional parameters
2.08.3
------------------------------------------------------------
* Actually add blackberry toolchain
2.08.2
------------------------------------------------------------
* Add blackberry support
* Add armv7 options
* Support new xcode layout
* Fix const qualifiers on interface functions
* Fix webOS obj directory
2.08.1
------------------------------------------------------------
* Fix Math.random returning 1.0 sometimes
* Std.is( 2.0, Int ) is now true
* Make static library building more separated - refactor defines to control this
* Do not use @files for linking on mac
* toString on Anon objects will now get called
* Fix fast memory access with --no-inline
* Android tool host now set to linux-x86
* Allow use of __compare as operator== overload
* Add toNativeInt
* Add weak references
* Implement some neko/cffi compatibility operations
* Fix mac deployment using environment variable
* Fix reentrant mutexes
* Do not explicitly specify version of g++
* Speedup some code by avoiding dynamic_cast if possible
* Some fixes to allow Android multi-threading in normal operation
2.08
------------------------------------------------------------
* Do not create a new class definition for each member function
* Allow 5 fast and up to 20 slow dynamic function arguments
* Support utf8 class
* Added "Fast Memory" API similar to flash
* Added support for webOS
* Fix uncompress buffers
* Added file to undefined pesky processor macros
* Setup default config in user area
* Auto-detect msvc and iphone version
* Force compilation for mac 10.5
* Some support for cygwin compilers
* Remove Boehm GC as an option
* Integrate properly now with Android ndk-r6
* Make Int32 pass haxe unit tests (shift/modulo)
* Fix bug in "join"
* Fix bug with marking the "this" pointer in closures
* Fix bug with returning NAN from parseFloat
* Fix linux link flags
* Fix bug where string of length 0 would be null
* Made String cca return value consistent
* Added control over @file syntax
* Removed need for nekoapi.ndll
* Allow for neko.so to end in ".0"
2.07
------------------------------------------------------------
* Added initial support for Mac64, Linux64, MinGW and GPH and refactored build tool.
* Return the count of traced objects
* Fix interface operator ==
* Initial work on msvc10 batch file
* Add bounds check on String.cca
* Build static libraries, if requrested
* Added exe stripping
* Added val_field_name, val_iter_fields
* Fixed nekoapi string length
* Fixed Sys.args
2.06.1
------------------------------------------------------------
* Close files if required in GC
* Added fix for File.write
* Fixed String UTF8 Encode
* Nekoapi is now a "ndll", not a "dso".
* Fix array compile issue on linux
* Fix stack setting on firced collect
2.06.0
------------------------------------------------------------
* Updates to match haxe 2.06 compiler features
* Numerous bug fixes
* Add additional context to GC collection process
* Swapped from wchar_t* to utf8 char*
* Added templated iterators
* Use strftime for Dates
* Fix socket select and "_s" members
* Seed Math.random
* Fixed dynamic integer compare
* Added __hxcpp_obj_id
* Added some Android support
2.05.1
------------------------------------------------------------
* Updated windows nekoapi.dll binary
* Added -m32 compile flags to force 32 bit
2.05.0
------------------------------------------------------------
* Default to IMMIX based internal garbage collection.
* Reorginised files - split big ones, and moved common ones out of "runtime".
* Put internal classes in "hx" namespace, or HX_ prefix for macros.
* Remove multiple-inheritance, and use delegation instead.
* Write "Options.txt" from compiler so dependency can be determined.
* Require -D HXCPP_MULTI_THREADED for multi-threaded classes - to avoid overhead if not required.
* Build thread code into executable for better control.
* Fix return values of parseINt/parseFloat.
* Added comprehensive list of reserved member names.
* Put if/else statements in blocks.
* Added assert, NULL, LITTLE_ENDIAN, BIG_ENDIAN as keywords.
* Added control over how fast-cffi routines are created by requiring cpp.rtti.FastIntergerLookup to be "implemented".
* Construct anonymous object fields in deterministic (as declared) order.
* Fix code generation for some complex inline cases.
* Added cpp.zip.Compress
* Change "Reflect" class to be more standard
* Use array of dynamics for StringBuf.
* Fix setting of attributes in XML nodes.
Build-tool:
* Allow multiple build threads (via setenv HXCPP_COMPILE_THREADS N) for faster building on multi-code boxes.
* Added FileGroup dependencies
* Added pre-compiled headers (windows only, at the moment since gcc seems buggy)
1.0.7
-----------------
Changelog starts.

View File

@ -0,0 +1,15 @@
* Copyright (c) 2008 by the contributors
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* See individual source files for additional license information.
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.

View File

@ -0,0 +1,30 @@
# hxcpp
[![Build Status](https://dev.azure.com/HaxeFoundation/GitHubPublic/_apis/build/status/HaxeFoundation.hxcpp?branchName=master)](https://dev.azure.com/HaxeFoundation/GitHubPublic/_build/latest?definitionId=3&branchName=master)
hxcpp is the runtime support for the c++ backend of the [haxe](http://haxe.org/) compiler. This contains the headers, libraries and support code required to generate a fully compiled executable from haxe code.
# building the tools
```
REPO=$(pwd)
cd ${REPO}/tools/run
haxe compile.hxml
cd ${REPO}/tools/hxcpp
haxe compile.hxml
cd $REPO
```
# cppia
You first need to build the cppia host.
```
REPO=$(pwd)
cd ${REPO}/project
haxe compile-cppia.hxml
cd $REPO
```
Then you can do `haxelib run hxcpp file.cppia`.

View File

@ -0,0 +1,42 @@
variables:
- group: variables-haxe
- name: AZURE_PIPELINES_REPO_URL
value: $(Build.Repository.Uri)
- name: AZURE_PIPELINES_BRANCH
value: $(Build.SourceBranchName)
- name: HXCPP_COMPILE_CACHE
value: $(Agent.TempDirectory)/hxcache
stages:
- stage: StageTest
jobs:
- template: tools/azure-pipelines/build.yml
parameters:
name: Linux64
vmImage: ubuntu-20.04
platform: linux64
arch: 64
- template: tools/azure-pipelines/build.yml
parameters:
name: Linux32
vmImage: ubuntu-20.04
platform: linux64
arch: 32
- template: tools/azure-pipelines/build.yml
parameters:
name: Mac
vmImage: macOS-10.15
platform: mac
arch: 64
- template: tools/azure-pipelines/build.yml
parameters:
name: Windows64
vmImage: windows-2019
platform: windows
arch: 64
- template: tools/azure-pipelines/build.yml
parameters:
name: Windows32
vmImage: windows-2019
platform: windows
arch: 32

View File

@ -0,0 +1,6 @@
<xml>
<pragma once="true" />
<include name="toolchain/haxe-target.xml" />
</xml>

View File

@ -0,0 +1,55 @@
The Hxcpp Cache
---------------
The hxcpp compile cache is used to share object files between projects. This can alleviate the need to ship static libraries with external projects, since developers who use the library can compile the library just once, and then reuse it between projects.
The cache uses a hashing mechanism to tell if the contents of a file or its dependencies has changed, and combines this with the compiler version and flags to make specific object files for each change and each compiler congiguration. This also allows some common haxe runtime and haxe generated files to share their object files between projects, even if in different directories.
Additional benefits include keeping some files outside the source tree, and being able to remove these temp files easily.
### Setup
A directory needs to be set aside to enable the cache. If possible, this should be on fast storage, such as a SSD. This is most easily done with an entry in the .hxcpp_config.xml file:
```xml
<set name="HXCPP_COMPILE_CACHE" value="c:/hxcpp/cache" />
<set name="HXCPP_CACHE_MB" value="4000" />
```
Keeping the path short can help in some border-line cases with some compilers where command-line length can become an issue.
The cache size defaults to 1 Gig. For many cases, this is big enough. However, on large projects, with several architectures and lots of debug information, this default can lead to "cache churn" where some files are evicted from the cache, even though they are likely to be used again. Increasing the number of mega-bytes allocated to the cache can help here.
### Using The Cache
To use the cashe with your own libraries, the files group should have 'cache' entry to tell hxcpp that you have considered dependency issues when designing the group.
```xml
<cache value="true" project="name" asLibrary="true" />
```
- project = name of project used to manage and group object files in the cache
- asLibrary = link the objs into a .lib file.
When linking a file group 'asLibrary', the object files are compiled and then the library tool is used to make a library from these object files. This library is then added to the linker. This has a few implications:
- Object files that to not resolve any symbols directly are not added to the final executable
+ Can make final exe size smaller
+ If the object file only contains a handler that is self-registering via static constructor,
then the constructor may not get called, leading to bugs.
- Can help on some systems where the linker command-line length is an issue.
### Management
When compiling normally, hxcpp will check the cache size and evict the least used files to maintain the specified cache size.
Object files in the cache are grouped into "projects" to make management easier, and the hxcpp build tool can be used to explicitly manage the object files.
```
haxelib run hxcpp cache [command] [project]
Perform command on cache, either on specific project or all. commands:
clear -- remove all files from cache
days #days -- remove files older than "days"
resize #megabytes -- Only keep #megabytes MB
list -- list cache usage
details -- list cache usage, per file
```
Start with
```
haxelib run hxcpp cache list
```
To get an idea of cache usage.

View File

@ -0,0 +1,152 @@
Threads And Stacks
-------------------
### Conservative, co-operation
Hxcpp uses conservative stop-the-world GC, where the threads need to co-operate.
- Threads must not change GC pointers in the collection phase
- The thread stacks/registers must be scanned for GC pointers
- Threads must not block without letting the GC system know not to wait for them, otherwise GC blocks until end of block
+ call hx::GCEnterBlocking() / gc_enter_blocking() / (cpp.vm.Gc.enterGCFreeZone() from Haxe) before potentially blocking system call (fs, network, etc)
+ call hx::GCExitBlocking() / gc_exit_blocking() / (cpp.vm.Gc.exitGCFreeZone() from Haxe) before making more GC calls
+ Might need to pre-allocate buffers
+ Don't forget the exit blocking on error condition
### Foreign Threads
When you create a thread from haxe, it starts attached. Before a non-haxe created thread can interact with hxcpp, some care must be taken, since GC allocations are done using a GC context per thread, and all threads must respect the stopped world.
- Foreign threads must be attached-detached
- SetTopOfStack(int * inTop,bool inPush)
- *inTop* = pointer to top of stack to attach, or '0' to remove stack
- *inPush* = usually true. recursive attachment/detachment
- Must not change things when the world is stopped
- Must define their stack range for scanning
- If you are attached, you may need to enter/exit gc free zone
- Must release context when done, if no more calls are going to be made
- Make sure local variables are covered in stack
- compiler may reorder, so be careful
- Read documentation because some things, eg audio callbacks, happen on other threads
- You can use other techniques, eg
- create a haxe thread, which blocks waiting for signal
- foreign thread generates request and signals haxe thread
- haxe thread performs job and generates data then signals foreign thread
- foreign picks up data and carries on
### Top of Stack
- To understand how to handle threads, you need a mental picture of the c++ stack
- The stack usually goes "down". That is, if the first stack location is 10000, the next one will be 9999 etc.
- Historical, but consistent. Except for emscripten which goes up - but still use same terminology/picture, just change the less-thans to greater-thans in code.
Say the system starts each program stack at 10000, the stack might look like this, with local variables and arguments pushed on the stack:
```
10000
-----------------------------------------------
9996 startup temp variable
9992 startup temp variable
-- main function --
9988 main return address - order and details of this are ABI specific
9984 char ** argv
9980 int argc
```
Hxcpp then runs it main code, which starts with the macro HX_TOP_OF_STACK, which expands to something like:
```
int t0 = 99;
hx::SetTopOfStack(&t0,false);
...
__boot_all();
__hxcpp_main();
-- main function --
9988 main return address order and details of this are ABI specific
9984 char ** argv
9980 int argc
9976 int t0
-- hx::SetTopOfStack --
records '9976' as top of stack for this thread
```
Later, many generated functions deep, `__hxcpp_main` generates an allocation call which
triggers a collection
```
...
8100 Array<Bullet> bullets
-- alloc Enemy --
...
-- Call collect --
8050 int bottomOfStackTemp
MarkConservative(&bottomOfStackTemp, 9976) -> scans stack from 8050 -> 9976
MarkConservative(Capture registers)
```
Enter/exit use similar technique, where the registers are captured and the bottomOfStack is 'locked-in' when the "enter gc free zone" call is made.
```
8100 Array<Bullet> bullets
-- EnterGCFreeZone --
8088 int bottomOfStackTemp
thread->setBottomOfStack(&bottomOfStackTemp)
thread->captureRegisters()
return
* any changes here will not affect GC
```
Now, when another thread does a collection, the gc-free thread can be scanned from 8088 to 9976, regardless of any stuff happening lower dowsn the stack.
### Not Called From Main
Top of stack can be tricky to get right when a gui framework does not really have a "main".
```
10000
-----------------------------------------------
9996 startup temp variable
9992 startup temp variable
-- main function --
setupWindows(onReadyCallback)......
...
8000
-- onReadyCallback --
7976 int t0
SetTopOfStack(&t0,false) -> 7966
__hxcpp_main();
setOnFrameCallack(haxeOnFrame)
return;
```
Later, the haxeOnFrame callback is trigger, but not "below" `__hxcpp_main`
```
9800 -- haxeOnFrame ---
// Top of stack will be below bottom of stack.
```
Solutions:
- Make sure you get in at top of main
+ may scan too much?
- Ratchet up top-of-stack in callbacks, inForce = false
+ gc_set_top_of_stack(void * inTopOfStack,bool inForce);
- Detach main thread after hxcpp_main and reattach each callback
+ android solution because render callbacks happen on different threads
+ gc_set_top_of_stack(&base,true); // attach
+ gc_set_top_of_stack(0,true); // detach
### Debugging.
- in debug mode, hxcpp will check for calls from unattached threads
- hxcpp can log conservative ranges. With a native debugger you can check the address of
your local variables and ensure they are included.
- hxcpp will scan native objects on the stack, but will not follow non-haxe pointers to other objects, so additional GC roots may be required.

View File

@ -0,0 +1,82 @@
Compiler
--------
Compilers are run over each of the changed files in each of the filegroups in a target to create object files, which are then linked into the target. Modification dates or hashes are used to tell if files need recompiling, of if the object file can be reused.
- *flag* - Add single arg to command-line.
```xml
<flag value="value" tag="tag" />
```
+ value = text for flag added to command line
+ tag = optional filter to restrict flag to files with matching tag. See [Tags.md](Tags.md).
- *cflag/cppflag/objcflag/mmflag* - Add flag when compiling specific file types.
```xml
<cflag value="value" />
<cppflag value="value" />
<objcflag value="value" />
<mmflag value="value" />
```
+ cflag = only added to .c files
+ cppflag = only added to .cpp files
+ objcflag = only added to .objc files
+ mmflag = only added to .mm objc++ files
- *pchflag* - Add flag when compiling precompiled header .h files.
```xml
<pchflag value="value" />
```
+ pchflag = Usually `["-x", "c++-header"]` for apple to specify the "identity" of the header
- *pch* - Set the precompiled header style - "gcc" or "msvc".
```xml
<pch value="gcc|msvc" />
```
- *objdir* - set name of directory used to store object files. Should be unique for given set of compiler flags to avoid linking against wrong architecture.
```xml
<objdir value="obj/somewhere" />
```
+ value = usually built programmatically, like `obj/msvc${MSVC_VER}-rt${OBJEXT}${OBJCACHE}${XPOBJ}`
- *output* - Flag used to specifying compiler output name.
```xml
<outflag value="-flag" />
```
+ value = flag value. Note that it should contain a space character
if the actual name should be a separate argument, like "-o ", or "-o"/"-out:" if it does not.
- *exe* = Override the executable command specified in the compiler attribute.
```xml
<exe name="command" />
```
+ name = command. Usually you would use 'path' to add the directory, then this is just the filename part.
- *ext* - Specify the object file extension
```xml
<ext name=".obj" />
```
+ name = extension, including ".". Usually ".o" or ".obj".
- *getversion* - The command-line used to create text describing the version of the compiler.
This is used for working out if the compiler has changed, and therefore the objs need recompiling.
```xml
<getversion value="command" />
```
+ value = command to run. It defaults to `compiler --version` which is usual for gcc based compilers.
Setting it empty will disable caching.
- *section* - Group entries - usually sharing common condition
```xml
<section > </section>
```
- *include* - include compiler options from another file. Most compilers should include `<include name="toolchain/common-defines.xml" />` to add defines used by hxcpp.
```xml
<include name="filename" />
```

View File

@ -0,0 +1,90 @@
Defines
-------
There are a number of standard defines you can use to control the hxcpp build. Some of these are used by the haxe compiler, and affect then generated code. Others apply to the build tool and affect how the code is compiled.
Defines affecting how the code is generated. These need to be in the command line when calling haxe.
| Define | Meaning |
|-------------------------|--------------------|
| *HXCPP_DEBUGGER* | Add extra macros required by debugger. Usually added automatically be debugger haxelib |
| *HXCPP_GC_GENERATIONAL* | Enable experimental generational garbage collector |
| *annotate_source* | Add additional annotations to source code - useful for developing hxcpp |
| *dll_export* | Export hxcpp runtime symbols |
| *file_extension* | Set the extension (without the dot) of generated files. eg "-D file_extension=mm" for objc++ code |
| *force_native_property* | Make dynamic access of fields call property getters/setters where appropriate |
| *include_prefix* | Place all generated include files in a sub-directory, eg "-D include_prefix=hxinc". Useful for avoiding name clashes |
| *no-compilation* | Generate the code, but do not compile it |
| *no-debug* | Do not generate debug macros in code |
| *nocppiaast* | Use legacy cppia generation instead of new more recent changes |
| *objc* | Generate objective-c++ classes |
| *scriptable* | Enable extra runtime information required for scripting |
Defines affecting how the code is compiled. These can be on the command line when calling haxe, or added via the hxcpp build environment.
| Define | Meaning |
|-------------------------|--------------------|
| *HXCPP_GC_MOVING* | Allow garbage collector to move memory to reduce fragmentation |
| *HXCPP_GC_SUMMARY* | Print small profiling summary at end of program |
| *HXCPP_GC_DYNAMIC_SIZE* | Monitor GC times and expand memory working space if required |
| *HXCPP_GC_BIG_BLOCKS* | Allow working memory greater than 1 Gig |
| *HXCPP_GC_DEBUG_LEVEL* | Number 1-4 indicating additional debugging in GC |
| *HXCPP_DEBUG_LINK* | Add symbols to final binary, even in release mode. |
| *HXCPP_STACK_TRACE* | Have valid function-level stack traces, even in release mode. |
| *HXCPP_STACK_LINE* | Include line information in stack traces, even in release mode. |
| *HXCPP_CHECK_POINTER* | Add null-pointer checks,even in release mode. |
| *HXCPP_PROFILER* | Add profiler support |
| *HXCPP_TELEMETRY* | Add telemetry support |
| *HXCPP_CPP11* | Use c++11 features and link libraries |
| *exe_link* | Generate executable file (rather than dynamic library on android) |
| *static_link* | Generate static library |
| *dll_link* | Generate dynamic library |
Other defines:
| Define | Meaning |
|-------------------------|--------------------|
| *HXCPP_VERBOSE* | Print extra output from build tool. |
| *HXCPP_TIMES* | Show some basic profiling information |
| *HXCPP_NEKO_BUILDTOOL* | Force use of hxcpp.n, rather than compiled BuildTool.exe
| *HXCPP_NO_COLOR* | Do not add colour-codes to tool output |
| *HXCPP_KEEP_TEMP* | Does not delete the files created for file 'embedName' option |
Defines affecting target architecture.
| Define | Meaning |
|-------------------------|--------------------|
| *HXCPP_M32* | Force 32-bit compile for current desktop |
| *HXCPP_M64* | Force 64-bit compile for current desktop |
| *HXCPP_ARMV6* | Compile arm-based devices for armv6 |
| *HXCPP_ARM64* | Compile arm-based devices for 64 bits |
| *HXCPP_ARMV7* | Compile arm-based devices for armv7 |
| *HXCPP_ARMV7S* | Compile arm-based devices for armv7s |
| *HXCPP_LINUX_ARMV7* | Run on a linux ARMv7 device |
| *HXCPP_LINUX_ARM64* | Run on a linux ARM64 device |
| *winrt* | Compile for windowsRt/windows UWP |
| *android* | Compile for android |
| *PLATFORM* | Specify the android platform for NDK compilation |
| *ANDROID_NDK_ROOT* | Specify the location of the android NDK toolchain |
| *ANDROID_NDK_DIR* | Specify the search location for finding the android NDK toolchain |
| *HXCPP_X86* | Compile android for x86 architecture |
| *iphoneos* | Compile for iphone iOS |
| *iphonesim* | Compile for iphone simulator |
| *appletvos* | Compile for apple tvOS |
| *appletvsim* | Compile for apple tvOS simulator |
| *watchos* | Compile for apple watchOS |
| *watchsimulator* | Compile for apple watchOS simulator |
| *webos* | Compile for webOS |
| *tizen* | Compile for Tizen |
| *blackberry* | Compile for Blackberry |
| *emscripten* | Compile for Emscripten |
| *cygwin* | Compile for windows using cygwin |
| *linux* | (Cross) Compile for linux |
| *rpi* | (Cross) Compile for raspberry pi |
| *mingw* | Compile for windows using mingw |
| *HXCPP_MINGW* | Compile for windows using mingw |
| *NO_AUTO_MSVC* | Do not detect msvc location, use the one already in the executable path |
| *HXCPP_WINXP_COMPAT* | Remain compatible with Windows XP. Disables condition variables. No effect on ARM. |

View File

@ -0,0 +1,94 @@
Files
------
The files node defines a group of files that all share the same attributes, including relative directory, default compiler flags and dependencies. The node can be used to define a set of header files on which other files can depend, or a set of source files to be compiled and included in a target.
- *depend* - Declare that all files in the group depend on another file or another file group.
```xml
<depend name="filename" />
<depend files="filesId" />
```
+ name = If the named file changes then then all the files in the group need recompiling.
+ files = If any of the files in the named group changes then then all the files in the group need recompiling.
- *options* - Name of file containing compiler flags. When the cache is not used, Options.txt helps detect when the options have changed, and therefore whether files need recompiling.
```xml
<options name="Options.txt" />
```
- *config* - Name of file to generate that contains the #defines that were active when code was compiled.
```xml
<config name="outfile.h" />
```
- *tag* - Add a default compiler flags tag to all files in group. See [Tags.md](Tags.md).
```xml
<tag value="tag" />
```
- *addTwice* - When compiled to a library, add the library twice to the link line - once at the beginning and once at then end to satisfy linux selective linking.
```xml
<addTwice value="tue" />
```
- *cache* - Use compiler cache for files in group. See [compile cache](../CompileCache.md) for more details.
```xml
<cache value="true" project="name" asLibrary="true" />
```
+ project = name of project used to manage and group object files in the cache
+ asLibrary = link the objs into a .lib file, which can skip unneeded objs, but
will also skip things that rely on static initializers to register handlers, so be careful.
- *include* - Include an external file list
```xml
<include name="filename.xml" />
```
- *section* - Groups block of elements - usually ones that all respect the same if/unless condition.
```xml
<section name="id" /> </section>
```
- *compilerflag* - Add a compilerflag when compiling files in group.
```xml
<compilerflag name="name" value="value" />
<compilerflag value="value" />
```
+ name, value = add 2 flags when compiling
+ value = add 1 flag when compiling
- *nvcc* - This group is compiled with nvcc.
```xml
<nvcc />
```
- *objprefix* - An id prepended to generated obj name to allow alphabetical grouping of similar objs.
```xml
<objprefix value="prefix" />
```
- *precompiledheader* - Use a precompiledheader of given name when compiling group
```xml
<precompiledheader name="name" dir="directory" />
```
+ name = the include used when precompiling these files (without the .h)
+ directory = the location of this file
eg, for `#include <lib/Header.h>`
+ name = "lib/Header"
+ directory = "${haxelib:somelib}/include"
- *file* - Add file to group, with optional attributes
```xml
<file name="filename" tags="tag,tag1" filterout="define" embedName="embed" >
<depend name="filename1" />
<depend name="filename2" />
</file>
```
+ name = name of file - may be absolute or relative to files.dir
+ tags = optional override of group tags. See [Tags.md](Tags.md).
+ filterout = allows files to be skipped at compile-time if the named define exists.
This is useful when the define is set sometime after the file list is parsed.
+ depend name = filename of additional dependency
+ embed = causes the file to be embedded as an extern c++ 'const char *' string constant of the specified name

View File

@ -0,0 +1,97 @@
The Haxe Target
---------------
When compiling from haxe, via hxcpp, a "Build.xml" file is generated in the output directory. The file lists the generated files and dependencies and ultimately includes the "toolchain/haxe-target.xml" file, which describes how to combine these files.
### Include Order
There are a few complications when setting the order in which things are configured, since a particular build might want to:
- set the compiler
- override some compiler settings
- make decisions based on the compiler or settings
- set or use standard file prefixes/suffixes
### Example Sequence
You can see which files are included by setting the HXCPP_VERBOSE define when compiling. One example is for a hypothetical user 'Hugh' on a windows platform:
```
Using makefile: Build.xml
No specified toolchain
- Parsing include: C:/Users/Hugh/dev/hxcpp/toolchain/setup.xml
- Parsing include: C:\Users\Hugh\.hxcpp_config.xml (section "vars")
Using Windows compiler: MSVC
- Parsing include: C:/Users/Hugh/dev/hxcpp/toolchain/finish-setup.xml
- Parsing makefile: C:\Users\Hugh\test\proj\cpp\Build.xml
- Parsing include: C:/Users/Hugh/dev/hxcpp/build-tool/BuildCommon.xml
- Parsing include: C:/Users/Hugh/dev/hxcpp/toolchain/haxe-target.xml
- Parsing include: C:/Users/Hugh/dev/hxcpp/toolchain/msvc-toolchain.xml
- Parsing compiler: C:/Users/Hugh/dev/hxcpp/toolchain/common-defines.xml
- Parsing include: C:\Users\Hugh\.hxcpp_config.xml (section "exes")
```
- setup.xml is read because no custom toolchain is specified, and this just include hxcpp_config
- the 'vars' section of hxcpp_config is read - mainly to setup SDK locations
- the hxcpp build tool then uses internal logic based on host and defines to work out which compiler/toolchain to use
- finish-setup then sets a bunch of standard defines for file-extensions and linking flags based on
the type of toolchain being used.
- The provided buildfile (Build.xml) is then processed. It can use the standard defines from finish-setup.
- Build.xml imports the standard haxe-target buildfile, which adds standard runtime files
- The toolchain file is then parsed - making use of any settings from the main Build.xml and finish-setup.
- This file includes the "common-defines.xml" from the compiler to inject standard haxe compiler flags
- hxcpp_config "exe" is parsed. Historically to add libraries or build-paths to targets.
### Standard Environment
finish-setup.xml is where the conventions are set. These variables include:
- haxelink = dll|static_link|exe
- LIBPREFIX = lib|""
- LIBEXTRA =
+ .iphonesim-64
+ .iphonesim
+ .iphoneos
+ .iphoneos-v7
+ .iphoneos-v7s
+ .iphoneos-64
+ .appletvsim-64
+ .appletvsim
+ .watchos
+ .watchsimulator
+ -x86
+ -v7
+ -64
- HX_LINK_SUFFIX = LIBEXTRA | -19 (msvc 19)
- LIBEXT = .a|.lib
- DBG = ""|"-debug"
- OBJEXT = "-list-of-config-ids" depending on available options
These variables are used by haxe-target - you can use them too. Haxe then builds the "haxe" target, which uses some code like:
```xml
<set name="HAXE_OUTPUT_FILE" value="${LIBPREFIX}${HAXE_OUTPUT_PART}${DBG}" />
<target id="haxe" tool="linker" toolid="${haxelink}" output="${HAXE_OUTPUT_FILE}">
<ext value="${LIBEXTRA}.a" if="static_link" />
<!-- ... -->
<files id="__main__" unless="static_link" />
<files id="__lib__" if="static_link"/>
<files id="__resources__" />
<files id="__externs__" />
<files id="runtime" unless="dll_import" />
<files id="cppia" if="scriptable" />
<lib name="-lpthread" if="linux" unless="static_link" />
<lib name="-ldl" if="linux" unless="static_link" />
</target>
```
Here you can see the various file groups, which are enabled or not depending on the compiler mode, and some standard libraries that are needed for Linux.
### Experimenting With Hxcpp Generated Code/Build.xml
If you are using external cpp code, or using meta-data to inject xml into the build process, and you are getting a compile or link error, then it can be useful to run the hxcpp build tool without re-running haxe. This lets you hand-edit the build file or generated c++ code until you get things to work. Once you have solved the issues using this technique, then you can move the changes back into the injected/external code.
First, compile haxe with '-v' flag. This gives quite a bit of debug, but will include a line like this:
```
haxelib run hxcpp Build.xml haxe -Dhaxe3="1" -Dhaxe_ver="4.000" -Dhxcpp_api_level="332" -Dsource-header="Generated by Haxe 4.0.0" -I"" -I"C:/Users/Hugh/dev/haxe/std/cpp/_std/" -I"C:/Users/Hugh/dev/haxe/std/"
```
To use this, first change directories to your output directory. This will be the one you specified with the "-cpp" haxe compiler option. Then, cut and paste this command into a shell, cmd or batch file.

View File

@ -0,0 +1,86 @@
Linker
------
Generally one linker is run per target to build a static library, dynamic library or exe. The 'id' attribute of the linker specifies whch type of linking is performed.
- *exe* - Overwrite the exe command for this linker.
```xml
<exe name="command" />
```
- *flag* - Add a single link flag.
```xml
<flag value="flag"/>
```
- *ext* - Default extension for generated files - if not overridden by target.
```xml
<ext value=".ext"/>
```
+ value = extension, including "."
- *outflag* - Flag for specifying linker output name.
```xml
<outflag value="-o"/>
```
+ value = linker flag. Note that it should contain a space character
if the actual name should be a separate argument, like "-o ", or "-o"/"-out:" if it does not.
- *section* - Group items - usually sharing common condition
```xml
<section > </section>
```
- *libdir* - A temp directory name to build into. This will capture the extra files the compiler
generates, and then the desired file will be copied to the correct location.
```xml
<libdir name="name"/>
```
- *lib* - Add a library to the link line.
```xml
<lib (name|hxbase|base)="libName" />
```
+ name = the complete name is specified
+ base = the name without compiler-specific extension (.a/.lib) is specified
+ hxbase = the name without extension and architecture (-v7/.iphoinesim) is specified
- *prefix* - Prefix for generated files.
```xml
<prefix value="lib"/>
```
+ value = prefix. This will usually be "lib" or nothing.
- *ranlib* - Whether ranlib needs to be run, and what command to use. Usually only for unix-style static libraries
```xml
<ranlib name="ranlib command"/>
```
- *libpathflag* - Flag used for adding library paths to command line. It will be combined with *lib* entries.
```xml
<libpathflag value="-L"/>
```
- *recreate* - Whether to delete the target file before re-running link command.
The archive "ar" command likes to add obj files to existing archives, so deleting first can help.
```xml
<recreate value="true"/>
```
- *expandAr* - Whether to extract the individual obj files from an archive and add these, rather than
add the archive as a single library. Can solve some link-order and static-initialization issues,
but may make final exe bigger.
```xml
<expandAr value="true"/>
```
- *fromfile* - If the linker supports taking a list of objs in a file, then this is flag for specifying the file.
```xml
<fromfile value="flag" needsQuotes="true" />
```
+ value = flag for specifying file.
If the filename should be a separate argument, then the flag should end with a space.
Usually `@` or `-filelist `. Use empty to disable.
+ needsQuotes = is whether to quote the obj names in the file

View File

@ -0,0 +1,79 @@
Build.xml
----------
The hxcpp build.xml build system is designed to make compiling, cross-compiling and linking easy on a large variety of operating systems and devices. It was originally designed to build the haxe-generated c++ code but has evolved to replace the need for configuration tools in many open source libraries.
### Running
The source code for the tool lives in "tools/hxcpp" in this repo. When compiled, it can be run with the haxe 'haxelib' library tool. This is usually done automatically by the haxe compiler after the cpp code has been generated. It can be done manually like:
```
haxelib run hxcpp build.xml key=value .... [target]
```
### Configuration
The hxcpp build tool is configured using key-value pairs, or just using keys, known internally as 'defines'. These can be set in several ways:
- From system environment variables
- From the command-line, with key=value
- From haxe. Keys defined in haxe with '-D key[=value]' are passed to the build too, where they can influence the build. Certain defines need to be set on the haxe command line so that they can influence the generated code.
- From the the .hxcpp_config.xml file in the users home(profile) directory. This is a good place to set values the apply to the whole machine, like the location of SDKs etc.
- The defines can be manipulated logically from within the build files themselves.
See [Defines.md](Defines.md) for a list of standard defines.
### Format
The compiler specification and target lists all use the same format.
- uses xml parser
- mostly declarative list of files and flags
- order is important
+ overriding values is a valid technique
+ "commands" are run as they are parsed (eg, 'echo')
- conditions via "if" and "unless" node attributes
- substitution via '${VAR}' syntax
- need to define 'default' target
### Conditions/Substitution
Most of the xml nodes support 'if' and 'unless' attributes. These will enable or disable the whole node according the existence or non-existence of a define. These can be combined with a space for "and" or two pipes for "or".
Substitution is supported via the dollars-brace syntax, and does simple text substitution. In addition, there are a few dynamic variables that can be used:
- "${VAR}" - normal replacement
- "${removeQuotes:VAR}" - strips surrounding quotes from VAR, it any
- "${dospath:VAR}" - converts VAR to backwards-slash path
- "${dir:PathWithFilename}" - just the directory part of filename
- "${this_dir}" - the location of the containing build.xml file
### Example
The following code is saved in [example.xml](example.xml) in this directory
```xml
<xml>
<echo value="Hello ${WHO}" if="WHO" unless="SILENT" />
<echo value="You are in ${haxelib:hxcpp}" unless="WHO||SILENT"/>
<error value="Silent and who both specified" if="WHO SILENT"/>
<target id="default" />
</xml>
```
and some example uses:
```
unsetenv SILENT
haxelib run hxcpp example.xml
haxelib run hxcpp example.xml WHO=world default
setenv SILENT 1
haxelib run hxcpp example.xml
haxelib run hxcpp example.xml WHO=world
```
### Details
The build.xml file contains configuration, targets, compilers, linkers and files. The details can be found in this directory.
- [Top Level](TopLevel.md)
- [Files](Files.md)
- [Targets](Targets.md)
- [Compiler](Compiler.md)
- [Linker](Linker.md)
- [Stripper](Stripper.md)
When building from haxe, the "haxe" target is built. You can see the details in [HaxeTarget](HaxeTarget.md).
You can extend the generated Build.xml from haxe code using [Xml injection](XmlInjection.md).

View File

@ -0,0 +1,15 @@
Stripper
--------
A stripper is used to remove debug information in release builds on gcc-like systems. It may contain entries:
- *exe* - Override stripper command
```xml
<exe name="command"/>
```
- *flag* - Add flag to stripper command
```xml
<flag value="flag"/>
```

View File

@ -0,0 +1,31 @@
Tags
----
Tags are identifiers that link compiler flags with specific files. Usually, they are defined in a files group with the 'tags' attribute as a comma separated list, and with the 'tag' attribute on a compiler 'flag' node. Files are then compiled with all the flags that have matching tags.
By restricting tags to certain files, only a sub-set of files needs to be recompiled when conditions change, and files without the relevant tags can reuse their object files. This can save a lot of time, since some flags only apply to a few files.
Files can override the group tags by specifying their own 'tags' attribute. Groups can add tags with the 'tag' node.
Some tags have standard meanings when compiling haxe code:
- *haxe* - The haxe tag adds all the required compiler flags to get haxe-generated code to compile correctly, and should be added to files that depend directly or indirectly on hxcpp.h.
- *static* - This will add the STATIC_LINK define when appropriate, which is used for generating cffi glue. It should be added to cffi code that might generate static libraries.
- *gc* - These flags only affect the garbage-collection files
- *hxstring* - These flags only affect String.cpp
- *optimization tags* - each file is assumed to have exactly 1 optimization tags. If none is explicitly specified, then the default is used depending on whether it is a debug or release build. They are:
+ optim-std = alias for 'debug' or 'release' depending on build
+ debug
+ release
+ optim-none
+ optim-size
Setting one of these tags is useful for compiling your library in release mode, even if haxe has -debug. Some very big files are slow to compile in release mode, so using a less optimized mode can be faster.
The tags attribute can be added to a haxe-generated file using the `@:fileXml` meta, eg:
```haxe
@:fileXml("tags='haxe,optim-none'")
class MyClass { ...
```
Here, the class is compiled with the normal haxe flags, but has the optimizations disabled, which can lead to much faster compiler times in some circumstances.

View File

@ -0,0 +1,82 @@
Targets
-------
Targets are used to produce binaries, or to group other targets. When compiling exes or dynamic libraries, they provide the additional link libraries.
By default, hxcpp will try to compile the 'default' target, so it is easiest to define this one - perhaps by simply adding a dependence on your other targets(s).
The target is defined with a 'toolid' attribute; exe, static_link or dll. This defines which linker is run, but many of the target entries will be the same even if the linker is changed.
Targets can contain the following nodes:
- *subTargetName* - Build another target before building this one.
```xml
<target id="subTargetName" />
```
- *merge* - Combine fields from another target. This is useful if you want a target to function as static library or dll when compiled in its own, but also allow it to be used as a list of object files if another target wants to link in the object files directly.
```xml
<merge id="otherTargetName" />
```
- *files* - Add a named group of compiled files to target.
```xml
<files id="filesId"/>
```
- *section* - Group items - usually sharing common condition
```xml
<section > </section>
```
- *lib* - Add a library to the link line.
```xml
<lib (name|hxbase|base)="libName" />
```
+ name = the complete name is specified
+ base = the name without compiler-specific extension (.a/.lib) is specified
+ hxbase = the name without extension and architecture (-v7/.iphoinesim) is specified
- *flag* - Add a single link flag.
```xml
<flag value="flag"/>
```
- *vflag* - Add a pair of link flags.
```xml
<vflag name="flag1" value="flag2"/>
```
- *depend* - Target depends on given filename.
```xml
<depend name="filename"/>
```
- *dir* - Add a directory to the targets directory list. These directories will get removed then the target is cleaned.
```xml
<dir name="tempPath"/>
```
- *outdir* - Directory for build results - including "copyFile" targets
```xml
<outdir name="path"/>
```
- *ext* - Extension for generated files.
```xml
<ext name=".ext"/>
```
+ ext = extension - should contain "."
- *builddir* - The directory from which the targets build commands are run, and therefore the
relative base for some filenames, and destination for some compiler generated temps.
```xml
<builddir name="path"/>
```
- *libpath* Add library search path to build command
```xml
<libpath name="directory"/>
```
+ name = directory. The particular linker will add the required flags

View File

@ -0,0 +1,139 @@
Structure of the top-level
---------------------------
The top-level nodes live inside an "xml" node, and can be:
- *set* - Set a "define", define being a general variable.
```xml
<set name="name" value="1" />
```
- *setenv* - Sets an hxcpp define and an environment variable for child processes.
```xml
<setenv name="name" value="1" />
```
- *unset* - Unset a define. if="name" will no longer be true
```xml
<unset name="name" />
```
- *setup* - Used internally to call custom setup code to find SDKs etc.
```xml
<setup name="androidNdk|blackberry|msvc|pdbserver|mingw|emscripten|nvcc" />
```
- *echo* - Print value to console. Good for debugging.
```xml
<echo value="text" />
```
- *error* - Print value to console and force error. Good for checking prerequisites.
```xml
<error value="error message" />
```
- *pleaseUpdateHxcppTool* - Used to tell people updating git version that they need to recompile the build tool.
```xml
<pleaseUpdateHxcppTool version="1" />
```
- *path* - Add an directory to the exe search path.
```xml
<path name="directory_to_add" />
```
- *mkdir* - Create a directory.
```xml
<mkdir name="directory" />
```
- *section* - Groups block of elements - usually ones that all respect the same if/unless condition.
```xml
<section name="id" /> </section>
```
- *copy* - Copy file when node is parsed.
```xml
<copy to="destination" from="src" />
```
- *import*/*include* - Read xml from another file. 'import' resets the relative base to the new file, include does not.
```xml
<import name="filename" section="filter" noerror="true" />
<include name="filename" section="filter" noerror="true" />
```
+ noerror - setting the optional noerror allows the file to be missing
+ section - setting the optional section will only read the named section from the xml file. Used by hxcpp_config.xml.
- *pragma* - Only include build file once, even with multiple include statements.
```xml
<pragma once="true" />
```
- *nvccflag* - Add flag to all nvcc compiles.
```xml
<nvccflag name="?name" value="-IincludePath" />
```
- *nvcclinkflag* - Add flag when linking with nvcc code.
```xml
<nvcclinkflag name="?name" value="-arch=sm_30" />
```
- *files* - Define a file group, and set default tags.
```xml
<files dir="dir" name="name" tags="tag1,tag2,tag3" >
...
</files>
```
+ dir = directory to which the filenames in the group are relative
+ tags = comma separated list of flags tags
- *target* - Define a target, and set its toolid(link mode) and output name.
```xml
<target name="name" overwrite="true" append="true" tool="linker" toolid="${haxelink}" output="filename" >
...
</target>
```
- *copyFile* - Copy a file after given toolId is run into target output directory
```xml
<copyFile name="destination" from="src" allowMissing="true" overwrite="true" toolId="filter" >
```
- *magiclib* - Internal for replacing dlls with object files
```xml
<magiclib name="libname" replace="old dll" />
```
- *compiler* - Define a compiler.
```xml
<compiler id="id" exe="command" replace="true" >
...
</compiler>
```
+ Use optional 'replace' to overwrite, otherwise append
+ It is assumed only 1 compiler is active
+ exe can be overridden in the body of the definition
- *stripper* - Define a stripper, to remove debug information for release from gcc executables
```xml
<stripper exe="command" replace="true" > </stripper>
```
+ Use optional 'replace' to overwrite, otherwise append
- *linker* - Define a linker.
```xml
<linker id="id" exe="command" replace="true" > </linker>
```
+ Use optional 'replace' to overwrite, otherwise append
+ id could be 'static_link', 'dll' or 'exe'. Usually all 3 linkers are defined.
+ exe can be overridden in the body of the definition
- *prelinker* - Define a prelinker.
```xml
<prelinker name="id" replace="true" />
...
</prelinker>
```

View File

@ -0,0 +1,23 @@
Xml Injection
-------------
When using external code in hxcpp, it is often useful to add libraries, include paths or compiler flags to the build process. This can be done with the `@:buildXml` class meta-data. eg,
```haxe
@:buildXml("
<target id='haxe'>
<lib name='${haxelib:nme}/lib/${BINDIR}/libnme${LIBEXTRA}${LIBEXT}'/>
</target>
")
@:keep
class StaticNme
{
...
```
So, by referencing a given class (you just 'import' the class, no need to use it because it has the @:keep meta-data), the xml fragment is also included.
Here, the xml fragment is copied verbatim into the generated Build.xml immediately after the standard file lists. This example adds a library to the haxe target, but you could also add flags to files nodes, or files to another files node or target. Another possibility is to add an include command to pull in a whole external xml file. This can help avoid some syntax awkwardness needed when quoting strings in meta-data, and allows a normal xml editor to be used.
It is also possible to replace the `__main__` file group to skip the standard initialization code and use a custom bootstrap procedure.

View File

@ -0,0 +1,6 @@
<xml>
<echo value="Hello ${WHO}" if="WHO" unless="SILENT" />
<echo value="You are in ${haxelib:hxcpp}" unless="WHO||SILENT"/>
<error value="Silent and who both specified" if="WHO SILENT"/>
<target id="default" />
</xml>

View File

@ -0,0 +1,14 @@
{
"name": "hxcpp",
"url": "https://github.com/HaxeFoundation/hxcpp/",
"license": "BSD",
"tags": ["haxe", "hxcpp", "cpp"],
"description": "Hxcpp is the runtime support for the C++ backend of the Haxe compiler. This contains the headers, libraries and support code required to generate a fully compiled executable from Haxe code.",
"version": "4.3.0",
"releasenote": "See Changes.md",
"contributors": ["gamehaxe", "HaxeFoundation"],
"binaryversion": 48,
"dependencies": {
}
}

View File

@ -0,0 +1,5 @@
<project name="hxcpp" url="http://gamehaxe.com/" license="BSD">
<user name="gamehaxe"/>
<description>Hxcpp is the runtime support for the c++ backend of the haxe compiler. This release constains the headers, libraries and support code required to generate a fully compiled executable from haxe code.</description>
<version name="3.1.0">See Changes.txt</version>
</project>

View File

@ -0,0 +1,343 @@
package hxcpp;
import haxe.io.Path;
import sys.FileSystem;
class Builder
{
public var debug:Bool;
public var verbose:Bool;
public function new(inArgs:Array<String>)
{
debug = false;
verbose = false;
var targets = new Map<String, Array<String>>();
var buildArgs = new Array<String>();
try
{
var clean = false;
var defaultTarget = true;
for(arg in inArgs)
{
if (arg=="-debug")
{
debug = true;
continue;
}
else if (arg=="-v" || arg=="-verbose")
{
verbose = true;
Sys.putEnv("HXCPP_VERBOSE", "1");
continue;
}
if (arg=="clean")
{
clean = true;
continue;
}
var parts = arg.split("-");
var linkStatic = allowStatic();
var linkNdll = allowNdll();
var explicitNdll = false;
if (parts[0]=="static")
{
linkNdll = false;
parts.shift();
}
else if (parts[0]=="ndll")
{
linkStatic = false;
explicitNdll = true;
parts.shift();
}
var target = parts.shift();
if (target=="default")
target = getDefault();
switch(target)
{
case "ios", "android", "blackberry", "tizen", "emscripten", "webos", "windows", "msvc", "linux", "mac", "mingw", "tvos":
defaultTarget = false;
if (linkStatic)
{
var stat = "static-" + target;
targets.set(stat, parts);
if (target=="ios" && wantLegacyIosBuild())
{
var stat = "static-" + "ioslegacy";
targets.set(stat, parts);
}
}
if (linkNdll && target!="ios" && target!="emscripten" && target!="tvos" /*&& (target!="mingw" || explicitNdll)*/ )
targets.set(target, parts);
default:
if (arg.substr(0,2)=="-D")
buildArgs.push(arg);
else
throw "Unknown arg '" + arg + "'";
}
}
if (clean)
{
if (!cleanAll(buildArgs))
return;
if (defaultTarget) // Just clean
return;
}
if (defaultTarget)
{
var target = getDefault();
if (target!="mingw")
targets.set(target,[]);
targets.set("static-" +target,[]);
onEmptyTarget();
Sys.println("\nUsing default = " + target);
}
for(target in targets.keys())
{
var archs = targets.get(target);
var validArchs = new Map<String, Array<String>>();
var isStatic = false;
if (target.substr(0,7)=="static-")
{
isStatic = true;
target = target.substr(7);
}
var staticFlags = isStatic ? ["-Dstatic_link"] : [];
if (target=="ios" || target=="tvos")
staticFlags = ["-DHXCPP_CPP11"];
switch(target)
{
case "linux":
if (wantLinux32())
validArchs.set("m32", ["-D"+target, "-DHXCPP_M32"].concat(staticFlags) );
validArchs.set("m64", ["-D"+target, "-DHXCPP_M64"].concat(staticFlags) );
case "mac":
if (wantMac32())
validArchs.set("m32", ["-D"+target, "-DHXCPP_M32"].concat(staticFlags) );
validArchs.set("m64", ["-D"+target, "-DHXCPP_M64"].concat(staticFlags) );
case "windows":
validArchs.set("m32", ["-D"+target, "-DHXCPP_M32"].concat(staticFlags) );
if (wantWindows64())
validArchs.set("m64", ["-D"+target, "-DHXCPP_M64"].concat(staticFlags) );
if (wantWindowsArm64())
validArchs.set("arm64", ["-D"+target, "-DHXCPP_ARM64"].concat(staticFlags) );
case "msvc":
if (isStatic)
{
validArchs.set("2013m32", ["-D"+target, "-DHXCPP_M32", "HXCPP_MSVC_VER=120"].concat(staticFlags) );
validArchs.set("2015m32", ["-D"+target, "-DHXCPP_M32", "HXCPP_MSVC_VER=140"].concat(staticFlags) );
if (wantWindows64())
{
validArchs.set("2013m64", ["-D"+target, "-DHXCPP_M64", "HXCPP_MSVC_VER=120"].concat(staticFlags) );
validArchs.set("2015m64", ["-D"+target, "-DHXCPP_M64", "HXCPP_MSVC_VER=140"].concat(staticFlags) );
}
}
else
{
validArchs.set("m32", ["-D"+target, "-DHXCPP_M32"] );
if (wantWindows64())
validArchs.set("m64", ["-D"+target, "-DHXCPP_M64"] );
}
case "mingw":
validArchs.set("m32", ["-Dwindows", "-DHXCPP_MINGW", "-DHXCPP_M32"].concat(staticFlags) );
case "ios", "ioslegacy":
validArchs.set("armv6", ["-Diphoneos"].concat(staticFlags) );
validArchs.set("armv7", ["-Diphoneos", "-DHXCPP_ARMV7"].concat(staticFlags) );
validArchs.set("armv7s", ["-Diphoneos", "-DHXCPP_ARMV7S"].concat(staticFlags) );
validArchs.set("arm64", ["-Diphoneos", "-DHXCPP_ARM64", "-DHXCPP_M64"].concat(staticFlags) );
//validArchs.push("armv64");
validArchs.set("x86", ["-Diphonesim"].concat(staticFlags) );
validArchs.set("x86_64", ["-Diphonesim", "-DHXCPP_M64"].concat(staticFlags) );
case "android":
if( archs.length == 0 )
throw("You must specify the archs you want for android");
validArchs.set("armv5", ["-Dandroid"].concat(staticFlags) );
validArchs.set("armv7", ["-Dandroid", "-DHXCPP_ARMV7"].concat(staticFlags) );
validArchs.set("arm64", ["-Dandroid", "-DHXCPP_ARM64"].concat(staticFlags) );
validArchs.set("x86", ["-Dandroid", "-DHXCPP_X86"].concat(staticFlags) );
validArchs.set("x86_64", ["-Dandroid", "-DHXCPP_X86_64"].concat(staticFlags) );
case "blackberry":
validArchs.set("armv7", ["-Dblackberry"].concat(staticFlags) );
validArchs.set("x86", ["-Dblackberry", "-Dsimulator"].concat(staticFlags) );
case "tizen":
validArchs.set("armv7", ["-Dtizen"].concat(staticFlags) );
validArchs.set("x86", ["-Dtizen", "-Dsimulator"].concat(staticFlags) );
case "emscripten":
validArchs.set("x86", ["-Demscripten"].concat(staticFlags) );
case "webos":
validArchs.set("armv7", ["-Dwebos"].concat(staticFlags) );
case "tvos":
validArchs.set("arm64", ["-Dappletvos", "-DHXCPP_ARM64", "-DHXCPP_M64", "-DENABLE_BITCODE"].concat(staticFlags) );
// NOTE: removed as there's no 32bit support for the AppleTV simulator
//validArchs.set("x86", ["-Dappletvsim", "-DENABLE_BITCODE"].concat(staticFlags) );
validArchs.set("x86_64", ["-Dappletvsim", "-DHXCPP_M64", "-DENABLE_BITCODE"].concat(staticFlags) );
}
var valid = new Array<String>();
for(key in validArchs.keys())
valid.push(key);
var buildArchs = archs.length==0 ? valid : archs;
for(arch in buildArchs)
{
if (validArchs.exists(arch))
{
var flags = validArchs.get(arch);
if (debug)
flags.push("-Ddebug");
flags = flags.concat(buildArgs);
runBuild(target, isStatic, arch, flags);
}
}
}
}
catch( e:Dynamic )
{
if (e!="")
Sys.println(e);
showUsage(false);
}
}
public function allowNdll() { return true; }
public function allowStatic() { return true; }
public function wantLegacyIosBuild() { return false; }
public function wantWindows64() { return false; }
public function wantMac32() { return false; }
public function wantLinux32() { return false; }
public function wantWindowsArm64() { return false; }
public function runBuild(target:String, isStatic:Bool, arch:String, buildFlags:Array<String>)
{
var args = ["run", "hxcpp", getBuildFile() ].concat(buildFlags);
Sys.println('\nBuild $target, link=' + (isStatic?"lib":"ndll")+' arch=$arch');
Sys.println("haxelib " + args.join(" "));
if (Sys.command("haxelib",args)!=0)
{
Sys.println("#### Error building " + arch);
Sys.exit(-1);
}
}
public function getBuildFile()
{
return "Build.xml";
}
public function getCleanDir()
{
return "obj";
}
public function cleanAll(inBuildFlags:Array<String>) : Bool
{
var args = ["run", "hxcpp", getBuildFile(), "clean", "-DHXCPP_CLEAN_ONLY"].concat(inBuildFlags);
Sys.println("haxelib " + args.join(" "));
if (Sys.command("haxelib",args)!=0)
{
Sys.println("#### Error cleaning");
Sys.exit(-1);
}
return true;
}
public function onEmptyTarget() : Void
{
showUsage(true);
}
static public function deleteRecurse(inDir:String) : Void
{
if (FileSystem.exists(inDir))
{
var contents = FileSystem.readDirectory(inDir);
for(item in contents)
{
if (item!="." && item!="..")
{
var name = inDir + "/" + item;
if (FileSystem.isDirectory(name))
deleteRecurse(name);
else
FileSystem.deleteFile(name);
}
}
FileSystem.deleteDirectory(inDir);
}
}
public function showUsage(inShowSpecifyMessage:Bool) : Void
{
var link = allowStatic() && allowNdll() ? "[link-]" : "";
Sys.println("Usage : neko build.n [clean] " + link +
"target[-arch][-arch] ...] [-debug] [-verbose] [-D...]");
Sys.println(" target : ios, android, windows, linux, mac, mingw, tvos");
Sys.println(" default (=current system)");
if (link!="")
{
Sys.println(" link : ndll- or static-");
Sys.println(" (none specified = both link types, mingw static only");
}
Sys.println(" arch : -armv5 -armv6 -armv7 -arm64 -x86 -x86_64 -m32 -m64");
Sys.println(" (none specified = all valid architectures");
Sys.println(" -D... : defines passed to hxcpp build system");
if (link!="")
Sys.println(" eg: neko build.n clean ndll-mac-m32-m64 = rebuild both mac ndlls");
if (inShowSpecifyMessage)
Sys.println(" Specify target or 'default' to remove this message");
}
public function getDefault() : String
{
var sys = Sys.systemName();
if (new EReg("window", "i").match(sys))
return "windows";
else if (new EReg("linux", "i").match(sys))
return "linux";
else if (new EReg("mac", "i").match(sys))
return "mac";
else
throw "Unknown host system: " + sys;
return "";
}
public static function main()
{
new Builder( Sys.args() );
}
}

View File

@ -0,0 +1,21 @@
package hxcpp;
class NekoInit
{
public static function nekoInit(inModuleName:String) : Bool
{
var init = neko.Lib.load(inModuleName, "neko_init", 5);
if (init != null)
{
init( function(s) return new String(s),
function(len:Int) { var r = []; if (len > 0) r[len - 1] = null; return r; },
null,
true,
false);
return true;
}
return false;
}
}

View File

@ -0,0 +1,24 @@
package hxcpp;
#if (hxcpp_api_level>=330)
class StaticMysql { }
#else
@:cppFileCode( 'extern "C" int mysql_register_prims();')
@:buildXml("
<target id='haxe'>
<lib name='${HXCPP}/lib/${BINDIR}/libmysql5${LIBEXTRA}${LIBEXT}'/>
<lib name='ws2_32.lib' if='windows'/>
</target>
")
@:keep class StaticMysql
{
static function __init__()
{
untyped __cpp__("mysql_register_prims();");
}
}
#end

View File

@ -0,0 +1,23 @@
package hxcpp;
#if (hxcpp_api_level>=330)
class StaticRegexp { }
#else
@:cppFileCode( 'extern "C" int regexp_register_prims();')
@:buildXml("
<target id='haxe'>
<lib name='${HXCPP}/lib/${BINDIR}/libregexp${LIBEXTRA}${LIBEXT}'/>
</target>
")
@:keep class StaticRegexp
{
static function __init__()
{
untyped __cpp__("regexp_register_prims();");
}
}
#end

View File

@ -0,0 +1,24 @@
package hxcpp;
#if (hxcpp_api_level>=330)
class StaticSqlite { }
#else
@:cppFileCode( 'extern "C" int sqlite_register_prims();')
@:buildXml("
<target id='haxe'>
<lib name='${HXCPP}/lib/${BINDIR}/libsqlite${LIBEXTRA}${LIBEXT}'/>
<lib name='-lpthread' if='linux'/>
</target>
")
@:keep class StaticSqlite
{
static function __init__()
{
untyped __cpp__("sqlite_register_prims();");
}
}
#end

View File

@ -0,0 +1,25 @@
package hxcpp;
#if (hxcpp_api_level>=330)
class StaticStd { }
#else
@:cppFileCode( 'extern "C" int std_register_prims();')
@:buildXml("
<target id='haxe'>
<lib name='${HXCPP}/lib/${BINDIR}/libstd${LIBEXTRA}${LIBEXT}'/>
<lib name='ws2_32.lib' if='windows' unless='static_link' />
</target>
")
@:keep class StaticStd
{
static function __init__()
{
untyped __cpp__("std_register_prims();");
}
}
#end

View File

@ -0,0 +1,29 @@
package hxcpp;
#if (hxcpp_api_level>=330)
class StaticZlib { }
#else
@:cppFileCode( 'extern "C" int zlib_register_prims();')
#if HXCPP_LINK_NO_ZLIB
@:buildXml("
<import name='${HXCPP}/project/libs/zlib/Build.xml'/>
")
#else
@:buildXml("
<target id='haxe'>
<lib name='${HXCPP}/lib/${BINDIR}/libzlib${LIBEXTRA}${LIBEXT}'/>
</target>
")
#end
@:keep class StaticZlib
{
static function __init__()
{
untyped __cpp__("zlib_register_prims();");
}
}
#end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,498 @@
#ifndef HX_DYNAMIC_H
#define HX_DYNAMIC_H
// --- Dynamic ---------------------------------------------------------------
//
// The Dynamic class views all classes through the hx::Object interface, and
// provides generic access to its pointer.
// It uses dynamic_cast to provide strongly-typed access to the real class.
namespace hx { class Interface; }
class HXCPP_EXTERN_CLASS_ATTRIBUTES Dynamic : public hx::ObjectPtr<hx::Object>
{
typedef hx::ObjectPtr<hx::Object> super;
public:
Dynamic() {};
Dynamic(int inVal);
Dynamic(short inVal);
Dynamic(unsigned int inVal);
Dynamic(unsigned short inVal);
Dynamic(unsigned char inVal);
Dynamic(signed char inVal);
Dynamic(const cpp::CppInt32__ &inVal);
Dynamic(bool inVal);
Dynamic(double inVal);
Dynamic(float inVal);
Dynamic(cpp::Int64 inVal);
Dynamic(cpp::UInt64 inVal);
Dynamic(hx::Object *inObj) : super(inObj) { }
Dynamic(const String &inString);
Dynamic(const null &inNull) : super(0) { }
Dynamic(const Dynamic &inRHS) : super(inRHS.mPtr) { }
explicit Dynamic(const HX_CHAR *inStr);
Dynamic(const cpp::Variant &inRHS) : super(inRHS.asDynamic()) { }
template<typename T>
Dynamic(const hx::Native<T *> &inInterface):super(inInterface.ptr ? inInterface->__GetRealObject() : (hx::Object *)0 ) { }
#if !defined(__GNUC__) || (defined(__WORDSIZE) && (__WORDSIZE != 64))
Dynamic(long inVal);
Dynamic(unsigned long inVal);
#endif
#ifdef __OBJC__
#ifdef HXCPP_OBJC
Dynamic(const id inObjc);
#endif
#endif
template<typename T,typename S>
explicit Dynamic(const cpp::Struct<T,S> &inRHS) { *this = inRHS; }
template<typename T>
explicit Dynamic(const cpp::Pointer<T> &inRHS) { *this = inRHS; }
void Set(bool inVal);
void Set(int inVal);
void Set(double inVal);
void Set(float inVal);
template<typename RESULT> RESULT StaticCast() const;
inline operator double () const { return mPtr ? mPtr->__ToDouble() : 0.0; }
inline operator float () const { return mPtr ? (float)mPtr->__ToDouble() : 0.0f; }
inline operator int () const { return mPtr ? mPtr->__ToInt() : 0; }
inline operator unsigned int () const { return mPtr ? mPtr->__ToInt() : 0; }
inline operator short () const { return mPtr ? mPtr->__ToInt() : 0; }
inline operator unsigned short () const { return mPtr ? mPtr->__ToInt() : 0; }
inline operator unsigned char () const { return mPtr ? mPtr->__ToInt() : 0; }
inline operator char () const { return mPtr ? mPtr->__ToInt() : 0; }
inline operator signed char () const { return mPtr ? mPtr->__ToInt() : 0; }
inline operator bool() const { return mPtr && mPtr->__ToInt(); }
inline operator cpp::Int64() const { return mPtr ? mPtr->__ToInt64() : 0; }
inline operator cpp::UInt64() const { return mPtr ? mPtr->__ToInt64() : 0; }
// Conversion to generic pointer requires you to tag the class with a typedef
template<typename T>
inline operator typename hx::Native<T *> () const {
return hx::Native<T *>(dynamic_cast<T *>(mPtr));
}
//inline operator cpp::Variant() const { return cpp::Variant(mPtr); }
#ifdef __OBJC__
#ifdef HXCPP_OBJC
#ifdef OBJC_ARC
inline operator id() const { return mPtr ? (__bridge id)mPtr->__GetHandle() : 0; }
#else
inline operator id() const { return mPtr ? (id)mPtr->__GetHandle() : 0; }
#endif
#endif
#endif
inline bool operator !() const { return !mPtr || !mPtr->__ToInt(); }
hx::IndexRef operator[](int inIndex);
inline Dynamic __get(int inIndex) const { return mPtr->__GetItem(inIndex); }
template<typename SOURCE_>
Dynamic(const hx::ObjectPtr<SOURCE_> &inObjectPtr) :
hx::ObjectPtr<hx::Object>(inObjectPtr.mPtr) { }
Dynamic Default(const Dynamic &inDef) { return mPtr ? *this : inDef; }
template<typename RETURN_>
RETURN_ Cast() const { return RETURN_(*this); }
template<typename CLASS_>
bool IsClass() { return CLASS_(mPtr,false).mPtr; }
static void __boot();
inline bool IsNumeric() const
{
if (!mPtr) return false;
int t = mPtr->__GetType();
return t==vtInt || t==vtFloat;
}
inline bool IsBool() const
{
if (!mPtr) return false;
int t = mPtr->__GetType();
return t==vtBool;
}
int Compare(const Dynamic &inRHS) const
{
if (mPtr==0) return inRHS.mPtr==0 ? 0 : -1;
if (inRHS.mPtr==0) return -1;
#if (HXCPP_API_LEVEL>=331)
return mPtr->__Compare(inRHS.mPtr);
#else
return mPtr->__Compare(inRHS.mPtr->__GetRealObject());
#endif
}
bool operator==(const null &inRHS) const { return mPtr==0; }
bool operator!=(const null &inRHS) const { return mPtr!=0; }
bool operator == (const Dynamic &inRHS) const
{
// Comparing pointers fails in the case on Nan==Nan
//if (mPtr==inRHS.mPtr) return true;
if (!mPtr && !inRHS.mPtr) return true;
if (!mPtr || !inRHS.mPtr) return false;
#if (HXCPP_API_LEVEL>=331)
return mPtr->__Compare(inRHS.mPtr)==0;
#else
return mPtr->__Compare(inRHS.mPtr->__GetRealObject())==0;
#endif
}
bool operator != (const Dynamic &inRHS) const
{
// Comparing pointers fails in the case on Nan==Nan
//if (mPtr==inRHS.mPtr) return true;
if (!mPtr && !inRHS.mPtr) return false;
if (!mPtr || !inRHS.mPtr) return true;
#if (HXCPP_API_LEVEL>=331)
return mPtr->__Compare(inRHS.mPtr)!=0;
#else
return mPtr->__Compare(inRHS.mPtr->__GetRealObject())!=0;
#endif
}
bool operator == (const cpp::Variant &inRHS) const { return (*this) == Dynamic(inRHS); }
bool operator != (const cpp::Variant &inRHS) const { return (*this) != Dynamic(inRHS); }
#define DYNAMIC_COMPARE_OP( op ) \
bool operator op (const String &inRHS) const { return mPtr && ((String)(*this) op inRHS); } \
bool operator op (double inRHS) const { return IsNumeric() && ((double)(*this) op inRHS); } \
bool operator op (cpp::Int64 inRHS) const { return IsNumeric() && ((cpp::Int64)(*this) op inRHS); } \
bool operator op (cpp::UInt64 inRHS) const { return IsNumeric() && ((cpp::Int64)(*this) op inRHS); } \
bool operator op (float inRHS) const { return IsNumeric() && ((double)(*this) op inRHS); } \
bool operator op (int inRHS) const { return IsNumeric() && ((double)(*this) op (double)inRHS); } \
bool operator op (unsigned int inRHS) const { return IsNumeric() && ((double)(*this) op (double)inRHS); } \
bool operator op (short inRHS) const { return IsNumeric() && ((double)(*this) op (double)inRHS); } \
bool operator op (unsigned short inRHS) const { return IsNumeric() && ((double)(*this) op (double)inRHS); } \
bool operator op (signed char inRHS) const { return IsNumeric() && ((double)(*this) op (double)inRHS); } \
bool operator op (unsigned char inRHS) const { return IsNumeric() && ((double)(*this) op (double)inRHS); } \
bool operator op (bool inRHS) const { return IsBool() && ((double)(*this) op (double)inRHS); } \
bool operator != (const String &inRHS) const { return !mPtr || ((String)(*this) != inRHS); }
bool operator != (double inRHS) const { return !IsNumeric() || ((double)(*this) != inRHS); }
bool operator != (cpp::Int64 inRHS) const { return !IsNumeric() || ((cpp::Int64)(*this) != inRHS); }
bool operator != (cpp::UInt64 inRHS) const { return !IsNumeric() || ((cpp::Int64)(*this) != inRHS); }
bool operator != (float inRHS) const { return !IsNumeric() || ((double)(*this) != inRHS); }
bool operator != (int inRHS) const { return !IsNumeric() || ((double)(*this) != (double)inRHS); }
bool operator != (unsigned int inRHS) const { return !IsNumeric() || ((double)(*this) != (double)inRHS); }
bool operator != (short inRHS) const { return !IsNumeric() || ((double)(*this) != (double)inRHS); }
bool operator != (unsigned short inRHS) const { return !IsNumeric() || ((double)(*this) != (double)inRHS); }
bool operator != (signed char inRHS) const { return !IsNumeric() || ((double)(*this) != (double)inRHS); }
bool operator != (unsigned char inRHS) const { return !IsNumeric() || ((double)(*this) != (double)inRHS); }
bool operator != (bool inRHS) const { return !IsBool() || ((double)(*this) != (double)inRHS); }
#define DYNAMIC_COMPARE_OP_ALL( op ) \
bool operator op (const Dynamic &inRHS) const { return mPtr && (Compare(inRHS) op 0); } \
bool operator op (const cpp::Variant &inRHS) const { return *this op Dynamic(inRHS); } \
DYNAMIC_COMPARE_OP(op)
DYNAMIC_COMPARE_OP( == )
DYNAMIC_COMPARE_OP_ALL( < )
DYNAMIC_COMPARE_OP_ALL( <= )
DYNAMIC_COMPARE_OP_ALL( >= )
DYNAMIC_COMPARE_OP_ALL( > )
template<typename T_>
bool operator==(const hx::ObjectPtr<T_> &inRHS) const
{
if (mPtr==inRHS.mPtr) return true;
if (!mPtr || !inRHS.mPtr) return false;
#if (HXCPP_API_LEVEL>=331)
return mPtr == inRHS.mPtr;
#else
return mPtr->__GetRealObject() == inRHS.mPtr->__GetRealObject();
#endif
}
template<typename T_>
bool operator!=(const hx::ObjectPtr<T_> &inRHS) const
{
if (mPtr==inRHS.mPtr) return false;
if (!mPtr || !inRHS.mPtr) return true;
#if (HXCPP_API_LEVEL>=331)
return mPtr != inRHS.mPtr;
#else
return mPtr->__GetRealObject() != inRHS.mPtr->__GetRealObject();
#endif
}
// Operator + is different, since it must consider strings too...
Dynamic operator+(const Dynamic &inRHS) const;
inline String operator+(const String &s) const;
Dynamic operator+(const cpp::UInt64 &i) const;
Dynamic operator+(const cpp::Int64 &i) const;
Dynamic operator+(const int &i) const;
Dynamic operator+(const unsigned int &i) const;
Dynamic operator+(const short &i) const;
Dynamic operator+(const unsigned short &i) const;
Dynamic operator+(const signed char &i) const;
Dynamic operator+(const unsigned char &i) const;
Dynamic operator+(const double &d) const;
Dynamic operator+(const float &d) const;
Dynamic operator+(const cpp::Variant &d) const;
double operator%(const Dynamic &inRHS) const;
double operator-() const { return mPtr ? - mPtr->__ToDouble() : 0.0; }
double operator++() { double val = mPtr->__ToDouble() + 1; *this = val; return val; }
double operator++(int) {double val = mPtr->__ToDouble(); *this = val+1; return val; }
double operator--() { double val = mPtr->__ToDouble() - 1; *this = val; return val; }
double operator--(int) {double val = mPtr->__ToDouble(); *this = val-1; return val; }
double operator / (const cpp::Variant &inRHS) const { return (double)(*this) / (double)inRHS; } \
double operator / (const Dynamic &inRHS) const { return (double)(*this) / (double)inRHS; } \
double operator / (const double &inRHS) const { return (double)(*this) / (double)inRHS; } \
double operator / (const float &inRHS) const { return (double)(*this) / (double)inRHS; } \
double operator / (const int &inRHS) const { return (double)(*this) / (double)inRHS; }
#define DYNAMIC_ARITH( op ) \
Dynamic operator op (const cpp::Variant &inRHS) const \
{ return mPtr->__GetType()==vtInt && inRHS.isInt() ? \
Dynamic((int)(*this) op (int)inRHS) : \
Dynamic( (double)(*this) op (double)inRHS); } \
Dynamic operator op (const Dynamic &inRHS) const \
{ return mPtr->__GetType()==vtInt && inRHS.mPtr->__GetType()==vtInt ? \
Dynamic((int)(*this) op (int)inRHS) : \
Dynamic( (double)(*this) op (double)inRHS); } \
double operator op (const double &inRHS) const { return (double)(*this) op (double)inRHS; } \
double operator op (const float &inRHS) const { return (double)(*this) op (double)inRHS; } \
Dynamic operator op (const int &inRHS) const \
{ return mPtr->__GetType()==vtInt ? Dynamic((int)(*this) op inRHS) : Dynamic((double)(*this) op inRHS); } \
Dynamic operator op (const unsigned int &inRHS) const \
{ return mPtr->__GetType()==vtInt ? Dynamic((int)(*this) op inRHS) : Dynamic((double)(*this) op inRHS); } \
Dynamic operator op (const short &inRHS) const \
{ return mPtr->__GetType()==vtInt ? Dynamic((int)(*this) op inRHS) : Dynamic((double)(*this) op inRHS); } \
Dynamic operator op (const unsigned short &inRHS) const \
{ return mPtr->__GetType()==vtInt ? Dynamic((int)(*this) op inRHS) : Dynamic((double)(*this) op inRHS); } \
Dynamic operator op (const signed char &inRHS) const \
{ return mPtr->__GetType()==vtInt ? Dynamic((int)(*this) op inRHS) : Dynamic((double)(*this) op inRHS); } \
Dynamic operator op (const unsigned char &inRHS) const \
{ return mPtr->__GetType()==vtInt ? Dynamic((int)(*this) op inRHS) : Dynamic((double)(*this) op inRHS); } \
Dynamic operator op (const cpp::Int64 &inRHS) const \
{ return Dynamic((double)(*this) op inRHS); } \
Dynamic operator op (const cpp::UInt64 &inRHS) const \
{ return Dynamic((double)(*this) op inRHS); } \
DYNAMIC_ARITH( - )
DYNAMIC_ARITH( * )
static void ThrowBadFunctionError();
inline void CheckFPtr() { if (!mPtr) ThrowBadFunctionError(); }
inline ::Dynamic operator()() { CheckFPtr(); return mPtr->__run(); }
inline ::Dynamic operator()(const Dynamic &inArg0) { CheckFPtr(); return mPtr->__run(inArg0); }
inline ::Dynamic operator()(const Dynamic &inArg0,const Dynamic &inArg1) { CheckFPtr(); return mPtr->__run(inArg0,inArg1); }
inline ::Dynamic operator()(const Dynamic &inArg0,const Dynamic &inArg1,const Dynamic &inArg2) { CheckFPtr(); return mPtr->__run(inArg0,inArg1,inArg2); }
inline ::Dynamic operator()(const Dynamic &inArg0,const Dynamic &inArg1,const Dynamic &inArg2,const Dynamic &inArg3) { CheckFPtr(); return mPtr->__run(inArg0,inArg1,inArg2,inArg3); }
inline ::Dynamic operator()(const Dynamic &inArg0,const Dynamic &inArg1,const Dynamic &inArg2,const Dynamic &inArg3,const Dynamic &inArg4) { CheckFPtr(); return mPtr->__run(inArg0,inArg1,inArg2,inArg3,inArg4); }
HX_DECLARE_DYNAMIC_FUNCTIONS;
typedef const Dynamic &D;
};
namespace hx
{
inline hx::Object *DynamicPtr(Dynamic inVal) { return inVal.mPtr; }
typedef Dynamic (*MemberFunction0)(hx::Object *inObj);
typedef Dynamic (*MemberFunction1)(hx::Object *inObj,const Dynamic &inArg0);
typedef Dynamic (*MemberFunction2)(hx::Object *inObj,const Dynamic &inArg0,const Dynamic &inArg1);
typedef Dynamic (*MemberFunction3)(hx::Object *inObj,const Dynamic &inArg0,const Dynamic &inArg1,const Dynamic &inArg2);
typedef Dynamic (*MemberFunction4)(hx::Object *inObj,const Dynamic &inArg0,const Dynamic &inArg1,const Dynamic &inArg2,const Dynamic &inArg3);
typedef Dynamic (*MemberFunction5)(hx::Object *inObj,const Dynamic &inArg0,const Dynamic &inArg1,const Dynamic &inArg2,const Dynamic &inArg3,const Dynamic &inArg4);
typedef Dynamic (*MemberFunctionVar)(hx::Object *inObj,const Array<Dynamic> &inArgs);
typedef Dynamic (*StaticFunction0)();
typedef Dynamic (*StaticFunction1)(const Dynamic &inArg0);
typedef Dynamic (*StaticFunction2)(const Dynamic &inArg0,const Dynamic &inArg1);
typedef Dynamic (*StaticFunction3)(const Dynamic &inArg0,const Dynamic &inArg1,const Dynamic &inArg2);
typedef Dynamic (*StaticFunction4)(const Dynamic &inArg0,const Dynamic &inArg1,const Dynamic &inArg2,const Dynamic &inArg3);
typedef Dynamic (*StaticFunction5)(const Dynamic &inArg0,const Dynamic &inArg1,const Dynamic &inArg2,const Dynamic &inArg3,const Dynamic &inArg4);
typedef Dynamic (*StaticFunction6)(const Dynamic &inArg0,const Dynamic &inArg1,const Dynamic &inArg2,const Dynamic &inArg3,const Dynamic &inArg4,const Dynamic &inArg5);
typedef Dynamic (*StaticFunctionVar)(const Array<Dynamic> &inArgs);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateMemberFunction0(const char *,hx::Object *, MemberFunction0);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateMemberFunction1(const char *,hx::Object *, MemberFunction1);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateMemberFunction2(const char *,hx::Object *, MemberFunction2);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateMemberFunction3(const char *,hx::Object *, MemberFunction3);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateMemberFunction4(const char *,hx::Object *, MemberFunction4);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateMemberFunction5(const char *,hx::Object *, MemberFunction5);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateMemberFunctionVar(const char *,hx::Object *, MemberFunctionVar,int inN);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateStaticFunction0(const char *,StaticFunction0);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateStaticFunction1(const char *,StaticFunction1);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateStaticFunction2(const char *,StaticFunction2);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateStaticFunction3(const char *,StaticFunction3);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateStaticFunction4(const char *,StaticFunction4);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateStaticFunction5(const char *,StaticFunction5);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateStaticFunction6(const char *,StaticFunction6);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic CreateStaticFunctionVar(const char *,StaticFunctionVar,int inN);
}
template<>
inline int Dynamic::Cast<int>() const { return mPtr ? mPtr->__ToInt() : 0; }
template<>
inline bool Dynamic::Cast<bool>() const { return mPtr ? mPtr->__ToInt() : 0; }
template<>
inline double Dynamic::Cast<double>() const { return mPtr ? mPtr->__ToDouble() : 0; }
template<>
inline float Dynamic::Cast<float>() const { return mPtr ? mPtr->__ToDouble() : 0; }
template<>
inline String Dynamic::Cast<String>() const { return mPtr ? mPtr->toString() : String(null()); }
//
// Gets the class definition that relates to a specific type.
// Most classes have their own class data, by the standard types (non-classes)
// use the template traits to get the class
namespace hx
{
HXCPP_EXTERN_CLASS_ATTRIBUTES hx::Class &GetIntClass();
HXCPP_EXTERN_CLASS_ATTRIBUTES hx::Class &GetFloatClass();
HXCPP_EXTERN_CLASS_ATTRIBUTES hx::Class &GetBoolClass();
HXCPP_EXTERN_CLASS_ATTRIBUTES hx::Class &GetVoidClass();
HXCPP_EXTERN_CLASS_ATTRIBUTES hx::Class &GetStringClass();
HXCPP_EXTERN_CLASS_ATTRIBUTES hx::Class &GetInt64Class();
}
template<>
inline bool Dynamic::IsClass<int>() { return mPtr && mPtr->__GetClass()==hx::GetIntClass(); }
template<>
inline bool Dynamic::IsClass<double>() { return mPtr &&
( mPtr->__GetClass()==hx::GetIntClass() || mPtr->__GetClass()==hx::GetFloatClass()) ; }
template<>
inline bool Dynamic::IsClass<float>() { return mPtr && mPtr->__GetClass()==hx::GetFloatClass(); }
template<>
inline bool Dynamic::IsClass<bool>() { return mPtr && mPtr->__GetClass()==hx::GetBoolClass(); }
template<>
inline bool Dynamic::IsClass<null>() { return !mPtr; }
template<>
inline bool Dynamic::IsClass<String>() { return mPtr && mPtr->__GetClass()==hx::GetStringClass(); }
template<>
inline bool Dynamic::IsClass<Dynamic>() { return true; }
template<>
inline bool Dynamic::IsClass< ::cpp::Int64>() { return mPtr && mPtr->__GetClass()==hx::GetInt64Class(); }
inline String Dynamic::operator+(const String &s) const { return Cast<String>() + s; }
#define HX_DYNAMIC_OP_ISEQ(T) \
inline bool operator == (const T &inLHS,const Dynamic &inRHS) { return inRHS==inLHS; } \
inline bool operator != (const T &inLHS,const Dynamic &inRHS) { return inRHS!=inLHS; }
HX_DYNAMIC_OP_ISEQ(String)
HX_DYNAMIC_OP_ISEQ(double)
HX_DYNAMIC_OP_ISEQ(float)
HX_DYNAMIC_OP_ISEQ(int)
HX_DYNAMIC_OP_ISEQ(bool)
inline bool operator < (bool inLHS,const Dynamic &inRHS) { return false; }
inline bool operator <= (bool inLHS,const Dynamic &inRHS) { return false; }
inline bool operator >= (bool inLHS,const Dynamic &inRHS) { return false; }
inline bool operator > (bool inLHS,const Dynamic &inRHS) { return false; }
#if defined(HX_WINRT) && defined(__cplusplus_winrt)
// Try to avoid the compiler using injected Box::operator int and Dynamic(null) when doing ==
template<typename T>
bool operator==(Platform::Box<T> ^inPtr, nullptr_t)
{
void* ptr = (void*) reinterpret_cast<void*>(inPtr);
return ptr==nullptr;
}
#endif
#define COMPARE_DYNAMIC_OP( op ) \
inline bool operator op (double inLHS,const ::Dynamic &inRHS) \
{ return inRHS.IsNumeric() && (inLHS op (double)inRHS); } \
inline bool operator op (float inLHS,const ::Dynamic &inRHS) \
{ return inRHS.IsNumeric() && ((double)inLHS op (double)inRHS); } \
inline bool operator op (int inLHS,const ::Dynamic &inRHS) \
{ return inRHS.IsNumeric() && (inLHS op (double)inRHS); }
COMPARE_DYNAMIC_OP( < )
COMPARE_DYNAMIC_OP( <= )
COMPARE_DYNAMIC_OP( >= )
COMPARE_DYNAMIC_OP( > )
#define ARITH_DYNAMIC( op ) \
inline double operator op (const cpp::Int64 &inLHS,const Dynamic &inRHS) { return inLHS op (cpp::Int64)inRHS;} \
inline double operator op (const cpp::UInt64 &inLHS,const Dynamic &inRHS) { return inLHS op (cpp::UInt64)inRHS;} \
inline double operator op (const double &inLHS,const Dynamic &inRHS) { return inLHS op (double)inRHS;} \
inline double operator op (const float &inLHS,const Dynamic &inRHS) { return inLHS op (double)inRHS;} \
inline double operator op (const int &inLHS,const Dynamic &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const unsigned int &inLHS,const Dynamic &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const short &inLHS,const Dynamic &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const unsigned short &inLHS,const Dynamic &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const signed char &inLHS,const Dynamic &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const unsigned char &inLHS,const Dynamic &inRHS) { return inLHS op (double)inRHS; } \
ARITH_DYNAMIC( - )
ARITH_DYNAMIC( + )
ARITH_DYNAMIC( / )
ARITH_DYNAMIC( * )
double operator%(const int &inLHS,const Dynamic &inRHS);
double operator%(const double &inLHS,const Dynamic &inRHS);
double operator%(const float &inLHS,const Dynamic &inRHS);
template<typename T,typename H> String::String(const cpp::Struct<T,H> &inRHS) { *this = (String)inRHS; }
template<typename OBJ> String::String(const hx::ObjectPtr<OBJ> &inRHS) { *this = Dynamic(inRHS); }
#endif

View File

@ -0,0 +1,196 @@
#ifndef HX_ENUM_H
#define HX_ENUM_H
// Enum (ie enum object class def) is the same as Class.
typedef hx::Class Enum;
namespace hx
{
// --- hx::EnumBase_obj ----------------------------------------------------------
//
// Base class for Enums.
// Specializations of this class don't actually add more data, just extra constructors
// and type information.
class HXCPP_EXTERN_CLASS_ATTRIBUTES EnumBase_obj : public hx::Object
{
typedef hx::Object super;
typedef EnumBase_obj OBJ_;
protected:
#if (HXCPP_API_LEVEL >= 330)
String _hx_tag;
int mFixedFields;
#ifdef HXCPP_SCRIPTABLE
struct CppiaClassInfo *classInfo;
#endif
#else
String tag;
DynamicArray mArgs;
#endif
public:
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdEnum };
int index;
public:
inline void *operator new( size_t inSize, int inExtra=0)
{
return hx::Object::operator new(inSize+inExtra, true, 0);
}
inline void operator delete(void *, int inExtra ) { }
inline void operator delete(void *, size_t inSize ) { }
inline void operator delete(void *, size_t inSize, int inExtra ) { }
HX_DO_ENUM_RTTI_INTERNAL;
static hx::ObjectPtr<hx::Class_obj> &__SGetClass();
String toString();
EnumBase_obj() : index(-1) { }
EnumBase_obj(const null &inNull) : index(-1) { }
int __GetType() const { return vtEnum; }
static Dynamic __CreateEmpty();
static Dynamic __Create(DynamicArray inArgs);
static void __boot();
void __Mark(hx::MarkContext *__inCtx);
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *__inCtx);
#endif
static hx::ObjectPtr<EnumBase_obj> Resolve(String inName);
inline static bool __GetStatic(const ::String &inName, Dynamic &outValue, hx::PropertyAccess inCallProp) { return false; }
#if (HXCPP_API_LEVEL >= 330)
inline cpp::Variant *_hx_getFixed() { return (cpp::Variant *)(this + 1); }
inline const cpp::Variant *_hx_getFixed() const { return (cpp::Variant *)(this + 1); }
inline ::Dynamic __Param(int inID) { return _hx_getFixed()[inID]; }
template<typename T>
inline EnumBase_obj *_hx_init(int inIndex,const T &inValue)
{
#ifdef HXCPP_GC_GENERATIONAL
cpp::Variant &v = _hx_getFixed()[inIndex];
v = inValue;
if (v.type<=cpp::Variant::typeString)
HX_OBJ_WB_GET(this, v.valObject);
#else
_hx_getFixed()[inIndex] = inValue;
#endif
return this;
}
inline void _hx_setIdentity(const String &inTag, int inIndex,int inFixedFields)
{
_hx_tag = inTag;
HX_OBJ_WB_GET(this, _hx_tag.__s);
index = inIndex;
mFixedFields = inFixedFields;
}
DynamicArray _hx_getParameters();
inline ::Dynamic _hx_getObject(int inId) { return _hx_getFixed()[inId].asDynamic(); }
inline int _hx_getInt(int inId) { return _hx_getFixed()[inId]; }
inline ::cpp::Int64 _hx_getInt64(int inId) { return _hx_getFixed()[inId].asInt64(); }
inline Float _hx_getFloat(int inId) { return _hx_getFixed()[inId]; }
inline bool _hx_getBool(int inId) { return _hx_getFixed()[inId]; }
inline ::String _hx_getString(int inId) { return _hx_getFixed()[inId].asString(); }
inline ::Dynamic _hx_getParamI(int inId) { return _hx_getFixed()[inId]; }
inline int _hx_getParamCount() { return mFixedFields; }
// Alias for _hx_getParamI
Dynamic __GetItem(int inIndex) const;
// For legacy
inline String __Tag() const { return _hx_tag; }
String _hx_getTag() const { return _hx_tag; }
int _hx_getIndex() const { return index; }
#else
Dynamic __Param(int inID) { return mArgs[inID]; }
DynamicArray __EnumParams() { return mArgs; }
String __Tag() const { return tag; }
int __Index() const { return index; }
void __Set( const String &inName,int inIndex,DynamicArray inArgs)
{
tag = inName;
index = inIndex;
mArgs = inArgs;
}
#endif
int __Compare(const hx::Object *inRHS) const;
virtual String GetEnumName( ) const { return HX_CSTRING("Enum"); }
};
typedef hx::ObjectPtr<EnumBase_obj> EnumBase;
HXCPP_EXTERN_CLASS_ATTRIBUTES bool __hxcpp_enum_eq( ::hx::EnumBase a, ::hx::EnumBase b);
// --- CreateEnum -------------------------------------------------------------
//
// Template function to return a strongly-typed version fo the Enum.
// Most of the common stuff is in "Set".
#if (HXCPP_API_LEVEL >= 330)
template<typename ENUM>
ENUM *CreateEnum(const String &inName,int inIndex, int inFields)
{
ENUM *result = new (inFields*sizeof(cpp::Variant)) ENUM;
result->_hx_setIdentity(inName,inIndex,inFields);
return result;
}
template<typename ENUM>
ENUM *CreateConstEnum(const String &inName,int inIndex)
{
ENUM vtable;
ENUM *result = (ENUM *)hx::InternalCreateConstBuffer(&vtable,sizeof(ENUM));
result->_hx_setIdentity(inName,inIndex,0);
return result;
}
#else
template<typename ENUM>
hx::ObjectPtr<ENUM> CreateEnum(const String &inName,int inIndex, DynamicArray inArgs=DynamicArray())
{
ENUM *result = new ENUM;
result->__Set(inName,inIndex,inArgs);
return result;
}
#endif
} // end namespace hx
#if (HXCPP_API_LEVEL >= 330)
inline int _hx_getEnumValueIndex(hx::EnumBase inEnum)
{
return inEnum->_hx_getIndex();
}
#endif
inline void __hxcpp_enum_force(hx::EnumBase inEnum,String inForceName, int inIndex)
{
#if (HXCPP_API_LEVEL >= 330)
inEnum->_hx_setIdentity(inForceName, inIndex,0);
#else
hx::DynamicArray empty;
inEnum->__Set(inForceName, inIndex, empty);
#endif
}
#endif

View File

@ -0,0 +1,92 @@
#ifndef INCLUDED_haxe_CppInt32__
#define INCLUDED_haxe_CppInt32__
#include <hxcpp.h>
namespace cpp
{
#define HX_I32_DEF_FUNC1(Name) \
static inline Dynamic __##Name(const Dynamic &a) { return Name(a); } \
static inline Dynamic Name##_dyn() { return hx::CreateStaticFunction1(#Name,&CppInt32__::__##Name); }
#define HX_I32_DEF_FUNC2(Name) \
static inline Dynamic __##Name(const Dynamic &a, const Dynamic &b) { return Name(a,b); } \
static inline Dynamic Name##_dyn() { return hx::CreateStaticFunction2(#Name,&CppInt32__::__##Name); }
class CppInt32__
{
public:
CppInt32__(int inX=0) : mValue(inX) { }
CppInt32__(const null &inNull) : mValue(0) { }
CppInt32__(const Dynamic &inD);
operator int() const { return mValue; }
template<typename T>
inline CppInt32__ &operator=(T inValue) { mValue = inValue; return *this; }
static inline CppInt32__ make(int a,int b) { return CppInt32__( (a<<16) | b ); }
static inline CppInt32__ ofInt(int a) { return CppInt32__( a ); }
static inline int toInt(CppInt32__ a) { __hxcpp_check_overflow(a); return a.mValue; }
static inline int toNativeInt(CppInt32__ a) { return a.mValue; }
static inline CppInt32__ add(CppInt32__ a,CppInt32__ b) { return CppInt32__( a.mValue + b.mValue ); }
static inline CppInt32__ sub(CppInt32__ a,CppInt32__ b) { return CppInt32__( a.mValue - b.mValue ); }
static inline CppInt32__ mul(CppInt32__ a,CppInt32__ b) { return CppInt32__( a.mValue * b.mValue ); }
static inline CppInt32__ div(CppInt32__ a,CppInt32__ b) { return CppInt32__( a.mValue / b.mValue ); }
static inline CppInt32__ mod(CppInt32__ a,CppInt32__ b) { return CppInt32__( a.mValue % b.mValue ); }
static inline CppInt32__ shl(CppInt32__ a,int b) { return CppInt32__( a.mValue << (b&31) ); }
static inline CppInt32__ shr(CppInt32__ a,int b) { return CppInt32__( a.mValue >> (b&31) ); }
static inline CppInt32__ ushr(CppInt32__ a,int b) { return CppInt32__( ((unsigned int)a.mValue) >> (b&31) ); }
static inline CppInt32__ _and(CppInt32__ a,CppInt32__ b) { return CppInt32__( a.mValue & b.mValue ); }
static inline CppInt32__ _or(CppInt32__ a,CppInt32__ b) { return CppInt32__( a.mValue | b.mValue ); }
static inline CppInt32__ _xor(CppInt32__ a,CppInt32__ b) { return CppInt32__( a.mValue ^ b.mValue ); }
static inline CppInt32__ neg(CppInt32__ a) { return CppInt32__( -a.mValue ); }
static inline CppInt32__ complement(CppInt32__ a) { return CppInt32__( ~a.mValue ); }
static inline int compare(CppInt32__ a,CppInt32__ b) { return ( a.mValue - b.mValue ); }
static inline bool isNeg(CppInt32__ a) { return a.mValue < 0; }
static inline bool isZero(CppInt32__ a) { return a.mValue == 0; }
static inline int ucompare(CppInt32__ a,CppInt32__ b) { unsigned int am = a.mValue, bm = b.mValue; return (am == bm) ? 0 : ((am > bm) ? 1 : -1); }
inline bool operator==(const CppInt32__ &inRHS) const { return mValue == inRHS.mValue; }
inline int operator-(CppInt32__ b) { return mValue - b.mValue; }
inline int operator+(CppInt32__ b) { return mValue + b.mValue; }
inline int operator*(CppInt32__ b) { return mValue * b.mValue; }
inline int operator/(CppInt32__ b) { return mValue / b.mValue; }
inline int operator%(CppInt32__ b) { return mValue % b.mValue; }
HX_I32_DEF_FUNC2(make)
HX_I32_DEF_FUNC1(ofInt)
HX_I32_DEF_FUNC1(toInt)
HX_I32_DEF_FUNC1(toNativeInt)
HX_I32_DEF_FUNC2(add)
HX_I32_DEF_FUNC2(sub)
HX_I32_DEF_FUNC2(mul)
HX_I32_DEF_FUNC2(div)
HX_I32_DEF_FUNC2(mod)
HX_I32_DEF_FUNC2(shl)
HX_I32_DEF_FUNC2(shr)
HX_I32_DEF_FUNC2(ushr)
HX_I32_DEF_FUNC2(_and)
HX_I32_DEF_FUNC2(_or)
HX_I32_DEF_FUNC2(_xor)
HX_I32_DEF_FUNC1(neg)
HX_I32_DEF_FUNC1(complement)
HX_I32_DEF_FUNC2(compare)
HX_I32_DEF_FUNC2(ucompare)
HX_I32_DEF_FUNC1(isNeg)
HX_I32_DEF_FUNC1(isZero)
int mValue;
};
typedef CppInt32__ CppInt32___obj;
}
#endif

View File

@ -0,0 +1,108 @@
#ifndef INCLUDED_cpp_FastIterator
#define INCLUDED_cpp_FastIterator
namespace cpp
{
class HXCPP_EXTERN_CLASS_ATTRIBUTES IteratorBase : public hx::Object
{
public:
hx::Val __Field(const String &inString ,hx::PropertyAccess inCallProp);
virtual bool hasNext() = 0;
virtual Dynamic _dynamicNext() = 0;
Dynamic hasNext_dyn( );
Dynamic next_dyn( );
Dynamic _dynamicNext_dyn( );
};
template<typename T>
class HXCPP_EXTERN_CLASS_ATTRIBUTES FastIterator_obj : public IteratorBase
{
public:
virtual bool hasNext() = 0;
virtual T next() = 0;
virtual Dynamic _dynamicNext() { return next(); }
};
template<typename T>
class HXCPP_EXTERN_CLASS_ATTRIBUTES DynamicIterator : public FastIterator_obj<T>
{
public:
Dynamic mNext;
Dynamic mHasNext;
DynamicIterator(Dynamic inValue)
{
mNext = inValue->__Field(HX_CSTRING("next"), HX_PROP_ALWAYS);
mHasNext = inValue->__Field(HX_CSTRING("hasNext"), HX_PROP_ALWAYS);
}
bool hasNext() { return mHasNext(); }
T next() { return mNext(); }
void __Mark(hx::MarkContext *__inCtx)
{
HX_MARK_MEMBER_NAME(mNext,"mNext");
HX_MARK_MEMBER_NAME(mHasNext,"mHasNext");
}
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *__inCtx)
{
HX_VISIT_MEMBER_NAME(mNext,"mNext");
HX_VISIT_MEMBER_NAME(mHasNext,"mHasNext");
}
#endif
};
template<typename T>
FastIterator_obj<T> *CreateFastIterator(Dynamic inValue)
{
FastIterator_obj<T> *result = dynamic_cast< FastIterator_obj<T> *>(inValue.GetPtr());
if (result) return result;
return new DynamicIterator<T>(inValue);
}
template<typename T>
class HXCPP_EXTERN_CLASS_ATTRIBUTES StringIterator : public cpp::FastIterator_obj<T>
{
public:
String value;
int pos;
StringIterator(const String &inValue) : value(inValue), pos(0) { }
bool hasNext() { return pos<value.length; }
void __Mark(hx::MarkContext *__inCtx)
{
cpp::FastIterator_obj<T>::__Mark(__inCtx);
HX_MARK_MEMBER_NAME(value,"value");
}
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *__inCtx)
{
cpp::FastIterator_obj<T>::__Visit(__inCtx);
HX_VISIT_MEMBER_NAME(value,"value");
}
#endif
};
}
#endif

View File

@ -0,0 +1,148 @@
#ifndef CPP_INT64_INCLUDED
#define CPP_INT64_INCLUDED
namespace cpp
{
class Int64Handler
{
public:
static inline const char *getName() { return "cpp.Int64"; }
static inline String toString( const void *inValue ) { return String( *(Int64 *)inValue ); }
static inline void handler(DynamicHandlerOp op, void *ioValue,int inSize, void *outResult)
{
if (op==dhoToString)
*(String *)outResult = toString(ioValue);
else if (op==dhoGetClassName)
*(const char **)outResult = getName();
else if (op==dhoFromDynamic)
{
StructHandlerDynamicParams *params = (StructHandlerDynamicParams *)outResult;
cpp::Int64 &value = *(cpp::Int64 *)ioValue;
params->outProcessed = true;
if (!params->inData)
value = 0;
else
value = params->inData->__ToInt64();
}
else if (op==dhoToDynamic)
{
Dynamic value = *(cpp::Int64 *)ioValue;
*(hx::Object **)outResult = value.mPtr;
}
else if (op==dhoIs)
{
StructHandlerDynamicParams *params = (StructHandlerDynamicParams *)outResult;
hx::Object *obj = params->inData;
int type = obj->__GetType();
params->outProcessed = type==vtInt || type==vtInt64;
}
else
return DefaultStructHandler::handler(op,ioValue,inSize, outResult);
}
};
typedef Struct<Int64,Int64Handler> Int64Struct;
}
#if (HXCPP_API_LEVEL >= 420)
inline cpp::Int64 _hx_int64_make(int a, int b) { return (((cpp::Int64)(unsigned int)a)<<32) | (unsigned int)b; }
inline bool _hx_int64_is_neg(cpp::Int64 a) { return a<0; }
inline bool _hx_int64_is_zero(cpp::Int64 a) { return a==0; }
inline bool _hx_int64_eq(cpp::Int64 a, cpp::Int64 b) { return a==b; }
inline bool _hx_int64_neq(cpp::Int64 a, cpp::Int64 b) { return a!=b; }
inline int _hx_int64_compare(cpp::Int64 a, cpp::Int64 b)
{
return a==b ? 0 : a<b ? -1 : 1;
}
inline int _hx_int64_ucompare(cpp::Int64 a, cpp::Int64 b)
{
return a==b ? 0 : ( ::cpp::UInt64)a<( ::cpp::UInt64)b ? -1 : 1;
}
inline String _hx_int64_to_string(cpp::Int64 a) { return a; }
inline cpp::Int64 _hx_int64_neg(cpp::Int64 a) { return -a; }
inline cpp::Int64 _hx_int64_complement(cpp::Int64 a) { return ~a; }
inline cpp::Int64 _hx_int64_pre_increment(cpp::Int64 &ioVal) {
return ++ioVal;
}
inline cpp::Int64 _hx_int64_post_increment(cpp::Int64 &ioVal) {
return ioVal++;
}
inline cpp::Int64 _hx_int64_pre_decrement(cpp::Int64 &ioVal) {
return --ioVal;
}
inline cpp::Int64 _hx_int64_post_decrement(cpp::Int64 &ioVal) {
return ioVal--;
}
inline cpp::Int64 _hx_int64_sub(cpp::Int64 a, cpp::Int64 b) { return a-b; }
inline cpp::Int64 _hx_int64_add(cpp::Int64 a, cpp::Int64 b) { return a+b; }
inline cpp::Int64 _hx_int64_mul(cpp::Int64 a, cpp::Int64 b) { return a*b; }
inline cpp::Int64 _hx_int64_div(cpp::Int64 a, cpp::Int64 b) { return a/b; }
inline cpp::Int64 _hx_int64_mod(cpp::Int64 a, cpp::Int64 b) { return a%b; }
inline cpp::Int64 _hx_int64_and(cpp::Int64 a, cpp::Int64 b) { return a&b; }
inline cpp::Int64 _hx_int64_or(cpp::Int64 a, cpp::Int64 b) { return a|b; }
inline cpp::Int64 _hx_int64_xor(cpp::Int64 a, cpp::Int64 b) { return a^b; }
inline cpp::Int64 _hx_int64_shl(cpp::Int64 a, int b) { return a<<(b&63); }
inline cpp::Int64 _hx_int64_shr(cpp::Int64 a, int b) { return a>>(b&63); }
inline cpp::Int64 _hx_int64_ushr(cpp::Int64 a, int b) { return ((cpp::UInt64)a)>>(b&63); }
inline int _hx_int64_high(cpp::Int64 a) { return (int)( a >> 32 ); }
inline int _hx_int64_low(cpp::Int64 a) { return (int)( a & 0xffffffff ); }
#else
inline cpp::Int64Struct _hx_int64_make(int a, int b) { return (((cpp::Int64)(unsigned int)a)<<32) | (unsigned int)b; }
inline bool _hx_int64_is_neg(cpp::Int64 a) { return a<0; }
inline bool _hx_int64_is_zero(cpp::Int64 a) { return a==0; }
inline bool _hx_int64_eq(cpp::Int64 a, cpp::Int64 b) { return a==b; }
inline bool _hx_int64_neq(cpp::Int64 a, cpp::Int64 b) { return a!=b; }
inline int _hx_int64_compare(cpp::Int64 a, cpp::Int64 b)
{
return a==b ? 0 : a<b ? -1 : 1;
}
inline int _hx_int64_ucompare(cpp::Int64 a, cpp::Int64 b)
{
return a==b ? 0 : ( ::cpp::UInt64)a<( ::cpp::UInt64)b ? -1 : 1;
}
inline String _hx_int64_to_string(cpp::Int64Struct a) { return a; }
inline cpp::Int64Struct _hx_int64_neg(cpp::Int64 a) { return -a; }
inline cpp::Int64Struct _hx_int64_complement(cpp::Int64 a) { return ~a; }
inline cpp::Int64Struct _hx_int64_pre_increment(cpp::Int64Struct &ioVal) {
return ++ioVal.get();
}
inline cpp::Int64Struct _hx_int64_post_increment(cpp::Int64Struct &ioVal) {
return ioVal.get()++;
}
inline cpp::Int64Struct _hx_int64_pre_decrement(cpp::Int64Struct &ioVal) {
return --ioVal.get();
}
inline cpp::Int64Struct _hx_int64_post_decrement(cpp::Int64Struct &ioVal) {
return ioVal.get()--;
}
inline cpp::Int64Struct _hx_int64_sub(cpp::Int64 a, cpp::Int64 b) { return a-b; }
inline cpp::Int64Struct _hx_int64_add(cpp::Int64 a, cpp::Int64 b) { return a+b; }
inline cpp::Int64Struct _hx_int64_mul(cpp::Int64 a, cpp::Int64 b) { return a*b; }
inline cpp::Int64Struct _hx_int64_div(cpp::Int64 a, cpp::Int64 b) { return a/b; }
inline cpp::Int64Struct _hx_int64_mod(cpp::Int64 a, cpp::Int64 b) { return a%b; }
inline cpp::Int64Struct _hx_int64_and(cpp::Int64 a, cpp::Int64 b) { return a&b; }
inline cpp::Int64Struct _hx_int64_or(cpp::Int64 a, cpp::Int64 b) { return a|b; }
inline cpp::Int64Struct _hx_int64_xor(cpp::Int64 a, cpp::Int64 b) { return a^b; }
inline cpp::Int64Struct _hx_int64_shl(cpp::Int64 a, int b) { return a<<(b&63); }
inline cpp::Int64Struct _hx_int64_shr(cpp::Int64 a, int b) { return a>>(b&63); }
inline cpp::Int64Struct _hx_int64_ushr(cpp::Int64 a, int b) { return ((cpp::UInt64)a)>>(b&63); }
inline int _hx_int64_high(cpp::Int64Struct a) { return (int)( a.get() >>32 ); }
inline int _hx_int64_low(cpp::Int64Struct a) { return (int)( a.get() & 0xffffffff ); }
#endif
#endif

View File

@ -0,0 +1,562 @@
#ifndef CPP_POINTER_H
#define CPP_POINTER_H
namespace cpp
{
struct AutoCast
{
void *value;
explicit inline AutoCast(void *inValue) : value(inValue) { }
};
struct RawAutoCast
{
void *value;
explicit inline RawAutoCast(void *inValue) : value(inValue) { }
template<typename T>
operator T*() const { return (T*)value; }
};
Dynamic CreateDynamicPointer(void *inValue);
enum DynamicHandlerOp
{
dhoGetClassName,
dhoToString,
dhoFromDynamic,
dhoToDynamic,
dhoIs,
};
typedef void (*DynamicHandlerFunc)(DynamicHandlerOp op, void *ioValue, int inSize, void *outResult);
Dynamic CreateDynamicStruct(const void *inValue, int inSize, DynamicHandlerFunc inFunc);
template<typename T> class Reference;
struct StructHandlerDynamicParams
{
StructHandlerDynamicParams(hx::Object *data,const char *inName) :
outProcessed(false), inName(inName), inData(data) { }
bool outProcessed;
hx::Object *inData;
const char *inName;
};
class DefaultStructHandler
{
public:
static inline const char *getName() { return "unknown"; }
static inline String toString( const void *inValue ) { return HX_CSTRING("Struct"); }
static inline void handler(DynamicHandlerOp op, void *ioValue, int inSize, void *outResult)
{
if (op==dhoToString)
*(String *)outResult = toString(ioValue);
else if (op==dhoGetClassName)
*(const char **)outResult = getName();
else if (op==dhoToDynamic)
{
// Handle outsize..
*(hx::Object **)outResult = 0;
}
else if (op==dhoFromDynamic)
{
StructHandlerDynamicParams *params = (StructHandlerDynamicParams *)outResult;
hx::Object *ptr= params->inData;
void *data = (void *)ptr->__GetHandle();
int len = ptr->__length();
if (data && len>=inSize && ptr->__CStr()==params->inName)
{
memcpy(ioValue,data,inSize);
params->outProcessed = true;
}
}
else if (op==dhoIs)
{
StructHandlerDynamicParams *params = (StructHandlerDynamicParams *)outResult;
hx::Object *ptr= params->inData;
void *data = (void *)ptr->__GetHandle();
int len = ptr->__length();
params->outProcessed = data && len>=inSize && ptr->__CStr()==params->inName;
}
}
};
class EnumHandler
{
public:
static inline const char *getName() { return "enum"; }
static inline String toString( const void *inValue ) {
int val = inValue ? *(int *)inValue : 0;
return HX_CSTRING("enum(") + String(val) + HX_CSTRING(")");
}
static inline void handler(DynamicHandlerOp op, void *ioValue, int inSize, void *outResult)
{
if (op==dhoToString)
*(String *)outResult = toString(ioValue);
else if (op==dhoGetClassName)
*(const char **)outResult = getName();
else if (op==dhoFromDynamic)
{
StructHandlerDynamicParams *params = (StructHandlerDynamicParams *)outResult;
if (params->inData->__GetType()==vtInt)
{
*(int *)ioValue = params->inData->__ToInt();
params->outProcessed = true;
}
else
DefaultStructHandler::handler(op,ioValue, inSize, outResult);
}
else
DefaultStructHandler::handler(op,ioValue, inSize, outResult);
}
};
template<typename T, typename HANDLER = DefaultStructHandler >
class Struct
{
public:
T value;
// This allows 'StaticCast' to be used from arrays
typedef Dynamic Ptr;
inline Struct( ) { }
inline Struct( const T &inRHS ) : value(inRHS) { }
inline Struct( const null &) { value = T(); }
inline Struct( const Reference<T> &);
inline Struct( const Dynamic &inRHS) { fromDynamic(inRHS.mPtr); }
inline Struct<T,HANDLER> &operator=( const T &inRHS ) { value = inRHS; return *this; }
inline Struct<T,HANDLER> &operator=( const null & ) { value = T(); return *this; }
inline Struct<T,HANDLER> &operator=( const Dynamic &inRHS ) { return *this = Struct<T,HANDLER>(inRHS); }
operator Dynamic() const
{
hx::Object *result = 0;
HANDLER::handler(dhoToDynamic, (void *)&value, sizeof(T), &result );
if (result)
return result;
return CreateDynamicStruct( &value, sizeof(T), HANDLER::handler);
}
operator String() const { return HANDLER::toString(&value); }
#if (HXCPP_API_LEVEL >= 330)
inline Struct( const hx::Val &inRHS) { fromDynamic(inRHS.asObject()); }
operator hx::Val() const { return operator Dynamic(); }
#endif
bool operator==(const Struct<T,HANDLER> &inRHS) const { return value==inRHS.value; }
bool operator==(const null &inRHS) const { return false; }
bool operator!=(const null &inRHS) const { return true; }
// Haxe uses -> notation
inline T *operator->() { return &value; }
T &get() { return value; }
static inline bool is( const Dynamic &inRHS)
{
hx::Object *ptr = inRHS.mPtr;
if (!ptr)
return false;
StructHandlerDynamicParams convert(ptr, ptr->__CStr());
HANDLER::handler(dhoIs, 0, sizeof(T), &convert );
return convert.outProcessed;
}
inline void fromDynamic( hx::Object *ptr)
{
if (!ptr)
{
value = T();
return;
}
StructHandlerDynamicParams convert(ptr, ptr->__CStr());
HANDLER::handler(dhoFromDynamic, &value, sizeof(T), &convert );
if (!convert.outProcessed)
{
hx::NullReference("DynamicData", true);
return;
}
}
inline operator T& () { return value; }
};
template<typename T>
class Pointer
{
public:
typedef T elementType;
T *ptr;
inline Pointer( ) : ptr(0) { }
inline Pointer( const Pointer &inRHS ) : ptr(inRHS.ptr) { }
inline Pointer( const Dynamic &inRHS) { ptr = inRHS==null()?0: (T*)inRHS->__GetHandle(); }
inline Pointer( const null &inRHS ) : ptr(0) { }
inline Pointer( const cpp::Variant &inVariant ) {
hx::Object *obj = inVariant.asObject();
ptr = obj ? (T*)inVariant.valObject->__GetHandle() : 0;
}
template<typename O>
inline Pointer( const O *inValue ) : ptr( (T*) inValue) { }
//inline Pointer( T *inValue ) : ptr(inValue) { }
inline Pointer( AutoCast inValue ) : ptr( (T*)inValue.value) { }
template<typename H>
inline Pointer( const Struct<T,H> &structVal ) : ptr( &structVal.value ) { }
template<typename O>
inline void setRaw(const O *inValue ) { ptr = (T*) inValue; }
inline Pointer operator=( const Pointer &inRHS ) { return ptr = inRHS.ptr; }
inline Dynamic operator=( Dynamic &inValue )
{
ptr = inValue==null() ? 0 : (T*) inValue->__GetHandle();
return inValue;
}
inline Dynamic operator=( null &inValue ) { ptr=0; return inValue; }
template<typename O>
inline Pointer operator=( const Pointer<O> &inValue ) { ptr = (T*) inValue.ptr; return *this; }
template<typename O>
inline Pointer operator=( const O *inValue ) { ptr = (T*) inValue; return *this; }
template<typename H>
inline Pointer operator=( const Struct<T,H> &structVal ) { ptr = &structVal.value; return *this; }
inline AutoCast reinterpret() { return AutoCast(ptr); }
inline RawAutoCast rawCast() { return RawAutoCast(ptr); }
inline bool operator==( const null &inValue ) const { return ptr==0; }
inline bool operator!=( const null &inValue ) const { return ptr!=0; }
// Allow '->' syntax
inline Pointer *operator->() { return this; }
inline Pointer inc() { return ++ptr; }
inline Pointer dec() { return --ptr; }
inline Pointer add(int inInt) { return ptr+inInt; }
inline Pointer sub(int inInt) { return ptr-inInt; }
inline Pointer incBy(int inDiff) { ptr+=inDiff; return ptr; }
inline Pointer decBy(int inDiff) { ptr-=inDiff; return ptr; }
inline T &postIncRef() { return *ptr++; }
inline T &postIncVal() { return *ptr++; }
inline T &at(int inIndex) { return ptr[inIndex]; }
inline void setAt(int inIndex, const T &test) { ptr[inIndex] = test; }
inline T &__get(int inIndex) { return ptr[inIndex]; }
inline T &__set(int inIndex, const T &inValue) { T *p = ptr+inIndex; *p = inValue; return *p; }
inline T &get_value() { return *ptr; }
inline T &get_ref() { return *ptr; }
inline T &set_ref(const T &inValue) { return *ptr = inValue; }
operator Dynamic () const { return CreateDynamicPointer((void *)ptr); }
#if (HXCPP_API_LEVEL >= 330)
operator cpp::Variant () const { return CreateDynamicPointer((void *)ptr); }
#endif
operator T * () { return ptr; }
T * get_raw() { return ptr; }
const T * get_constRaw() { return ptr; }
inline void destroy() { delete ptr; }
inline void destroyArray() { delete [] ptr; }
inline bool lt(Pointer inOther) { return ptr < inOther.ptr; }
inline bool gt(Pointer inOther) { return ptr > inOther.ptr; }
inline bool leq(Pointer inOther) { return ptr <= inOther.ptr; }
inline bool geq(Pointer inOther) { return ptr >= inOther.ptr; }
};
template<>
class Pointer<void>
{
public:
enum { elementSize = 0 };
void *ptr;
inline Pointer( ) : ptr(0) { }
inline Pointer( const Pointer &inRHS ) : ptr(inRHS.ptr) { }
inline Pointer( const Dynamic &inRHS) { ptr = inRHS==null()?0: (void*)inRHS->__GetHandle(); }
inline Pointer( const null &inRHS ) : ptr(0) { }
template<typename O>
inline Pointer( const O *inValue ) : ptr( (void*) inValue) { }
//inline Pointer( T *inValue ) : ptr(inValue) { }
inline Pointer( AutoCast inValue ) : ptr( (void*)inValue.value) { }
inline Pointer operator=( const Pointer &inRHS ) { return ptr = inRHS.ptr; }
inline Dynamic operator=( Dynamic &inValue )
{
ptr = inValue==null() ? 0 : (void*) inValue->__GetHandle();
return inValue;
}
inline Dynamic operator=( null &inValue ) { ptr=0; return inValue; }
inline AutoCast reinterpret() { return AutoCast(ptr); }
inline RawAutoCast rawCast() { return RawAutoCast(ptr); }
inline bool operator==( const null &inValue ) const { return ptr==0; }
inline bool operator!=( const null &inValue ) const { return ptr!=0; }
// Allow '->' syntax
inline Pointer *operator->() { return this; }
inline Pointer inc() { return ptr; }
inline Pointer dec() { return ptr; }
inline Pointer add(int inInt) { return ptr; }
inline Pointer sub(int inInt) { return ptr; }
inline Pointer incBy(int inDiff) { return ptr; }
inline Pointer decBy(int inDiff) { return ptr; }
inline void postIncRef() { }
inline void postIncVal() { }
inline void at(int inIndex) { }
inline void __get(int inIndex) { }
template<typename O>
inline void __set(int inIndex, O inValue) { }
inline void get_value() { }
inline void get_ref() { }
template<typename O> inline void set_ref(O val) { }
operator Dynamic () const { return CreateDynamicPointer(ptr); }
//operator hx::Val () const { return CreateDynamicPointer((void *)ptr); }
operator void * () { return ptr; }
void * get_raw() { return ptr; }
const void * get_constRaw() { return ptr; }
inline void destroy() { }
inline void destroyArray() { }
inline bool lt(Pointer inOther) { return ptr < inOther.ptr; }
inline bool gt(Pointer inOther) { return ptr > inOther.ptr; }
inline bool leq(Pointer inOther) { return ptr <= inOther.ptr; }
inline bool geq(Pointer inOther) { return ptr >= inOther.ptr; }
};
template<typename T>
inline bool operator == (const null &, Pointer<T> inPtr) { return inPtr.ptr==0; }
template<typename T>
inline bool operator != (const null &, Pointer<T> inPtr) { return inPtr.ptr!=0; }
template<typename T>
class Reference : public Pointer<T>
{
public:
using Pointer<T>::ptr;
inline Reference( const T &inRHS ) : Pointer<T>(&inRHS) { }
inline Reference( T &inRHS ) : Pointer<T>(&inRHS) { }
inline Reference( ) : Pointer<T>((T*)0) { }
inline Reference( const Reference &inRHS ) : Pointer<T>(inRHS.ptr) { }
inline Reference( const Dynamic &inRHS) { ptr = inRHS==null()?0: (T*)inRHS->__GetHandle(); }
inline Reference( const null &inRHS ) : Pointer<T>((T*)0) { }
inline Reference( const T *inValue ) : Pointer<T>( (T*) inValue) { }
//inline Reference( T *inValue ) : Pointer(inValue) { }
inline Reference( AutoCast inValue ) : Pointer<T>( (T*)inValue.value) { }
template<typename OTHER>
inline Reference( const Reference<OTHER> &inOther )
{
// Allow reinterpret or not?
ptr = (T*)inOther.ptr;
}
template<typename H>
inline Reference( const Struct<T,H> &structVal ) : Pointer<T>( &structVal.value ) { }
inline Reference operator=( const Reference &inRHS ) { return ptr = inRHS.ptr; }
inline T *operator->() const { return ptr; }
inline operator T &() { return *ptr; }
};
template<typename T,typename H>
Struct<T,H>::Struct( const Reference<T> &ref ) : value(*ref.ptr) { };
template<typename T>
class Function
{
public:
T *call;
inline Function( ) { }
inline Function( const Function &inRHS ) : call(inRHS.call) { }
inline Function( const Dynamic &inRHS) { call = inRHS==null()?0: (T*)inRHS->__GetHandle(); }
inline Function( const null &inRHS ) { call = 0; }
inline Function( T *inValue ) : call((T*)(inValue)) { }
//inline Function( T *inValue ) : call(inValue) { }
inline Function( AutoCast inValue ) : call( (T*)inValue.value) { }
inline Function( const hx::AnyCast &inValue ) : call( (T*)inValue.mPtr) { }
template<typename FROM>
inline static Function __new(FROM from)
{
return Function(from);
}
inline Function operator=( const Function &inRHS ) { return call = inRHS.call; }
inline Dynamic operator=( Dynamic &inValue )
{
call = inValue==null() ? 0 : (T*) inValue->__GetHandle();
return inValue;
}
inline Dynamic operator=( null &inValue ) { call=0; return inValue; }
inline bool operator==( const null &inValue ) const { return call==0; }
inline bool operator!=( const null &inValue ) const { return call!=0; }
operator Dynamic () const { return CreateDynamicPointer((void *)call); }
//operator hx::Val () const { return CreateDynamicPointer((void *)call); }
operator T * () { return call; }
operator void * () { return (void *)call; }
inline T &get_call() { return *call; }
inline bool lt(Function inOther) { return call < inOther.call; }
inline bool gt(Function inOther) { return call > inOther.call; }
inline bool leq(Function inOther) { return call <= inOther.call; }
inline bool geq(Function inOther) { return call >= inOther.call; }
};
template<typename T>
inline bool operator == (const null &, Function<T> inPtr) { return inPtr.call==0; }
template<typename T>
inline bool operator != (const null &, Function<T> inPtr) { return inPtr.call!=0; }
class Function_obj
{
public:
inline static AutoCast getProcAddress(String inLib, String inPrim)
{
return AutoCast(__hxcpp_get_proc_address(inLib, inPrim,false));
}
template<typename T>
inline static AutoCast fromStaticFunction(T *inFunction)
{
return AutoCast(inFunction);
}
};
class Pointer_obj
{
public:
template<typename T>
inline static AutoCast arrayElem(::Array<T> array, int inIndex) { return AutoCast(&array[inIndex]); }
inline static AutoCast arrayElem(Dynamic inVal, int inIndex)
{
if (inVal==null() || !inVal->__IsArray())
return AutoCast(0);
hx::ArrayBase *base = (hx::ArrayBase *)inVal.GetPtr();
return AutoCast(base->GetBase() + inIndex*base->GetElementSize());
}
template<typename T>
inline static AutoCast ofArray(::Array<T> array) { return AutoCast(&array[0]); }
inline static AutoCast ofArray(Dynamic inVal)
{
if (inVal==null() || !inVal->__IsArray())
return AutoCast(0);
hx::ArrayBase *base = (hx::ArrayBase *)inVal.GetPtr();
return AutoCast(base->GetBase());
}
template<typename T>
inline static Pointer<T> addressOf(T &value) { return Pointer<T>(&value); }
template<typename T>
inline static Pointer<void> endOf(hx::ObjectPtr<T> value) { return (void *)(value.mPtr+1); }
template<typename T>
inline static Pointer<T> fromPointer(T *value) { return Pointer<T>(value); }
template<typename T>
inline static Pointer<T> fromPointer(const T *value) { return Pointer<T>(value); }
template<typename T>
inline static Pointer<T> fromRaw(T *value) { return Pointer<T>(value); }
template<typename T>
inline static Pointer<T> fromRaw(const T *value) { return Pointer<T>(value); }
inline static Pointer<void> fromRaw(const AutoCast &inAutoCast) { return Pointer<void>(inAutoCast.value); }
inline static Pointer<void> fromRaw(const RawAutoCast &inAutoCast) { return Pointer<void>(inAutoCast.value); }
inline static AutoCast fromHandle(Dynamic inValue, String inKind)
{
if (inValue==null() || (inKind!=null() && inKind!=__hxcpp_get_kind(inValue)))
return AutoCast(0);
return AutoCast(inValue->__GetHandle());
}
};
class Reference_obj
{
public:
};
} // end namespace cpp
namespace hx
{
template <typename T>
T *StarOf(T &x) { return &x; }
}
#endif

View File

@ -0,0 +1,676 @@
#ifndef CPP_VARIANT_TWICE_H
namespace cpp
{
#ifndef CPP_VARIANT_ONCE_H
#define CPP_VARIANT_ONCE_H
template<typename T>
inline bool isIntType(const T &inRHS) { return false; }
template<> inline bool isIntType(const int &inRHS) { return true; }
template<> inline bool isIntType(const Dynamic &inRHS);
template<> inline bool isIntType(const cpp::Variant &inRHS);
template<typename T>
inline bool isStringType(const T &inRHS) { return false; }
template<> inline bool isStringType(const String &inRHS) { return true; }
template<> inline bool isStringType(const Dynamic &inRHS);
template<> inline bool isStringType(const cpp::Variant &inRHS);
struct Variant
{
enum Type
{
typeObject = 0,
typeString,
typeDouble,
typeInt,
typeInt64,
typeBool,
};
union
{
// Although this is typed as 'char', it might be char16_t in the case of smart strings
const char *valStringPtr;
hx::Object *valObject;
double valDouble;
cpp::Int64 valInt64;
int valInt;
bool valBool;
};
Type type;
unsigned int valStringLen;
inline bool isNull() const {
return (type==typeObject && !valObject) || (type==typeString && !valStringPtr); }
inline bool isNumeric() const;
inline bool isBool() const;
inline int asInt() const;
inline bool isInt() const;
inline cpp::Int64 asInt64() const;
inline bool isInt64() const;
inline bool isString() const;
inline double asDouble() const;
inline hx::Object *asObject() const { return type==typeObject ? valObject : 0; }
inline hx::Object *asDynamic() const{ return type==typeObject ? valObject : toDynamic(); }
inline hx::Object *toDynamic() const; // later
inline String asString() const;
inline String getString() const;
inline Variant() : valInt64(0), type(typeObject) { }
//inline Variant() { copyBuf.b[0] = copyBuf.b[1] = 0; }
inline Variant(const null &) : type(typeObject), valObject(0) { }
inline Variant(bool inValue) : type(typeBool), valBool(inValue) { }
inline Variant(double inValue) : type(typeDouble), valDouble(inValue) { }
inline Variant(const ::String &inValue); // later
inline Variant(cpp::Int64 inValue) : type(typeInt64), valInt64(inValue) { }
inline Variant(cpp::UInt64 inValue) : type(typeInt64), valInt64(inValue) { }
inline Variant(int inValue) : type(typeInt), valInt(inValue) { }
inline Variant(cpp::UInt32 inValue) : type(typeInt), valInt(inValue) { }
inline Variant(cpp::Int16 inValue) : type(typeInt), valInt(inValue) { }
inline Variant(cpp::UInt16 inValue) : type(typeInt), valInt(inValue) { }
inline Variant(cpp::Int8 inValue) : type(typeInt), valInt(inValue) { }
inline Variant(cpp::UInt8 inValue) : type(typeInt), valInt(inValue) { }
#if defined(__OBJC__) && defined(HXCPP_OBJC)
inline Variant(const id inObjc);
inline operator id() const;
#endif
template<typename SOURCE_>
Variant(const hx::ObjectPtr<SOURCE_> &inObjectPtr);
inline Variant(const Dynamic &inRHS); // later
inline Variant(hx::Object *inValue) : type(typeObject), valObject(inValue) { }
template<typename T,typename H>
explicit inline Variant(const cpp::Struct<T,H> &inVal);
template<typename T>
explicit inline Variant(const cpp::Pointer<T> &inRHS) ;
template<typename T>
explicit inline Variant(const cpp::Function<T> &inRHS) ;
template<typename T>
explicit inline Variant(const hx::Native<T> &inRHS) ;
//inline operator Dynamic() const; // later
//inline operator String() const;
inline operator double() const { return asDouble(); }
inline operator int() const { return asInt(); }
inline operator bool() const { return asInt(); }
inline operator float () const { return asDouble(); }
inline operator unsigned int () const { return asInt(); }
inline operator short () const { return asInt(); }
inline operator unsigned short () const { return asInt(); }
inline operator unsigned char () const { return asInt(); }
inline operator char () const { return asInt(); }
inline operator signed char () const { return asInt(); }
inline operator cpp::Int64 () const { return asInt64(); }
inline operator cpp::UInt64 () const { return asInt64(); }
inline bool operator !() const { return !asInt(); }
inline int Compare(hx::Object *inRHS) const;
inline int Compare(const Dynamic &inRHS) const;
inline int Compare(const cpp::Variant &inRHS) const;
inline double set(const double &inValue) { type=typeDouble; return valDouble=inValue; }
inline double set(const float &inValue) { type=typeDouble; return valDouble=inValue; }
inline void mark(hx::MarkContext *__inCtx); // later
#ifdef HXCPP_VISIT_ALLOCS
inline void visit(hx::VisitContext *__inCtx); // later
#endif
//inline Variant &operator=(const Variant &inRhs) { copyBuf = inRhs.copyBuf; return *this; }
template<typename T>
bool operator==(const T &inRHS) const;
template<typename T>
bool operator==(const hx::ObjectPtr<T> &inRHS) const
{ return Compare(inRHS.mPtr)==0; }
template<typename T>
bool operator!=(const hx::ObjectPtr<T> &inRHS) const
{ return Compare(inRHS.mPtr)!=0; }
inline bool operator==(const null &inRHS) const { return isNull(); }
inline bool operator==(const String &inRHS) const;
inline bool operator!=(const null &inRHS) const { return !isNull(); }
inline bool operator!=(const Variant &inRHS) const { return !operator==(inRHS); }
inline bool operator!=(const String &inRHS) const;
template<typename RETURN_>
RETURN_ Cast() const { return RETURN_(*this); }
void CheckFPtr();
HX_DECLARE_VARIANT_FUNCTIONS
// Operator + is different, since it must consider strings too...
inline String operator+(const String &s) const;
template<typename T>
inline cpp::Variant operator + (const T &inRHS) const;
inline double operator%(const Dynamic &inRHS) const;
inline double operator-() const { return -asDouble(); }
inline double operator++() { return set(asDouble()+1); }
inline double operator++(int) {double val = asDouble(); set(val+1); return val; }
inline double operator--() { return set(asDouble()-1); }
inline double operator--(int) {double val = asDouble(); set(val-1); return val; }
template<typename T>
inline double operator / (const T &inRHS) const { return asDouble() / (double)inRHS; } \
template<typename T>
inline cpp::Variant operator - (const T &inRHS) const
{
if (::cpp::isIntType(inRHS) && isInt() )
return asInt() - (int)inRHS;
return asDouble() - (double)inRHS;
}
template<typename T>
inline cpp::Variant operator * (const T &inRHS) const
{
if (::cpp::isIntType(inRHS) && isInt())
return asInt() * (int)inRHS;
return asDouble() * (double)inRHS;
}
inline bool operator < (const String &inRHS) const;
inline bool operator <= (const String &inRHS) const;
inline bool operator > (const String &inRHS) const;
inline bool operator >= (const String &inRHS) const;
#define HX_VARIANT_COMPARE_OP( op ) \
inline bool operator op (double inRHS) const { return isNumeric() && (asDouble() op inRHS); } \
inline bool operator op (cpp::Int64 inRHS) const { return isNumeric() && (asInt64() op inRHS); } \
inline bool operator op (cpp::UInt64 inRHS) const { return isNumeric() && ((cpp::UInt64)(asInt64()) op inRHS); } \
inline bool operator op (float inRHS) const { return isNumeric() && (asDouble() op inRHS); } \
inline bool operator op (int inRHS) const { return isNumeric() && (asDouble() op (double)inRHS); } \
inline bool operator op (unsigned int inRHS) const { return isNumeric() && (asDouble() op (double)inRHS); } \
inline bool operator op (short inRHS) const { return isNumeric() && (asDouble() op (double)inRHS); } \
inline bool operator op (unsigned short inRHS) const { return isNumeric() && (asDouble() op (double)inRHS); } \
inline bool operator op (signed char inRHS) const { return isNumeric() && (asDouble() op (double)inRHS); } \
inline bool operator op (unsigned char inRHS) const { return isNumeric() && (asDouble() op (double)inRHS); } \
inline bool operator op (bool inRHS) const { return isBool() && (asDouble() op (double)inRHS); } \
inline bool operator op (const Dynamic &inRHS) const { return Compare(inRHS) op 0; } \
#define HX_VARIANT_COMPARE_OP_ALL( op ) \
inline bool operator op (const null &inRHS) const { return false; } \
inline bool operator op (const cpp::Variant &inRHS) const { return Compare(inRHS) op 0; } \
HX_VARIANT_COMPARE_OP(op)
HX_VARIANT_COMPARE_OP( == )
HX_VARIANT_COMPARE_OP( != )
HX_VARIANT_COMPARE_OP_ALL( < )
HX_VARIANT_COMPARE_OP_ALL( <= )
HX_VARIANT_COMPARE_OP_ALL( >= )
HX_VARIANT_COMPARE_OP_ALL( > )
};
#else // Second time ...
#define CPP_VARIANT_TWICE_H
bool Variant::isInt() const
{
return type==typeInt || (type==typeObject && valObject && valObject->__GetType()==vtInt);
}
bool Variant::isInt64() const
{
return type==typeInt64 || (type==typeObject && valObject && valObject->__GetType()==vtInt64);
}
bool Variant::isString() const
{
return type==typeString || (type==typeObject && valObject && valObject->__GetType()==vtString);
}
#if defined(__OBJC__) && defined(HXCPP_OBJC)
// Variant type neither adds nor releases references counts while holding the value as an id on the stack
// The Dynamic created here owns the id, and we refer to the Dynamic and use his reference count to keep the id alive
inline Variant::Variant(const id inObjc) { type=typeObject; valObject = Dynamic(inObjc).mPtr; }
#ifdef OBJC_ARC
inline Variant::operator id () const { return type==typeObject && valObject ? (__bridge id)valObject->__GetHandle() : 0; }
#else
inline Variant::operator id () const { return type==typeObject && valObject ? (id)valObject->__GetHandle() : 0; }
#endif
#endif
template<> inline bool isIntType(const Dynamic &inRHS) { return inRHS->__GetType()==vtInt; }
template<> inline bool isIntType(const cpp::Variant &inRHS) { return inRHS.isInt(); }
template<> inline bool isStringType(const Dynamic &inRHS) { return inRHS.mPtr && inRHS->__GetType()==vtString; }
template<> inline bool isStringType(const cpp::Variant &inRHS) { return inRHS.isString(); }
template<typename T,typename H>
Variant::Variant(const cpp::Struct<T,H> &inVal) :
type(typeObject), valObject(Dynamic(inVal).mPtr) { }
template<typename T>
Variant::Variant(const cpp::Pointer<T> &inRHS) : type(typeObject), valObject( Dynamic(inRHS).mPtr ) { }
template<typename T>
Variant::Variant(const cpp::Function<T> &inRHS) : type(typeObject), valObject( Dynamic(inRHS).mPtr ) { }
template<typename T>
Variant::Variant(const hx::Native<T> &inRHS) : type(typeObject), valObject( CreateDynamicPointer(inRHS.ptr).mPtr ) { }
#define HX_ARITH_VARIANT( op ) \
inline double operator op (const double &inLHS,const cpp::Variant &inRHS) { return inLHS op (double)inRHS;} \
inline double operator op (const float &inLHS,const cpp::Variant &inRHS) { return inLHS op (double)inRHS;} \
inline double operator op (const int &inLHS,const cpp::Variant &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const unsigned int &inLHS,const cpp::Variant &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const signed char &inLHS,const cpp::Variant &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const unsigned char &inLHS,const cpp::Variant &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const signed short &inLHS,const cpp::Variant &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const unsigned short &inLHS,const cpp::Variant &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const cpp::Int64 &inLHS,const cpp::Variant &inRHS) { return inLHS op (double)inRHS; } \
inline double operator op (const cpp::UInt64 &inLHS,const cpp::Variant &inRHS) { return inLHS op (double)inRHS; } \
HX_ARITH_VARIANT( - )
HX_ARITH_VARIANT( + )
HX_ARITH_VARIANT( / )
HX_ARITH_VARIANT( * )
inline bool Variant::operator==(const String &inString) const
{
if (isNull()) return inString==null();
return type==typeString && asString()==inString;
}
inline bool Variant::operator!=(const String &inString) const
{
if (isNull()) return inString!=null();
return type!=typeString || asString()!=inString;
}
inline bool Variant::operator < (const String &inRHS) const { return asString() < inRHS; }
inline bool Variant::operator <= (const String &inRHS) const { return asString() < inRHS; }
inline bool Variant::operator > (const String &inRHS) const { return asString() > inRHS; }
inline bool Variant::operator >= (const String &inRHS) const { return asString() >= inRHS; }
Variant::Variant(const ::String &inValue) :
type(typeString), valStringPtr(inValue.raw_ptr()), valStringLen(inValue.length) { }
Variant::Variant(const Dynamic &inRHS) : type(typeObject), valObject(inRHS.mPtr) { }
template<typename SOURCE_>
Variant::Variant(const hx::ObjectPtr<SOURCE_> &inObjectPtr) :
type(typeObject), valObject(inObjectPtr.mPtr) { }
inline void Variant::CheckFPtr()
{
if (isNull()) Dynamic::ThrowBadFunctionError();
}
HX_IMPLEMENT_INLINE_VARIANT_FUNCTIONS
int Variant::asInt() const
{
if (type==typeInt)
return valInt;
switch(type)
{
case typeDouble: return valDouble;
case typeInt64: return (int)valInt64;
case typeBool: return valBool;
case typeObject: return valObject ? valObject->__ToInt() : 0;
default: ;
}
return 0;
}
cpp::Int64 Variant::asInt64() const
{
if (type==typeInt64)
return valInt64;
switch(type)
{
case typeDouble: return valDouble;
case typeInt: return valInt;
case typeBool: return valBool;
case typeObject: return valObject ? valObject->__ToInt64() : 0;
default: ;
}
return 0;
}
double Variant::asDouble() const
{
if (type==typeDouble)
return valDouble;
else if (type==typeInt)
return valInt;
else if (type==typeBool)
return valBool ? 1.0 : 0.0;
else if (type==typeInt64)
return valInt64;
else if (type==typeObject)
return valObject ? valObject->__ToDouble() : 0.0;
return 0.0;
}
inline hx::Object *Variant::toDynamic() const
{
switch(type)
{
case typeInt: return Dynamic(valInt).mPtr;
case typeDouble: return Dynamic(valDouble).mPtr;
case typeBool: return Dynamic(valBool).mPtr;
case typeString: return Dynamic(String(valStringPtr, valStringLen)).mPtr;
case typeInt64: return Dynamic(valInt64).mPtr;
case typeObject: return valObject;
default: ;
}
return 0;
}
/*
Variant::operator Dynamic() const
{
switch(type)
{
case typeInt: return valInt;
case typeDouble: return valDouble;
case typeBool: return valBool;
case typeString: return String(valStringPtr, valStringLen);
case typeObject: return valObject;
default: ;
}
return null();
}
*/
bool Variant::isNumeric() const
{
if (type==typeInt || type==typeDouble || type==typeInt64)
return true;
if (type!=typeObject || valObject==0)
return false;
int t = valObject->__GetType();
return t==vtInt || t==vtFloat;
}
bool Variant::isBool() const
{
if (type==typeBool)
return true;
if (type!=typeObject || valObject==0)
return false;
return valObject->__GetType() == vtBool;
}
String Variant::getString() const { return String(valStringPtr, valStringLen); }
String Variant::asString() const
{
switch(type)
{
case typeInt: return String(valInt);
case typeDouble: return String(valDouble);
case typeBool: return String(valBool);
case typeString: return String(valStringPtr, valStringLen);
case typeInt64: return String(valInt64);
case typeObject: return valObject ? valObject->toString() : String();
default: ;
}
return String();
}
//Variant::operator String() const { return asString(); }
void Variant::mark(hx::MarkContext *__inCtx)
{
if (type==typeString)
{
HX_MARK_STRING(valStringPtr);
}
else if (type==typeObject)
{
HX_MARK_OBJECT(valObject);
}
}
template<typename T>
bool Variant::operator==(const T &inRHS) const
{
switch(type)
{
case typeInt: return valInt==(double)inRHS;
case typeDouble:return valDouble==(double)inRHS;
case typeBool: return valBool==(bool)inRHS;
case typeInt64: return valInt64==(cpp::Int64)inRHS;
case typeString: return getString()==String(inRHS);
case typeObject:
if (!valObject)
return inRHS == null();
return valObject->__Compare( Dynamic(inRHS).mPtr )==0;
}
return false;
}
int Variant::Compare(hx::Object *inPtr) const
{
if (!inPtr)
return isNull() ? 0 : 1;
switch(type)
{
case typeInt:
{
double diff = valInt - inPtr->__ToDouble();
return diff<0 ? -1 : diff==0 ? 0 : 1;
}
case typeDouble:
{
double diff = valDouble - inPtr->__ToDouble();
return diff<0 ? -1 : diff==0 ? 0 : 1;
}
case typeInt64:
{
cpp::Int64 diff = valInt64 - inPtr->__ToInt64();
return diff<0 ? -1 : diff==0 ? 0 : 1;
}
case typeBool:
if (!inPtr) return 1;
return valBool==(bool)(inPtr->__ToInt()) ? 1 : 0;
case typeString:
if (!inPtr) return valStringPtr ? 1 : 0;
if (inPtr->__GetType()!=vtString)
return 1;
return String(valStringPtr, valStringLen)==inPtr->toString() ? 1 : 0;
case typeObject:
#if (HXCPP_API_LEVEL>=331)
return valObject->__Compare( inPtr );
#else
return valObject->__Compare( inPtr->__GetRealObject() );
#endif
default: ;
}
return 0;
}
int Variant::Compare(const Dynamic &inD) const { return Compare(inD.mPtr); }
int Variant::Compare(const cpp::Variant &inVar) const
{
if (inVar.type==typeObject)
return Compare(inVar.valObject);
switch(type)
{
case typeInt:
{
double diff = valInt - inVar.asDouble();
return diff<0 ? -1 : diff==0 ? 0 : 1;
}
case typeDouble:
{
double diff = valDouble - inVar.asDouble();
return diff<0 ? -1 : diff==0 ? 0 : 1;
}
case typeInt64:
{
cpp::Int64 diff = valInt64 - inVar.asInt64();
return diff<0 ? -1 : diff==0 ? 0 : 1;
}
case typeBool:
return valBool==(bool)(inVar.asInt()) ? 1 : 0;
case typeString:
if (inVar.type!=typeString)
return 1;
return String(valStringPtr, valStringLen)==inVar.asString();
case typeObject:
if (!valObject)
return 1;
return - inVar.Compare(*this);
}
return 0;
}
String cpp::Variant::operator+(const String &s) const
{
return asString() + s;
}
template<typename T>
cpp::Variant Variant::operator + (const T &inRHS) const
{
if (isString() || ::cpp::isStringType(inRHS))
return asString() + String(inRHS);
return asDouble() + (double)inRHS;
}
#ifdef HXCPP_VISIT_ALLOCS
void Variant::visit(hx::VisitContext *__inCtx)
{
if (type==typeString)
{
HX_VISIT_STRING(valStringPtr);
}
else if (type==typeObject)
{
HX_VISIT_OBJECT(valObject);
}
}
#endif // HXCPP_VISIT_ALLOCS
#define HX_VARIANT_OP_ISEQ(T) \
inline bool operator == (const T &inLHS,const cpp::Variant &inRHS) { return inRHS==inLHS; } \
inline bool operator != (const T &inLHS,const cpp::Variant &inRHS) { return inRHS!=inLHS; }
#define HX_VARIANT_OP_ISEQ(T) \
inline bool operator == (const T &inLHS,const cpp::Variant &inRHS) { return inRHS==inLHS; } \
inline bool operator != (const T &inLHS,const cpp::Variant &inRHS) { return inRHS!=inLHS; }
HX_VARIANT_OP_ISEQ(String)
HX_VARIANT_OP_ISEQ(double)
HX_VARIANT_OP_ISEQ(float)
HX_VARIANT_OP_ISEQ(cpp::Int64)
HX_VARIANT_OP_ISEQ(cpp::UInt64)
HX_VARIANT_OP_ISEQ(int)
HX_VARIANT_OP_ISEQ(unsigned int)
HX_VARIANT_OP_ISEQ(short)
HX_VARIANT_OP_ISEQ(unsigned short)
HX_VARIANT_OP_ISEQ(signed char)
HX_VARIANT_OP_ISEQ(unsigned char)
HX_VARIANT_OP_ISEQ(bool)
inline bool operator < (bool inLHS,const cpp::Variant &inRHS) { return false; }
inline bool operator <= (bool inLHS,const cpp::Variant &inRHS) { return false; }
inline bool operator >= (bool inLHS,const cpp::Variant &inRHS) { return false; }
inline bool operator > (bool inLHS,const cpp::Variant &inRHS) { return false; }
#define HX_COMPARE_VARIANT_OP( op ) \
inline bool operator op (double inLHS,const ::cpp::Variant &inRHS) \
{ return inRHS.isNumeric() && (inLHS op (double)inRHS); } \
inline bool operator op (float inLHS,const ::cpp::Variant &inRHS) \
{ return inRHS.isNumeric() && ((double)inLHS op (double)inRHS); } \
inline bool operator op (cpp::Int64 inLHS,const ::cpp::Variant &inRHS) \
{ return inRHS.isNumeric() && (inLHS op (double)inRHS); } \
inline bool operator op (cpp::UInt64 inLHS,const ::cpp::Variant &inRHS) \
{ return inRHS.isNumeric() && (inLHS op (double)inRHS); } \
inline bool operator op (int inLHS,const ::cpp::Variant &inRHS) \
{ return inRHS.isNumeric() && (inLHS op (double)inRHS); } \
inline bool operator op (unsigned int inLHS,const ::cpp::Variant &inRHS) \
{ return inRHS.isNumeric() && (inLHS op (double)inRHS); } \
inline bool operator op (short inLHS,const ::cpp::Variant &inRHS) \
{ return inRHS.isNumeric() && (inLHS op (double)inRHS); } \
inline bool operator op (unsigned short inLHS,const ::cpp::Variant &inRHS) \
{ return inRHS.isNumeric() && (inLHS op (double)inRHS); } \
inline bool operator op (signed char inLHS,const ::cpp::Variant &inRHS) \
{ return inRHS.isNumeric() && (inLHS op (double)inRHS); } \
inline bool operator op (unsigned char inLHS,const ::cpp::Variant &inRHS) \
{ return inRHS.isNumeric() && (inLHS op (double)inRHS); } \
inline bool operator op (const null &,const ::cpp::Variant &inRHS) \
{ return false; } \
HX_COMPARE_VARIANT_OP( < )
HX_COMPARE_VARIANT_OP( <= )
HX_COMPARE_VARIANT_OP( >= )
HX_COMPARE_VARIANT_OP( > )
} // close cpp
namespace hx {
template<typename T>
bool ObjectPtr<T>::operator==(const cpp::Variant &inRHS) const {
return inRHS.Compare(mPtr)==0;
}
template<typename T>
bool ObjectPtr<T>::operator!=(const cpp::Variant &inRHS) const {
return inRHS.Compare(mPtr)!=0;
}
} // close hx
namespace cpp {
#endif // not twice
} // end namespace cpp
#endif // CPP_VARIANT_TWICE_H

View File

@ -0,0 +1,727 @@
namespace cpp
{
// This file is included twice - either side of the Array definition
#ifndef HX_VARRAY_DEFINED
#define HX_VARRAY_DEFINED
class VirtualArray : public hx::ObjectPtr<VirtualArray_obj>
{
typedef hx::ObjectPtr<VirtualArray_obj> super;
public:
typedef Dynamic Elem;
inline VirtualArray() : super(0) { }
inline VirtualArray(VirtualArray_obj *inObj) : super(inObj) { }
inline VirtualArray(const null &inNull) : super(0) { }
inline VirtualArray(const VirtualArray &inOther) : super( inOther.mPtr ) { }
// Build from foreign array
template<typename SOURCE_> inline VirtualArray( const Array<SOURCE_> &inRHS );
inline VirtualArray( const Dynamic &inRHS ) : super(0) { setDynamic(inRHS); }
inline VirtualArray( const cpp::ArrayBase &inRHS ) : super(0) { setDynamic(inRHS); }
inline VirtualArray(const ::cpp::Variant &inVariant) { setDynamic(inVariant.asObject()); }
inline VirtualArray &operator=(const null &inNull) { mPtr = 0; return *this; }
inline VirtualArray &operator=(Ptr inRHS) { mPtr = inRHS; return *this; }
inline VirtualArray &operator=(const VirtualArray &inRHS) { mPtr = inRHS.mPtr; return *this; }
inline void setDynamic( const Dynamic &inRHS );
template<typename T>
inline VirtualArray Add(const T &inVal);
inline bool operator==(const Dynamic &value) const { return value==*this; }
template<typename SOURCE_> inline bool operator==( const Array<SOURCE_> &inRHS );
inline bool operator!=(Dynamic value) const { return value!=*this; }
template<typename SOURCE_> inline bool operator!=( const Array<SOURCE_> &inRHS ) { return inRHS!=*this; }
};
class HXCPP_EXTERN_CLASS_ATTRIBUTES VirtualArray_obj : public hx::ArrayCommon
{
typedef hx::ArrayStore ArrayStore;
typedef hx::ArrayBase ArrayBase;
public:
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdVirtualArray };
typedef hx::Object super;
ArrayStore store;
ArrayBase *base;
VirtualArray_obj(ArrayBase *inBase=0, bool inFixed=false) : base(inBase)
{
mArrayConvertId = hx::aciVirtualArray;
store = inFixed && inBase ? hx::arrayFixed : base ? base->getStoreType() : hx::arrayEmpty;
#ifdef HXCPP_GC_GENERATIONAL
if (base)
HX_OBJ_WB_GET(this,base);
#endif
}
VirtualArray_obj(ArrayStore inStore)
{
mArrayConvertId = hx::aciVirtualArray;
store = inStore;
}
hx::Object *__GetRealObject() { return base?(hx::Object *)base:(hx::Object *)this; }
inline static VirtualArray __new(int inSize=0,int inReserve=0)
{
VirtualArray result = new VirtualArray_obj(hx::arrayEmpty);
if (inSize>0)
result->__SetSizeExact(inSize);
if (inReserve>0)
result->reserve(inReserve);
return result;
}
#if (HXCPP_API_LEVEL>330)
int __Compare(const hx::Object *inRHS) const;
#endif
inline int get_length() const
{
return base ? base->length : 0;
}
inline void checkBase() const
{
#ifdef HXCPP_CHECK_POINTER
if (store==hx::arrayNull)
{
hx::NullReference("Array", true);
// The handler might have fixed up the null value
if (store==hx::arrayNull) hx::NullReference("Array", false);
}
#endif
}
void EnsureStorage(const Dynamic &inValue)
{
if (!inValue.mPtr)
{
EnsureNullStorage();
}
else switch(inValue->__GetType())
{
case vtBool: EnsureBoolStorage(); break;
case vtInt: EnsureIntStorage(); break;
case vtFloat: EnsureFloatStorage(); break;
case vtString: EnsureStringStorage(); break;
case vtInt64: EnsureInt64Storage(); break;
default: EnsureObjectStorage();
}
}
void EnsureStorage(const cpp::Variant &inValue)
{
switch(inValue.type)
{
case Variant::typeObject:
if (!inValue.valObject)
EnsureNullStorage();
else
EnsureObjectStorage();
break;
case Variant::typeString: EnsureStringStorage(); break;
case Variant::typeDouble: EnsureFloatStorage(); break;
case Variant::typeInt: EnsureIntStorage(); break;
case Variant::typeBool: EnsureBoolStorage(); break;
case Variant::typeInt64: EnsureInt64Storage(); break;
}
}
void MakeIntArray();
void MakeInt64Array();
void MakeObjectArray();
void MakeFloatArray();
void MakeBoolArray();
void MakeStringArray();
void EnsureStorage(const VirtualArray &inValue) { EnsureObjectStorage(); }
void EnsureStorage(const unsigned char &inValue) { EnsureIntStorage(); }
void EnsureStorage(const bool &inValue) { EnsureBoolStorage(); }
void EnsureStorage(const String &inValue) { EnsureStringStorage(); }
void EnsureStorage(const double &inValue) { EnsureFloatStorage(); }
void EnsureStorage(const float &inValue) { EnsureFloatStorage(); }
void EnsureStorage(const int &inValue) { EnsureIntStorage(); }
void EnsureStorage(const cpp::Int64 &inValue) { EnsureInt64Storage(); }
void EnsureStorage(const cpp::UInt64 &inValue) { EnsureInt64Storage(); }
void EnsureStorage(const null &inValue) { EnsureNullStorage(); }
template<typename T>
void EnsureStorage(const T &inValue) { EnsureObjectStorage(); }
inline void EnsureBoolStorage()
{
switch(store)
{
case hx::arrayNull:
case hx::arrayObject:
case hx::arrayFixed:
case hx::arrayBool:
return;
case hx::arrayEmpty:
MakeBoolArray();
break;
case hx::arrayInt:
case hx::arrayInt64:
case hx::arrayFloat:
case hx::arrayString:
MakeObjectArray();
break;
}
}
inline void EnsureStringStorage()
{
switch(store)
{
case hx::arrayNull:
case hx::arrayObject:
case hx::arrayFixed:
case hx::arrayString:
return;
case hx::arrayEmpty:
MakeStringArray();
break;
case hx::arrayInt:
case hx::arrayInt64:
case hx::arrayFloat:
case hx::arrayBool:
MakeObjectArray();
break;
}
}
inline void EnsureFloatStorage()
{
switch(store)
{
case hx::arrayNull:
case hx::arrayFloat:
case hx::arrayObject:
case hx::arrayFixed:
return;
case hx::arrayInt:
case hx::arrayInt64:
case hx::arrayEmpty:
MakeFloatArray();
break;
case hx::arrayBool:
case hx::arrayString:
MakeObjectArray();
break;
}
}
inline void EnsureIntStorage()
{
switch(store)
{
case hx::arrayNull:
case hx::arrayInt:
case hx::arrayInt64:
case hx::arrayFloat:
case hx::arrayObject:
case hx::arrayFixed:
return;
case hx::arrayEmpty:
MakeIntArray();
break;
case hx::arrayBool:
case hx::arrayString:
MakeObjectArray();
break;
}
}
inline void EnsureInt64Storage()
{
switch(store)
{
case hx::arrayNull:
case hx::arrayInt64:
case hx::arrayFloat:
case hx::arrayObject:
case hx::arrayFixed:
return;
case hx::arrayInt:
case hx::arrayEmpty:
MakeInt64Array();
break;
case hx::arrayBool:
case hx::arrayString:
MakeObjectArray();
break;
}
}
inline void EnsureObjectStorage()
{
switch(store)
{
case hx::arrayNull:
case hx::arrayObject:
case hx::arrayFixed:
return;
case hx::arrayEmpty:
case hx::arrayInt:
case hx::arrayInt64:
case hx::arrayFloat:
case hx::arrayBool:
case hx::arrayString:
MakeObjectArray();
break;
}
}
inline void EnsureNullStorage()
{
switch(store)
{
case hx::arrayNull:
case hx::arrayObject:
case hx::arrayFixed:
case hx::arrayString:
return;
case hx::arrayEmpty:
case hx::arrayInt:
case hx::arrayInt64:
case hx::arrayFloat:
case hx::arrayBool:
MakeObjectArray();
break;
}
}
template<typename F> void fixType();
template<typename F> F castArray();
void EnsureBase();
void CreateEmptyArray(int inLen);
void EnsureArrayStorage(ArrayStore inValue);
void EnsureArrayStorage(VirtualArray inValue);
void __Mark(hx::MarkContext *__inCtx)
{
HX_MARK_OBJECT(base);
}
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *__inCtx)
{
if (base)
__inCtx->visitObject( (hx::Object **)&base);
}
#endif
// Used by cpp.ArrayBase
inline int getElementSize() const { return base ? base->GetElementSize() : 0; }
inline int getByteCount() const { return base ? base->getByteCount() : 0; }
inline char * getBase() const { return base ? base->GetBase() : 0; }
hx::Val __SetField(const String &inString,const hx::Val &inValue ,hx::PropertyAccess inCallProp) { return null(); }
static hx::Class &__SGetClass() { return hx::ArrayBase::__mClass; }
hx::Class __GetClass() const;
String toString();
String __ToString() const { return const_cast<VirtualArray_obj *>(this)->toString(); }
void setData(void *inData, int inElements) { EnsureBase(); base->setData(inData, inElements); }
void setUnmanagedData(void *inData, int inElements) { EnsureBase(); base->setUnmanagedData(inData, inElements); }
int __GetType() const { return vtArray; }
inline size_t size() const { checkBase(); return store==hx::arrayEmpty ? 0 : base->length; }
inline int __length() const { checkBase(); return store==hx::arrayEmpty ? 0 : (int)base->length; }
String ItemString(int inI) { checkBase(); return store==hx::arrayEmpty ? null() : base->ItemString(inI); }
const char * __CStr() const { return store==hx::arrayEmpty ? "[]" : store==hx::arrayNull ? "null" : base->__CStr(); }
inline const char *GetBase() const { return base ? base->GetBase() : 0; }
inline char *GetBase() { return base ? base->GetBase() : 0; }
int GetElementSize() const { checkBase(); return store==hx::arrayEmpty ? 0 : base->GetElementSize(); }
inline void reserve(int inSize) const
{
if (base)
base->reserve(inSize);
}
inline int capacity()
{
if (base)
return base->capacity();
return 0;
}
void resize(int inLen)
{
if (!base)
CreateEmptyArray(inLen);
else
base->resize(inLen);
}
void __SetSize(int inLen) { resize(inLen); }
VirtualArray __SetSizeExact(int inLen=0)
{
if (!base && inLen)
CreateEmptyArray(inLen);
else if (base)
base->__SetSizeExact(inLen);
return this;
}
void safeSort(Dynamic sorter, bool isString) { checkBase(); if (store!=hx::arrayEmpty) base->safeSort(sorter,isString); }
inline void __unsafeStringReference(String inString) { if (base) base->__unsafeStringReference(inString); }
Dynamic __GetItem(int inIndex) const;
Dynamic __SetItem(int inIndex,Dynamic inValue);
hx::Val __Field(const String &inString, hx::PropertyAccess inCallProp);
template<typename T>
inline const T &set(int inIdx, const T &inVal)
{
if (store!=hx::arrayFixed)
{
if (inIdx>(store==hx::arrayEmpty ? 0 : (int)base->length) )
EnsureObjectStorage();
else
EnsureStorage(inVal);
}
base->set(inIdx, inVal);
return inVal;
}
template<typename T>
inline int push(const T &inVal)
{
if (store!=hx::arrayFixed) EnsureStorage(inVal);
return base->__push(Dynamic(inVal));
}
template<typename T>
inline VirtualArray_obj *Add(const T &inVal)
{
if (store!=hx::arrayFixed) EnsureStorage(inVal);
base->__push(Dynamic(inVal));
return this;
}
inline Dynamic pop() { checkBase(); return store==hx::arrayEmpty ? null() : base->__pop(); }
inline bool contains(Dynamic inValue)
{
checkBase();
if (store==hx::arrayEmpty)
return false;
EnsureStorage(inValue);
return base->__contains(inValue);
}
inline bool remove(Dynamic inValue)
{
checkBase();
if (store==hx::arrayEmpty)
return false;
EnsureStorage(inValue);
return base->__remove(inValue);
}
inline bool removeAt(int inIndex) { checkBase(); return (store!=hx::arrayEmpty) && base->__removeAt(inIndex); }
int indexOf(Dynamic inValue, Dynamic fromIndex = null())
{
checkBase();
if (store==hx::arrayEmpty)
return -1;
EnsureStorage(inValue);
return (int)base->__indexOf(inValue,fromIndex);
}
int lastIndexOf(Dynamic inValue, Dynamic fromIndex = null())
{
checkBase();
if (store==hx::arrayEmpty)
return -1;
EnsureStorage(inValue);
return (int)base->__lastIndexOf(inValue,fromIndex);
}
Dynamic shift() { checkBase(); return store==hx::arrayEmpty ? null() : base->__shift(); }
VirtualArray concat( VirtualArray inTail )
{
inTail->checkBase();
EnsureArrayStorage(inTail);
if (inTail->__length()<1)
return copy();
return new VirtualArray_obj( base->__concat(inTail), store==hx::arrayFixed );
}
VirtualArray copy( )
{
checkBase();
if (store==hx::arrayEmpty)
return new VirtualArray_obj(hx::arrayEmpty);
return new VirtualArray_obj(base->__copy(), store==hx::arrayFixed);
}
VirtualArray slice(int inPos, Dynamic end = null())
{
checkBase();
if (store==hx::arrayEmpty)
return new VirtualArray_obj(hx::arrayEmpty);
return new VirtualArray_obj(base->__slice(inPos,end), store==hx::arrayFixed);
}
VirtualArray splice(int inPos, int len);
VirtualArray map(Dynamic inFunc);
VirtualArray filter(Dynamic inFunc);
template<typename T>
inline VirtualArray init(int inIndex, const T &inVal)
{
if (store!=hx::arrayFixed) EnsureStorage(inVal);
__SetItem(inIndex,inVal);
return this;
}
inline Dynamic __unsafe_set(int inIndex, const Dynamic &val) { return __SetItem(inIndex,val); }
inline Dynamic __unsafe_get(int inIndex) { return __GetItem(inIndex); }
template<typename T>
inline void insert(int inPos, const T &inValue)
{
if (store!=hx::arrayFixed)
{
if (inPos>(store==hx::arrayEmpty ? 0 : (int)base->length) )
EnsureObjectStorage();
else
EnsureStorage(inValue);
}
base->__insert(inPos,inValue);
}
template<typename T>
inline void unshift(const T& inValue)
{
if (store!=hx::arrayFixed) EnsureStorage(inValue);
base->__unshift(inValue);
}
inline void reverse() { checkBase(); if (store!=hx::arrayEmpty) base->__reverse(); }
inline void qsort(Dynamic inSorter) { checkBase(); if (base) base->__qsort(inSorter); }
inline void sort(Dynamic inSorter) { checkBase(); if (base) base->__sort(inSorter); }
Dynamic iterator() { checkBase(); return !base ? getEmptyIterator() : base->__iterator(); }
static Dynamic getEmptyIterator();
Dynamic keyValueIterator() { checkBase(); return !base ? getEmptyIterator() : base->__keyValueIterator(); }
bool IsByteArray() const { checkBase(); return store!=hx::arrayEmpty && base->IsByteArray(); }
void zero(Dynamic inFirst, Dynamic inCount) { checkBase(); if (store!=hx::arrayEmpty) base->zero(inFirst,inCount); }
inline int memcmp(VirtualArray inOther)
{
checkBase();
if (store==hx::arrayEmpty)
return inOther->__length() == 0;
return base->__memcmp(inOther);
}
inline void blit(int inDestElement, cpp::VirtualArray inSourceArray, int inSourceElement, int inElementCount)
{
inSourceArray->checkBase();
EnsureArrayStorage(inSourceArray);
if (base)
base->__blit(inDestElement, inSourceArray, inSourceElement, inElementCount);
}
String join(String inSeparator) { checkBase(); if (!base) return HX_CSTRING(""); return base->__join(inSeparator); }
Dynamic __get(int inIndex) const { checkBase(); if (store==hx::arrayEmpty) return null(); return base->__GetItem(inIndex); }
Dynamic concat_dyn();
Dynamic copy_dyn();
Dynamic insert_dyn();
Dynamic iterator_dyn();
Dynamic keyValueIterator_dyn();
Dynamic join_dyn();
Dynamic pop_dyn();
Dynamic push_dyn();
Dynamic contains_dyn();
Dynamic remove_dyn();
Dynamic removeAt_dyn();
Dynamic indexOf_dyn();
Dynamic lastIndexOf_dyn();
Dynamic reverse_dyn();
Dynamic shift_dyn();
Dynamic slice_dyn();
Dynamic splice_dyn();
Dynamic sort_dyn();
Dynamic toString_dyn();
Dynamic unshift_dyn();
Dynamic map_dyn();
Dynamic filter_dyn();
Dynamic __SetSize_dyn();
Dynamic __SetSizeExact_dyn();
Dynamic __unsafe_get_dyn();
Dynamic __unsafe_set_dyn();
Dynamic blit_dyn();
Dynamic zero_dyn();
Dynamic memcmp_dyn();
Dynamic resize_dyn();
};
//typedef hx::ObjectPtr< VirtualArray_obj > VirtualArray;
#else // !HX_VARRAY_DEFINED
// Build dynamic array from foreign array
template<typename SOURCE_>
VirtualArray::VirtualArray( const Array<SOURCE_> &inRHS )
: super( !inRHS.mPtr ? 0 : new VirtualArray_obj( inRHS.mPtr, true) )
{
}
template<typename T>
inline VirtualArray VirtualArray::Add(const T &inVal)
{
mPtr->push(inVal);
return *this;
}
inline void VirtualArray::setDynamic( const Dynamic &inRHS )
{
hx::Object *ptr = inRHS.GetPtr();
if (ptr)
{
if (ptr->__GetClass().mPtr == super::__SGetClass().mPtr )
{
cpp::VirtualArray_obj *varray = dynamic_cast<cpp::VirtualArray_obj *>(ptr);
if (varray)
mPtr = varray;
else
mPtr = new VirtualArray_obj(dynamic_cast<cpp::ArrayBase_obj *>(ptr), true);
}
}
}
template<typename F>
void VirtualArray_obj::fixType()
{
if (store==hx::arrayFixed)
return;
store = hx::arrayFixed;
if (base && base->length>0)
{
Array<F> fixedArray = Dynamic(base);
base = fixedArray.mPtr;
}
else
{
base = new Array_obj<F>(0,0);
}
#ifdef HXCPP_GC_GENERATIONAL
if (base)
HX_OBJ_WB_GET(this,base);
#endif
}
template<typename ARRAY >
ARRAY VirtualArray_obj::castArray()
{
if (store==hx::arrayFixed)
return Dynamic(base);
store = hx::arrayFixed;
if (base && base->length>0)
{
ARRAY fixedArray = Dynamic(base);
base = fixedArray.mPtr;
#ifdef HXCPP_GC_GENERATIONAL
if (base)
HX_OBJ_WB_GET(this,base);
#endif
return fixedArray;
}
else
{
ARRAY fixedArray(0,0);
base = fixedArray.mPtr;
#ifdef HXCPP_GC_GENERATIONAL
if (base)
HX_OBJ_WB_GET(this,base);
#endif
return fixedArray;
}
}
template<typename SOURCE_>
inline bool VirtualArray::operator==( const Array<SOURCE_> &inRHS )
{
if (!mPtr)
return inRHS.mPtr;
return mPtr->castArray< Array<SOURCE_> >() == inRHS;
}
} // end namespace cpp
HXCPP_EXTERN_CLASS_ATTRIBUTES Dynamic _hx_reslove_virtual_array(cpp::VirtualArray inArray);
namespace hx
{
// For type inference when marking
template<> inline void MarkMember(cpp::VirtualArray &outT,hx::MarkContext *__inCtx)
{ HX_MARK_OBJECT(outT.mPtr); }
#ifdef HXCPP_VISIT_ALLOCS
template<> inline void VisitMember(cpp::VirtualArray &outT,hx::VisitContext *__inCtx)
{
HX_VISIT_OBJECT(outT.mPtr);
}
#endif
} // end namespace hx
namespace cpp
{
#endif // HX_VARRAY_DEFINED
}

View File

@ -0,0 +1,38 @@
#pragma once
#include <assert.h>
#include <stdint.h>
struct bytearray {
uint8_t *data;
int refCount;
bytearray() {
data = NULL;
refCount = 0;
}
void alloc(int length) {
data = new uint8_t[length];
}
void addRef() {
++refCount;
}
void subRef() {
--refCount;
if (refCount == 0) {
delete[] data;
data = NULL;
}
}
float get(int index) {
return data[index];
}
float set(int index, float value) {
return data[index] = value;
}
};

View File

@ -0,0 +1,755 @@
#ifndef HX_ANON_H
#define HX_ANON_H
namespace hx
{
typedef Dynamic FieldMap;
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic FieldMapCreate();
HXCPP_EXTERN_CLASS_ATTRIBUTES
bool FieldMapGet(Dynamic *inMap, const ::String &inName, ::Dynamic &outValue);
HXCPP_EXTERN_CLASS_ATTRIBUTES
bool FieldMapHas(Dynamic *inMap, const ::String &inName);
HXCPP_EXTERN_CLASS_ATTRIBUTES
bool FieldMapGet(Dynamic *inMap, int inID, ::Dynamic &outValue);
HXCPP_EXTERN_CLASS_ATTRIBUTES
#ifdef HXCPP_GC_GENERATIONAL
void FieldMapSet(hx::Object *inThis,Dynamic *inMap, const ::String &inName, const ::Dynamic &inValue);
#else
void FieldMapSet(Dynamic *inMap, const ::String &inName, const ::Dynamic &inValue);
#endif
HXCPP_EXTERN_CLASS_ATTRIBUTES
void FieldMapAppendFields(Dynamic *inMap,::Array< ::String> &outFields);
HXCPP_EXTERN_CLASS_ATTRIBUTES
void FieldMapMark(Dynamic *inMap,hx::MarkContext *__inCtx);
#ifdef HXCPP_VISIT_ALLOCS
HXCPP_EXTERN_CLASS_ATTRIBUTES
void FieldMapVisit(Dynamic **inMap,hx::VisitContext *__inCtx);
#endif
} // end namespace hx
namespace hx
{
// --- hx::Anon_obj ----------------------------------------------
//
// The hx::Anon_obj contains an arbitrary string map of fields.
class HXCPP_EXTERN_CLASS_ATTRIBUTES Anon_obj : public hx::Object
{
typedef hx::Anon_obj OBJ_;
typedef hx::ObjectPtr<hx::Anon_obj> Anon;
typedef hx::Object super;
inline void *operator new( size_t inSize, int inExtra )
{
return hx::Object::operator new(inSize+inExtra, true, 0);
}
struct VariantKey
{
int hash;
String key;
cpp::Variant value;
};
Dynamic mFields;
int mFixedFields;
public:
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdDynamic };
inline void *operator new( size_t inSize )
{
return hx::Object::operator new(inSize, true, 0);
}
inline void operator delete(void *, size_t inSize ) { }
inline void operator delete(void *, size_t inSize, int inExtra ) { }
inline Anon_obj *setFixed(int index, const String &inName, const ::cpp::Variant &inValue)
{
VariantKey *fixed = getFixed() + index;
fixed->hash = inName.hash();
fixed->key = inName;
fixed->value = inValue;
if (inValue.type == ::cpp::Variant::typeObject) {
HX_OBJ_WB_GET(this, inValue.valObject);
}
else if (inValue.type == ::cpp::Variant::typeString) {
HX_OBJ_WB_GET(this, inValue.valStringPtr);
}
return this;
}
inline VariantKey *getFixed()
{
return (VariantKey *)(this + 1);
}
inline int findFixed(const ::String &inKey,bool inSkip5 = false);
Anon_obj(int inFixedFields = 0);
static Anon Create(int inElements)
{
return Anon(new (inElements*sizeof(VariantKey) ) hx::Anon_obj(inElements) );
}
static Anon Create() { return Anon(new (0) hx::Anon_obj); }
static Anon Create(const Dynamic &inSrc) { return Anon(new (0) hx::Anon_obj); }
static Dynamic __CreateEmpty() { return Anon(new (0) hx::Anon_obj); }
static Dynamic __Create(DynamicArray inArgs);
static void __boot();
void operator delete( void *, int) { }
hx::Val __Field(const String &inString ,hx::PropertyAccess inCallProp);
bool __HasField(const String &inString);
hx::Val __SetField(const String &inString,const hx::Val &inValue ,hx::PropertyAccess inCallProp);
virtual void __GetFields(Array<String> &outFields);
Dynamic *__GetFieldMap() { return &mFields; }
virtual int __GetType() const { return vtObject; }
hx::Anon_obj *Add(const String &inName,const Dynamic &inValue,bool inSetThisPointer=true);
void __Mark(hx::MarkContext *__inCtx);
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *__inCtx);
#endif
String __ToString() const;
String toString();
static hx::ObjectPtr<hx::Class_obj> __mClass; \
static hx::ObjectPtr<hx::Class_obj> &__SGetClass() { return __mClass; }
#if (HXCPP_API_LEVEL<331)
bool __Is(hx::Object *inObj) const { return dynamic_cast<OBJ_ *>(inObj)!=0; }
#endif
hx::ObjectPtr<hx::Class_obj > __GetClass() const { return __mClass; }
bool __Remove(String inKey);
};
typedef hx::ObjectPtr<hx::Anon_obj> Anon;
HXCPP_EXTERN_CLASS_ATTRIBUTES
Anon SourceInfo(String inFile, int inLine, String inClass, String inMethod);
HXCPP_EXTERN_CLASS_ATTRIBUTES String StringFromAnonFields(hx::Object *inPtr);
template<typename _hx_T0>
class AnonStruct1_obj : public hx::Object
{
public:
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdDynamic };
String name0; _hx_T0 t0;
inline static hx::Object *Create(const String &inName0, _hx_T0 inT0)
{
AnonStruct1_obj *result = new AnonStruct1_obj;
result->name0 = inName0; result->t0 = inT0;
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT0));
}
return result;
}
hx::Val __Field(const String &inField, hx::PropertyAccess)
{
if (HX_QSTR_EQ(inField,name0)) return t0;
return null();
}
hx::Val __SetField(const String &inField,const hx::Val &inValue, hx::PropertyAccess inCallProp)
{
if (inField.__s==name0.__s || HX_QSTR_EQ(inField,name0)) {
t0 = inValue.Cast< _hx_T0 >();
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t0));
}
return inValue;
}
hx::Throw(HX_CSTRING("Missing field ") + inField);
return inValue;
}
void __Mark(hx::MarkContext *__inCtx)
{
HX_MARK_MEMBER(t0);
}
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *__inCtx)
{
HX_VISIT_MEMBER(t0);
}
#endif
void __GetFields(Array<String> &outFields)
{
outFields->push(name0);
}
String toString() { return StringFromAnonFields(this); }
};
template<typename _hx_T0, typename _hx_T1>
class AnonStruct2_obj : public hx::Object
{
public:
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdDynamic };
String name0; _hx_T0 t0;
String name1; _hx_T1 t1;
inline static hx::Object *Create(const String &inName0, _hx_T0 inT0,
const String &inName1, _hx_T1 inT1)
{
AnonStruct2_obj *result = new AnonStruct2_obj;
result->name0 = inName0; result->t0 = inT0;
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT0));
}
result->name1 = inName1; result->t1 = inT1;
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT1));
}
return result;
}
hx::Val __Field(const String &inField, hx::PropertyAccess)
{
if (inField.__s==name0.__s) return t0;
if (inField.__s==name1.__s) return t1;
#ifdef HX_SMART_STRINGS
if (!inField.isAsciiEncodedQ())
return null();
#endif
if (HX_QSTR_EQ_AE(inField,name0)) return t0;
if (HX_QSTR_EQ_AE(inField,name1)) return t1;
return null();
}
hx::Val __SetField(const String &inField,const hx::Val &inValue, hx::PropertyAccess inCallProp)
{
if (inField.__s==name0.__s) {
t0 = inValue.Cast< _hx_T0 >();
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t0));
}
return inValue;
}
if (inField.__s==name1.__s) {
t1 = inValue.Cast< _hx_T1 >();
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t1));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name0)) {
t0 = inValue.Cast< _hx_T0 >();
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t0));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name1)) {
t1 = inValue.Cast< _hx_T1 >();
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t1));
}
return inValue;
}
hx::Throw(HX_CSTRING("Missing field ") + inField);
return inValue;
}
void __Mark(hx::MarkContext *__inCtx)
{
HX_MARK_MEMBER(t0);
HX_MARK_MEMBER(t1);
}
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *__inCtx)
{
HX_VISIT_MEMBER(t0);
HX_VISIT_MEMBER(t1);
}
#endif
void __GetFields(Array<String> &outFields)
{
outFields->push(name0);
outFields->push(name1);
}
String toString() { return StringFromAnonFields(this); }
};
template<typename _hx_T0, typename _hx_T1, typename _hx_T2>
class AnonStruct3_obj : public hx::Object
{
public:
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdDynamic };
String name0; _hx_T0 t0;
String name1; _hx_T1 t1;
String name2; _hx_T2 t2;
inline static hx::Object *Create(const String &inName0, _hx_T0 inT0,
const String &inName1, _hx_T1 inT1,
const String &inName2, _hx_T2 inT2)
{
AnonStruct3_obj *result = new AnonStruct3_obj;
result->name0 = inName0; result->t0 = inT0;
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT0));
}
result->name1 = inName1; result->t1 = inT1;
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT1));
}
result->name2 = inName2; result->t2 = inT2;
if (hx::ContainsPointers<_hx_T2>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT2));
}
return result;
}
hx::Val __Field(const String &inField, hx::PropertyAccess)
{
if (inField.__s==name0.__s) return t0;
if (inField.__s==name1.__s) return t1;
if (inField.__s==name2.__s) return t2;
#ifdef HX_SMART_STRINGS
if (!inField.isAsciiEncodedQ())
return null();
#endif
if (HX_QSTR_EQ_AE(inField,name0)) return t0;
if (HX_QSTR_EQ_AE(inField,name1)) return t1;
if (HX_QSTR_EQ_AE(inField,name2)) return t2;
return null();
}
hx::Val __SetField(const String &inField,const hx::Val &inValue, hx::PropertyAccess inCallProp)
{
if (inField.__s==name0.__s) {
t0 = inValue.Cast< _hx_T0 >();
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t0));
}
return inValue;
}
if (inField.__s==name1.__s) {
t1 = inValue.Cast< _hx_T1 >();
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t1));
}
return inValue;
}
if (inField.__s==name2.__s) {
t2 = inValue.Cast< _hx_T2 >();
if (hx::ContainsPointers<_hx_T2>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t2));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name0)) {
t0 = inValue.Cast< _hx_T0 >();
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t0));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name1)) {
t1 = inValue.Cast< _hx_T1 >();
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t1));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name2)) {
t2 = inValue.Cast< _hx_T2 >();
if (hx::ContainsPointers<_hx_T2>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t2));
}
return inValue;
}
hx::Throw(HX_CSTRING("Missing field ") + inField);
return inValue;
}
void __Mark(hx::MarkContext *__inCtx)
{
HX_MARK_MEMBER(t0);
HX_MARK_MEMBER(t1);
HX_MARK_MEMBER(t2);
}
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *__inCtx)
{
HX_VISIT_MEMBER(t0);
HX_VISIT_MEMBER(t1);
HX_VISIT_MEMBER(t2);
}
#endif
void __GetFields(Array<String> &outFields)
{
outFields->push(name0);
outFields->push(name1);
outFields->push(name2);
}
String toString() { return StringFromAnonFields(this); }
};
template<typename _hx_T0, typename _hx_T1, typename _hx_T2, typename _hx_T3>
class AnonStruct4_obj : public hx::Object
{
public:
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdDynamic };
String name0; _hx_T0 t0;
String name1; _hx_T1 t1;
String name2; _hx_T2 t2;
String name3; _hx_T3 t3;
inline static hx::Object *Create(const String &inName0, _hx_T0 inT0,
const String &inName1, _hx_T1 inT1,
const String &inName2, _hx_T2 inT2,
const String &inName3, _hx_T3 inT3
)
{
AnonStruct4_obj *result = new AnonStruct4_obj;
result->name0 = inName0; result->t0 = inT0;
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT0));
}
result->name1 = inName1; result->t1 = inT1;
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT1));
}
result->name2 = inName2; result->t2 = inT2;
if (hx::ContainsPointers<_hx_T2>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT2));
}
result->name3 = inName3; result->t3 = inT3;
if (hx::ContainsPointers<_hx_T3>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT3));
}
return result;
}
hx::Val __Field(const String &inField, hx::PropertyAccess)
{
if (inField.__s==name0.__s) return t0;
if (inField.__s==name1.__s) return t1;
if (inField.__s==name2.__s) return t2;
if (inField.__s==name3.__s) return t3;
#ifdef HX_SMART_STRINGS
if (!inField.isAsciiEncodedQ())
return null();
#endif
if (HX_QSTR_EQ_AE(inField,name0)) return t0;
if (HX_QSTR_EQ_AE(inField,name1)) return t1;
if (HX_QSTR_EQ_AE(inField,name2)) return t2;
if (HX_QSTR_EQ_AE(inField,name3)) return t3;
return null();
}
hx::Val __SetField(const String &inField,const hx::Val &inValue, hx::PropertyAccess inCallProp)
{
if (inField.__s==name0.__s) {
t0 = inValue.Cast< _hx_T0 >();
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t0));
}
return inValue;
}
if (inField.__s==name1.__s) {
t1 = inValue.Cast< _hx_T1 >();
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t1));
}
return inValue;
}
if (inField.__s==name2.__s) {
t2 = inValue.Cast< _hx_T2 >();
if (hx::ContainsPointers<_hx_T2>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t2));
}
return inValue;
}
if (inField.__s==name3.__s) {
t3 = inValue.Cast< _hx_T3 >();
if (hx::ContainsPointers<_hx_T3>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t3));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name0)) {
t0 = inValue.Cast< _hx_T0 >();
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t0));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name1)) {
t1 = inValue.Cast< _hx_T1 >();
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t1));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name2)) {
t2 = inValue.Cast< _hx_T2 >();
if (hx::ContainsPointers<_hx_T2>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t2));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name3)) {
t3 = inValue.Cast< _hx_T3 >();
if (hx::ContainsPointers<_hx_T3>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t3));
}
return inValue;
}
hx::Throw(HX_CSTRING("Missing field ") + inField);
return inValue;
}
void __Mark(hx::MarkContext *__inCtx)
{
HX_MARK_MEMBER(t0);
HX_MARK_MEMBER(t1);
HX_MARK_MEMBER(t2);
HX_MARK_MEMBER(t3);
}
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *__inCtx)
{
HX_VISIT_MEMBER(t0);
HX_VISIT_MEMBER(t1);
HX_VISIT_MEMBER(t2);
HX_VISIT_MEMBER(t3);
}
#endif
void __GetFields(Array<String> &outFields)
{
outFields->push(name0);
outFields->push(name1);
outFields->push(name2);
outFields->push(name3);
}
String toString() { return StringFromAnonFields(this); }
};
template<typename _hx_T0, typename _hx_T1, typename _hx_T2, typename _hx_T3, typename _hx_T4>
class AnonStruct5_obj : public hx::Object
{
public:
HX_IS_INSTANCE_OF enum { _hx_ClassId = hx::clsIdDynamic };
String name0; _hx_T0 t0;
String name1; _hx_T1 t1;
String name2; _hx_T2 t2;
String name3; _hx_T3 t3;
String name4; _hx_T4 t4;
inline static hx::Object *Create(const String &inName0, _hx_T0 inT0,
const String &inName1, _hx_T1 inT1,
const String &inName2, _hx_T2 inT2,
const String &inName3, _hx_T3 inT3,
const String &inName4, _hx_T4 inT4
)
{
AnonStruct5_obj *result = new AnonStruct5_obj;
result->name0 = inName0; result->t0 = inT0;
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT0));
}
result->name1 = inName1; result->t1 = inT1;
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT1));
}
result->name2 = inName2; result->t2 = inT2;
if (hx::ContainsPointers<_hx_T2>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT2));
}
result->name3 = inName3; result->t3 = inT3;
if (hx::ContainsPointers<_hx_T3>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT3));
}
result->name4 = inName4; result->t4 = inT4;
if (hx::ContainsPointers<_hx_T4>()) {
HX_OBJ_WB_GET(result, hx::PointerOf(inT4));
}
return result;
}
hx::Val __Field(const String &inField, hx::PropertyAccess)
{
if (inField.__s==name0.__s) return t0;
if (inField.__s==name1.__s) return t1;
if (inField.__s==name2.__s) return t2;
if (inField.__s==name3.__s) return t3;
if (inField.__s==name4.__s) return t4;
#ifdef HX_SMART_STRINGS
if (!inField.isAsciiEncodedQ())
return null();
#endif
if (HX_QSTR_EQ_AE(inField,name0)) return t0;
if (HX_QSTR_EQ_AE(inField,name1)) return t1;
if (HX_QSTR_EQ_AE(inField,name2)) return t2;
if (HX_QSTR_EQ_AE(inField,name3)) return t3;
if (HX_QSTR_EQ_AE(inField,name4)) return t4;
return null();
}
hx::Val __SetField(const String &inField,const hx::Val &inValue, hx::PropertyAccess inCallProp)
{
if (inField.__s==name0.__s) {
t0 = inValue.Cast< _hx_T0 >();
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t0));
}
return inValue;
}
if (inField.__s==name1.__s) {
t1 = inValue.Cast< _hx_T1 >();
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t1));
}
return inValue;
}
if (inField.__s==name2.__s) {
t2 = inValue.Cast< _hx_T2 >();
if (hx::ContainsPointers<_hx_T2>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t2));
}
return inValue;
}
if (inField.__s==name3.__s) {
t3 = inValue.Cast< _hx_T3 >();
if (hx::ContainsPointers<_hx_T3>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t3));
}
return inValue;
}
if (inField.__s==name4.__s) {
t4 = inValue.Cast< _hx_T4 >();
if (hx::ContainsPointers<_hx_T4>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t4));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name0)) {
t0 = inValue.Cast< _hx_T0 >();
if (hx::ContainsPointers<_hx_T0>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t0));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name1)) {
t1 = inValue.Cast< _hx_T1 >();
if (hx::ContainsPointers<_hx_T1>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t1));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name2)) {
t2 = inValue.Cast< _hx_T2 >();
if (hx::ContainsPointers<_hx_T2>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t2));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name3)) {
t3 = inValue.Cast< _hx_T3 >();
if (hx::ContainsPointers<_hx_T3>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t3));
}
return inValue;
}
if (HX_QSTR_EQ(inField,name4)) {
t4 = inValue.Cast< _hx_T4 >();
if (hx::ContainsPointers<_hx_T4>()) {
HX_OBJ_WB_GET(this, hx::PointerOf(t4));
}
return inValue;
}
hx::Throw(HX_CSTRING("Missing field ") + inField);
return inValue;
}
void __Mark(hx::MarkContext *__inCtx)
{
HX_MARK_MEMBER(t0);
HX_MARK_MEMBER(t1);
HX_MARK_MEMBER(t2);
HX_MARK_MEMBER(t3);
HX_MARK_MEMBER(t4);
}
#ifdef HXCPP_VISIT_ALLOCS
void __Visit(hx::VisitContext *__inCtx)
{
HX_VISIT_MEMBER(t0);
HX_VISIT_MEMBER(t1);
HX_VISIT_MEMBER(t2);
HX_VISIT_MEMBER(t3);
HX_VISIT_MEMBER(t4);
}
#endif
void __GetFields(Array<String> &outFields)
{
outFields->push(name0);
outFields->push(name1);
outFields->push(name2);
outFields->push(name3);
outFields->push(name4);
}
String toString() { return StringFromAnonFields(this); }
};
} // end namespace hx
HXCPP_EXTERN_CLASS_ATTRIBUTES
bool __hxcpp_anon_remove(Dynamic inObj,::String inKey);
#endif

View File

@ -0,0 +1,15 @@
#ifndef HX_BOOT_H
#define HX_BOOT_H
// Properly construct all the classes defined in the haxe code
void __boot_all();
namespace hx
{
// Initializer the hxcpp runtime system
HXCPP_EXTERN_CLASS_ATTRIBUTES void Boot();
}
#endif

View File

@ -0,0 +1,469 @@
#ifndef HX_CFFI_H
#define HX_CFFI_H
// 410 - adds gc_try_unblocking
#define HX_CFFI_API_VERSION 410
#ifdef HXCPP_JS_PRIME
#include <emscripten/bind.h>
using namespace emscripten;
typedef struct emscripten::val value;
typedef struct _vkind *vkind;
typedef struct _buffer *buffer;
#define HAVE_NEKO_TYPES 1
#endif
#include "OS.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(BLACKBERRY)
using namespace std;
#endif
// --- Register functions (primitives) ----
#ifdef STATIC_LINK
#define DEFINE_PRIM_MULT(func) \
int __reg_##func = hx_register_prim(#func "__MULT",(void *)(&func)); \
#define DEFINE_PRIM(func,nargs) \
int __reg_##func = hx_register_prim(#func "__" #nargs,(void *)(&func)); \
#define DEFINE_PRIM_MULT_NATIVE(func,ext) \
int __reg_##func = hx_register_prim(#func "__MULT",(void *)(&func)) + \
hx_register_prim(#func "__" #ext,(void *)(&func##_##ext)) ;
#define DEFINE_PRIM_NATIVE(func,nargs,ext) \
int __reg_##func = hx_register_prim(#func "__" #nargs,(void *)(&func)) + \
hx_register_prim(#func "__" #ext,(void *)(&func##_##ext)) ;
#define DEFINE_LIB_PRIM_MULT(lib,func) \
int __reg_##func = hx_register_prim(lib "_" #func "__MULT",(void *)(&func)); \
#define DEFINE_LIB_PRIM(lib,func,nargs) \
int __reg_##func = hx_register_prim(lib "_" #func "__" #nargs,(void *)(&func)); \
#elif defined(HXCPP_JS_PRIME)
//#define DEFINE_PRIM_MULT(func) EMSCRIPTEN_BINDINGS(func) { function(#func, &func); }
//TODO
#define DEFINE_PRIM_MULT(func)
#define DEFINE_PRIM(func,nargs) EMSCRIPTEN_BINDINGS(func) { function(#func, &func); }
#else
#define DEFINE_PRIM_MULT(func) extern "C" { \
EXPORT void *func##__MULT() { return (void*)(&func); } \
}
#define DEFINE_PRIM(func,nargs) extern "C" { \
EXPORT void *func##__##nargs() { return (void*)(&func); } \
}
#define DEFINE_PRIM_MULT_NATIVE(func,ext) extern "C" { \
EXPORT void *func##__MULT() { return (void*)(&func); } \
EXPORT void *func##__##ext() { return (void*)(&func##_##ext); } \
}
#define DEFINE_PRIM_NATIVE(func,nargs,ext) extern "C" { \
EXPORT void *func##__##nargs() { return (void*)(&func); } \
EXPORT void *func##__##ext() { return (void*)(&func##_##ext); } \
}
#define DEFINE_LIB_PRIM_MULT(lib,func) extern "C" { \
EXPORT void *func##__MULT() { return (void*)(&func); } \
}
#define DEFINE_LIB_PRIM(lib,func,nargs) extern "C" { \
EXPORT void *func##__##nargs() { return (void*)(&func); } \
}
#endif // !STATIC_LINK
#define DEFFUNC_0(ret,name) DEFFUNC(name,ret, (), ())
#define DEFFUNC_1(ret,name,t1) DEFFUNC(name,ret, (t1 a1), (a1))
#define DEFFUNC_2(ret,name,t1,t2) DEFFUNC(name,ret, (t1 a1, t2 a2), (a1,a2))
#define DEFFUNC_3(ret,name,t1,t2,t3) DEFFUNC(name,ret, (t1 a1, t2 a2, t3 a3), (a1,a2,a3))
#define DEFFUNC_4(ret,name,t1,t2,t3,t4) DEFFUNC(name,ret, (t1 a1, t2 a2, t3 a3, t4 a4), (a1,a2,a3,a4))
#define DEFFUNC_5(ret,name,t1,t2,t3,t4,t5) DEFFUNC(name,ret, (t1 a1, t2 a2, t3 a3, t4 a4,t5 a5), (a1,a2,a3,a4,a5))
enum hxValueType
{
valtUnknown = -1,
valtInt = 0xff,
valtNull = 0,
valtFloat = 1,
valtBool = 2,
valtString = 3,
valtObject = 4,
valtArray = 5,
valtFunction = 6,
valtEnum,
valtClass,
valtRoot = 0xff,
valtAbstractBase = 0x100,
};
namespace hx
{
enum StringEncoding
{
StringAscii,
StringUtf8,
StringUtf16
};
}
// val_fun_nargs may return a special value
enum { faNotFunction = -2, faVarArgs=-1, faArgs0=0 /* ... */ };
typedef int field;
#ifdef IMPLEMENT_API
#include "CFFILoader.h"
#endif
#if !defined(HAVE_NEKO_TYPES)
#ifdef HXCPP_NATIVE_CFFI_VALUE
namespace hx { class Object; }
typedef hx::Object _value;
#else
struct _value;
#endif
typedef _value *value;
typedef struct _vkind *vkind;
typedef struct _buffer *buffer;
#endif
typedef buffer cffiByteBuffer;
typedef struct _gcroot *gcroot;
typedef void (*hxFinalizer)(value v);
typedef void (*hxPtrFinalizer)(void *v);
typedef void (__hx_field_iter)(value v,field f,void *);
#define hx_failure(msg) hx_fail(msg,__FILE__,__LINE__)
#ifndef IGNORE_CFFI_API_H
#ifndef IMPLEMENT_API
#if defined(STATIC_LINK) || defined(HXCPP_JS_PRIME)
#define DEFFUNC(name,ret,def_args,call_args) \
extern "C" ret name def_args;
#else
#define DEFFUNC(name,ret,def_args,call_args) \
typedef ret (*FUNC_##name) def_args; \
extern FUNC_##name name;
#endif
#endif
#include "CFFIAPI.h"
#ifdef WANT_DYNALLOC_ALLOC_BYTES
void *DynAlloc::allocBytes(size_t n)
{
return hx_alloc((int)n);
}
#endif
#define DEFINE_KIND(name) extern "C" { vkind name = 0; }
#ifdef STATIC_LINK
# define DEFINE_ENTRY_POINT(name)
#else
# define DEFINE_ENTRY_POINT(name) extern "C" { void name(); EXPORT void *__neko_entry_point() { return (void *)&name; } }
#endif
#ifdef HEADER_IMPORTS
# define H_EXTERN IMPORT
#else
# define H_EXTERN EXPORT
#endif
#define DECLARE_PRIM(func,nargs) extern "C" { H_EXTERN void *func##__##nargs(); }
#define DECLARE_KIND(name) extern "C" { H_EXTERN extern vkind name; }
// --- Helpers ----------------------------------------------------------------
// Check type...
inline bool val_is_null(value inVal) { return val_type(inVal)==valtNull; }
inline bool val_is_int(value inVal) { return val_type(inVal)==valtInt; }
inline bool val_is_bool(value inVal) { return val_type(inVal)==valtBool; }
inline bool val_is_float(value inVal) { return val_type(inVal)==valtFloat; }
inline bool val_is_string(value inVal) { return val_type(inVal)==valtString; }
inline bool val_is_function(value inVal) { return val_type(inVal)==valtFunction; }
inline bool val_is_array(value inVal) { return val_type(inVal)==valtArray; }
inline bool val_is_abstract(value inVal) { return val_type(inVal)>=valtAbstractBase; }
inline bool val_is_kind(value inVal,vkind inKind) { return val_to_kind(inVal,inKind)!=0; }
inline bool val_is_number(value inVal)
{
int t = val_type(inVal);
return t==valtInt || t==valtFloat;
}
inline bool val_is_object(value inVal)
{
int t = val_type(inVal);
return t==valtObject || t==valtEnum ||t==valtClass;
}
class AutoGCBlocking
{
public:
inline AutoGCBlocking(bool inSoftUnlock=false) :
mSoftUnlock(inSoftUnlock), mLocked( gc_try_blocking() ) { }
inline ~AutoGCBlocking() { Close(); }
inline void Close()
{
if (mLocked)
{
if (mSoftUnlock)
gc_try_unblocking();
else
gc_exit_blocking();
}
mLocked = false;
}
bool mLocked;
bool mSoftUnlock;
};
class AutoGCUnblocking
{
public:
AutoGCUnblocking() : mUnlocked( gc_try_unblocking() ) { }
~AutoGCUnblocking() { Close(); }
void Close() { if (mUnlocked) gc_enter_blocking(); mUnlocked = false; }
bool mUnlocked;
};
class AutoGCRoot
{
public:
AutoGCRoot(value inValue)
{
mRoot = 0;
mPtr = alloc_root();
if (mPtr)
*mPtr = inValue;
else
mRoot = create_root(inValue);
}
~AutoGCRoot()
{
if (mPtr)
free_root(mPtr);
else if (mRoot)
destroy_root(mRoot);
}
value get()const { return mPtr ? *mPtr : query_root(mRoot); }
void set(value inValue)
{
if (mPtr)
*mPtr = inValue;
else
{
if (mRoot) destroy_root(mRoot);
mRoot = create_root(inValue);
}
}
private:
value *mPtr;
gcroot mRoot;
AutoGCRoot(const AutoGCRoot &);
void operator=(const AutoGCRoot &);
};
struct CffiBytes
{
CffiBytes( unsigned char *inData=0, int inLength=0) : data(inData), length(inLength) {}
unsigned char *data;
int length;
};
inline CffiBytes getByteData(value inValue)
{
static field bField = 0;
static field lengthField = 0;
if (bField==0)
{
bField = val_id("b");
lengthField = val_id("length");
}
if (val_is_object(inValue))
{
value b = val_field(inValue, bField);
value len = val_field(inValue, lengthField);
if (val_is_string(b) && val_is_int(len))
return CffiBytes( (unsigned char *)val_string(b), val_int(len) );
if (val_is_buffer(b) && val_is_int(len))
return CffiBytes( (unsigned char *)buffer_data(val_to_buffer(b)), val_int(len) );
}
else if (val_is_buffer(inValue))
{
value len = val_field(inValue, lengthField);
if (val_is_int(len))
{
buffer b = val_to_buffer(inValue);
return CffiBytes( (unsigned char *)buffer_data(b), val_int(len) );
}
}
return CffiBytes();
}
inline bool resizeByteData(value inValue, int inNewLen)
{
if (!val_is_object(inValue))
return false;
static field bField = 0;
static field lengthField = 0;
if (bField==0)
{
bField = val_id("b");
lengthField = val_id("length");
}
value len = val_field(inValue, lengthField);
if (!val_is_int(len))
return false;
int oldLen = val_int(len);
value b = val_field(inValue, bField);
if (val_is_string(b))
{
if (inNewLen>oldLen)
{
value newString = alloc_raw_string(inNewLen);
memcpy( (char *)val_string(newString), val_string(b), inNewLen);
alloc_field(inValue, bField, newString );
}
alloc_field(inValue, lengthField, alloc_int(inNewLen) );
}
else if (val_is_buffer(b))
{
cffiByteBuffer buf = val_to_buffer(b);
buffer_set_size(buf,inNewLen);
alloc_field(inValue, lengthField, alloc_int(inNewLen) );
}
else
return false;
return true;
}
#define val_null alloc_null()
#define bfailure(x) val_throw(buffer_to_string(x))
#define copy_string(str,len) alloc_string_len(str,len)
// The "Check" macros throw an error if assumtion is false
#define val_check_kind(v,t) if( !val_is_kind(v,t) ) hx_failure("invalid kind");
#define val_check_function(f,n) if( !val_is_function(f) || (val_fun_nargs(f) != (n) && val_fun_nargs(f) != faVarArgs) ) hx_failure("Bad function");
#define val_check(v,t) if( !val_is_##t(v) ) hx_failure("type not " #t);
// The "Get" function will return or force an error
inline bool val_get_bool(value inVal) { val_check(inVal,bool); return val_bool(inVal); }
inline int val_get_int(value inVal) { val_check(inVal,int); return val_int(inVal); }
inline double val_get_double(value inVal) { val_check(inVal,number); return val_number(inVal); }
inline const char *val_get_string(value inVal) { val_check(inVal,string); return val_string(inVal); }
inline void *val_get_handle(value inVal,vkind inKind)
{ val_check_kind(inVal,inKind); return val_to_kind(inVal,inKind); }
inline value alloc_string(const char *inStr)
{
const char *end = inStr;
while(*end) end++;
return alloc_string_len(inStr,(int)(end-inStr));
}
inline value alloc_wstring(const wchar_t *inStr)
{
const wchar_t *end = inStr;
while(*end) end++;
return alloc_wstring_len(inStr,(int)(end-inStr));
}
inline void hxcpp_unscramble(const unsigned char *bytes, int len, const char *key, unsigned char *dest)
{
int keyLen = 0;
while(key[keyLen])
keyLen++;
int state = 0;
//state = ((state + key[i]) ^ ch) & 0xff);
for(int i=0;i<len;i++)
{
dest[i] = ( (state + key[i%keyLen]) ^ bytes[i] ) & 0xff;
state = bytes[i];
}
}
//additional glue for easier neko modules compilation
#define val_true alloc_bool(true)
#define val_false alloc_bool(false)
inline void neko_error() { hx_error(); }
// Conservative marking within a buffer is not yet supported.
//inline void * alloc(int i) { return hx_alloc(i); }
// The bytes themselves will be GC'd, but not the pointers contained within.
inline void * alloc_private(int i) { return hx_alloc(i); }
// You should use alloc_buffer_len/buffer_data instead
//value alloc_empty_string(int len) { }
#endif
#endif

View File

@ -0,0 +1,189 @@
/*
This bit of Macro magic is used to define extern function pointers
in ndlls, define stub implementations that link back to the hxcpp dll
and glue up the implementation in the hxcpp runtime.
*/
DEFFUNC_1(void,val_throw,value)
DEFFUNC_0(void,hx_error)
DEFFUNC_3(void,hx_fail,const char *,const char *,int)
// Determine value type
DEFFUNC_1(int,val_type,value)
DEFFUNC_1(vkind,val_kind,value)
DEFFUNC_2(void *,val_to_kind,value,vkind)
// don't check the 'kind' ...
DEFFUNC_1(void *,val_data,value)
DEFFUNC_1(int,val_fun_nargs,value)
// Extract value type
DEFFUNC_1(bool,val_bool,value)
DEFFUNC_1(int,val_int,value)
DEFFUNC_1(double,val_float,value)
DEFFUNC_1(double,val_number,value)
// Create value type
DEFFUNC_0(value,alloc_null)
DEFFUNC_1(value,alloc_bool,bool)
DEFFUNC_1(value,alloc_int,int)
DEFFUNC_1(value,alloc_float,double)
DEFFUNC_0(value,alloc_empty_object)
DEFFUNC_2(value,alloc_abstract,vkind,void *)
// Allocates conservative-collected memory
DEFFUNC_3(value,create_abstract,vkind,int,hxFinalizer)
DEFFUNC_1(void,free_abstract,value)
DEFFUNC_1(value,alloc_best_int,int)
DEFFUNC_1(value,alloc_int32,int)
// String access
DEFFUNC_1(int,val_strlen,value)
DEFFUNC_2(value,alloc_string_len,const char *,int)
DEFFUNC_2(value,alloc_wstring_len,const wchar_t *,int)
DEFFUNC_1(const wchar_t *,val_wstring,value)
DEFFUNC_1(const char *,val_string,value)
DEFFUNC_1(wchar_t *,val_dup_wstring,value)
DEFFUNC_1(char *,val_dup_string,value)
DEFFUNC_2(char *,alloc_string_data,const char *,int)
#ifdef HXCPP_PRIME
/*DEFFUNC_2(HxString,alloc_hxs_wchar,const wchar_t *,int)
DEFFUNC_2(HxString,alloc_hxs_utf16,const char16_t *,int)
DEFFUNC_2(HxString,alloc_hxs_utf8,const char *,int)*/
DEFFUNC_2(const char *,hxs_utf8,const HxString &,hx::IStringAlloc *)
DEFFUNC_2(const wchar_t *,hxs_wchar,const HxString &,hx::IStringAlloc *)
DEFFUNC_2(const char16_t *,hxs_utf16,const HxString &,hx::IStringAlloc *)
DEFFUNC_1(hx::StringEncoding,hxs_encoding,const HxString &)
#endif
// Array access - generic
DEFFUNC_1(value,alloc_array,int)
DEFFUNC_1(int,val_array_size,value)
DEFFUNC_2(void,val_array_set_size,value,int)
DEFFUNC_2(value,val_array_i,value,int)
DEFFUNC_3(void,val_array_set_i,value,int,value)
DEFFUNC_2(void,val_array_push,value,value)
// Array access - fast if possible - may return null
// Resizing the array may invalidate the pointer
DEFFUNC_1(bool *,val_array_bool,value)
DEFFUNC_1(int *,val_array_int,value)
DEFFUNC_1(double *,val_array_double,value)
DEFFUNC_1(float *,val_array_float,value)
DEFFUNC_1(value *,val_array_value,value)
// String Buffer
// A 'buffer' is a tool for joining strings together.
// The C++ implementation is haxe.io.BytesData
// The neko implementation is something else again, and can't be passes as a value, only copied to a string
// Create a buffer from string of an empty buffer of a given length
DEFFUNC_1(buffer,alloc_buffer,const char *)
DEFFUNC_1(buffer,alloc_buffer_len,int)
// Append a string representation of a value to the buffer
DEFFUNC_2(void,val_buffer,buffer,value)
// Append a c-string to a buffer
DEFFUNC_2(void,buffer_append,buffer,const char *)
// Append given number of bytes of a c-string to the buffer
DEFFUNC_3(void,buffer_append_sub,buffer,const char *,int)
// Append given character to string
DEFFUNC_2(void,buffer_append_char,buffer,int)
// Convert buffer back into string value
DEFFUNC_1(value,buffer_to_string,buffer)
// These routines are for direct access to the c++ BytesData structure
// Use getByteData and resizeByteData for more generic access to haxe.io.Bytes
// This will never return true on a neko host.
DEFFUNC_1(bool,val_is_buffer,value)
// These functions are only valid if val_is_buffer returns true
// Currently, cffiByteBuffer is the same struct as buffer, but the usage is quite different
DEFFUNC_1(cffiByteBuffer,val_to_buffer,value)
// Number of byes in the array
DEFFUNC_1(int,buffer_size,cffiByteBuffer)
// Pointer to the byte data - will become invalid if the array is resized
DEFFUNC_1(char *,buffer_data,cffiByteBuffer)
// Convert c++ ByteBuffer back to 'value' - no copy involved
DEFFUNC_1(value,buffer_val,cffiByteBuffer)
// Resize the array - will invalidate the data
DEFFUNC_2(void,buffer_set_size,cffiByteBuffer,int)
// This is used by resizeByteData for manipulating bytes directly on neko
DEFFUNC_1(value,alloc_raw_string,int)
// Call Function
DEFFUNC_1(value,val_call0,value)
DEFFUNC_2(value,val_call1,value,value)
DEFFUNC_3(value,val_call2,value,value,value)
DEFFUNC_4(value,val_call3,value,value,value,value)
DEFFUNC_3(value,val_callN,value,value *,int)
// Call the function - catch and print any exceptions
DEFFUNC_1(value,val_call0_traceexcept,value)
// Call object field
DEFFUNC_2(value,val_ocall0,value,int)
DEFFUNC_3(value,val_ocall1,value,int,value)
DEFFUNC_4(value,val_ocall2,value,int,value,value)
DEFFUNC_4(value,val_ocallN,value,int,value *,int)
// Objects access
DEFFUNC_1(int,val_id,const char *)
DEFFUNC_3(void,alloc_field,value,int,value)
DEFFUNC_3(void,alloc_field_numeric,value,int,double)
DEFFUNC_2(value,val_field,value,int)
DEFFUNC_2(double,val_field_numeric,value,int)
DEFFUNC_1(value,val_field_name,field)
DEFFUNC_3(void,val_iter_fields,value,__hx_field_iter,void *)
DEFFUNC_3(void,val_iter_field_vals,value,__hx_field_iter,void *)
// Abstract types
DEFFUNC_0(vkind,alloc_kind)
DEFFUNC_2(void,kind_share,vkind *,const char *)
// Garbage Collection
DEFFUNC_1(void *,hx_alloc,int)
DEFFUNC_2(void, val_gc,value,hxFinalizer)
DEFFUNC_2(void, val_gc_ptr,void *,hxPtrFinalizer)
DEFFUNC_0(value *, alloc_root)
DEFFUNC_1(void, free_root,value *)
DEFFUNC_2(void, gc_change_managed_memory,int,const char *)
// Only available on cpp target...
DEFFUNC_1(void, val_gc_add_root,value *)
DEFFUNC_1(void, val_gc_remove_root,value *)
// Only available on js target - use AutoGCRoot to assist
DEFFUNC_1(gcroot, create_root,value)
DEFFUNC_1(value, query_root,gcroot)
DEFFUNC_1(void, destroy_root,gcroot)
DEFFUNC_0(void, gc_enter_blocking)
DEFFUNC_0(void, gc_exit_blocking)
DEFFUNC_0(bool, gc_try_blocking)
DEFFUNC_0(void, gc_safe_point)
DEFFUNC_2(void, gc_set_top_of_stack,int *,bool)
DEFFUNC_0(bool, gc_try_unblocking)
// Used for finding functions in static libraries
DEFFUNC_2(int, hx_register_prim, const char *, void*)

View File

@ -0,0 +1,202 @@
extern "C"
{
typedef std::map<std::string,int> IdMap;
static IdMap sIdMap;
static std::vector<val> sIdKeys;
int val_id(const char *inName)
{
IdMap::iterator id = sIdMap.find(inName);
if (id==sIdMap.end())
{
int result = sIdMap.size();
sIdMap[inName] = result;
sIdKeys.push_back(value(inName));
return result;
}
return id->second;
}
double val_field_numeric(value inObject, int inFieldId)
{
return inObject[sIdKeys[inFieldId]].as<double>();
}
int val_int(value inValue) { return inValue.as<int>(); }
bool val_bool(value inValue) { return inValue.as<bool>(); }
double val_number(value inValue) { return inValue.as<double>(); }
double val_float(value inValue) { return inValue.as<double>(); }
value alloc_null() { return emscripten::val::null(); }
value alloc_int(int inValue) { return value(inValue); }
value alloc_best_int(int inValue) { return value(inValue); }
value alloc_int32(int inValue) { return value(inValue); }
value alloc_bool(bool inValue) { return value(inValue); }
value alloc_float(double inValue) { return value(inValue); }
value val_field(value inObject, int inIndex) { return inObject[sIdKeys[inIndex]]; }
void alloc_field(value inObject, int inIndex, value inValue) { inObject.set(sIdKeys[inIndex],inValue); }
/*
DEFFUNC_1(void,val_throw,value)
DEFFUNC_0(void,hx_error)
DEFFUNC_3(void,hx_fail,const char *,const char *,int)
// Determine value type
DEFFUNC_1(int,val_type,value)
DEFFUNC_1(vkind,val_kind,value)
DEFFUNC_2(void *,val_to_kind,value,vkind)
// don't check the 'kind' ...
DEFFUNC_1(void *,val_data,value)
DEFFUNC_1(int,val_fun_nargs,value)
// Create value type
DEFFUNC_0(value,alloc_empty_object)
DEFFUNC_2(value,alloc_abstract,vkind,void *)
// Allocates conservative-collected memory
DEFFUNC_3(value,create_abstract,vkind,int,hxFinalizer)
DEFFUNC_1(void,free_abstract,value)
// String access
DEFFUNC_1(int,val_strlen,value)
DEFFUNC_1(const wchar_t *,val_wstring,value)
DEFFUNC_1(const char *,val_string,value)
DEFFUNC_1(wchar_t *,val_dup_wstring,value)
DEFFUNC_1(char *,val_dup_string,value)
DEFFUNC_2(char *,alloc_string_data,const char *,int)
DEFFUNC_2(value,alloc_string_len,const char *,int)
DEFFUNC_2(value,alloc_wstring_len,const wchar_t *,int)
// Array access - generic
DEFFUNC_1(value,alloc_array,int)
DEFFUNC_1(int,val_array_size,value)
DEFFUNC_2(void,val_array_set_size,value,int)
DEFFUNC_2(value,val_array_i,value,int)
DEFFUNC_3(void,val_array_set_i,value,int,value)
DEFFUNC_2(void,val_array_push,value,value)
// Array access - fast if possible - may return null
// Resizing the array may invalidate the pointer
DEFFUNC_1(bool *,val_array_bool,value)
DEFFUNC_1(int *,val_array_int,value)
DEFFUNC_1(double *,val_array_double,value)
DEFFUNC_1(float *,val_array_float,value)
DEFFUNC_1(value *,val_array_value,value)
// String Buffer
// A 'buffer' is a tool for joining strings together.
// The C++ implementation is haxe.io.BytesData
// The neko implementation is something else again, and can't be passes as a value, only copied to a string
// Create a buffer from string of an empty buffer of a given length
DEFFUNC_1(buffer,alloc_buffer,const char *)
DEFFUNC_1(buffer,alloc_buffer_len,int)
// Append a string representation of a value to the buffer
DEFFUNC_2(void,val_buffer,buffer,value)
// Append a c-string to a buffer
DEFFUNC_2(void,buffer_append,buffer,const char *)
// Append given number of bytes of a c-string to the buffer
DEFFUNC_3(void,buffer_append_sub,buffer,const char *,int)
// Append given character to string
DEFFUNC_2(void,buffer_append_char,buffer,int)
// Convert buffer back into string value
DEFFUNC_1(value,buffer_to_string,buffer)
// These routines are for direct access to the c++ BytesData structure
// Use getByteData and resizeByteData for more generic access to haxe.io.Bytes
// This will never return true on a neko host.
DEFFUNC_1(bool,val_is_buffer,value)
// These functions are only valid if val_is_buffer returns true
// Currently, cffiByteBuffer is the same struct as buffer, but the usage is quite different
DEFFUNC_1(cffiByteBuffer,val_to_buffer,value)
// Number of byes in the array
DEFFUNC_1(int,buffer_size,cffiByteBuffer)
// Pointer to the byte data - will become invalid if the array is resized
DEFFUNC_1(char *,buffer_data,cffiByteBuffer)
// Convert c++ ByteBuffer back to 'value' - no copy involved
DEFFUNC_1(value,buffer_val,cffiByteBuffer)
// Resize the array - will invalidate the data
DEFFUNC_2(void,buffer_set_size,cffiByteBuffer,int)
// This is used by resizeByteData for manipulating bytes directly on neko
DEFFUNC_1(value,alloc_raw_string,int)
// Call Function
DEFFUNC_1(value,val_call0,value)
DEFFUNC_2(value,val_call1,value,value)
DEFFUNC_3(value,val_call2,value,value,value)
DEFFUNC_4(value,val_call3,value,value,value,value)
DEFFUNC_3(value,val_callN,value,value *,int)
// Call the function - catch and print any exceptions
DEFFUNC_1(value,val_call0_traceexcept,value)
// Call object field
DEFFUNC_2(value,val_ocall0,value,int)
DEFFUNC_3(value,val_ocall1,value,int,value)
DEFFUNC_4(value,val_ocall2,value,int,value,value)
DEFFUNC_4(value,val_ocallN,value,int,value *,int)
// Objects access
DEFFUNC_1(int,val_id,const char *)
DEFFUNC_3(void,alloc_field,value,int,value)
DEFFUNC_2(value,val_field,value,int)
DEFFUNC_2(double,val_field_numeric,value,int)
DEFFUNC_1(value,val_field_name,field)
DEFFUNC_3(void,val_iter_fields,value,__hx_field_iter,void *)
DEFFUNC_3(void,val_iter_field_vals,value,__hx_field_iter,void *)
// Abstract types
DEFFUNC_0(vkind,alloc_kind)
DEFFUNC_2(void,kind_share,vkind *,const char *)
// Garbage Collection
DEFFUNC_1(void *,hx_alloc,int)
DEFFUNC_2(void, val_gc,value,hxFinalizer)
DEFFUNC_2(void, val_gc_ptr,void *,hxPtrFinalizer)
DEFFUNC_0(value *, alloc_root)
DEFFUNC_1(void, free_root,value *)
DEFFUNC_2(void, gc_change_managed_memory,int,const char *)
// Only available on cpp target...
DEFFUNC_1(void, val_gc_add_root,value *)
DEFFUNC_1(void, val_gc_remove_root,value *)
// Only available on js target - use AutoGCRoot to assist
DEFFUNC_1(gcroot, create_root,value)
DEFFUNC_1(value, query_root,gcroot)
DEFFUNC_1(void, destroy_root,gcroot)
DEFFUNC_0(void, gc_enter_blocking)
DEFFUNC_0(void, gc_exit_blocking)
DEFFUNC_0(void, gc_safe_point)
DEFFUNC_2(void, gc_set_top_of_stack,int *,bool)
// Used for finding functions in static libraries
DEFFUNC_2(int, hx_register_prim, const char *, void*)
*/
}

View File

@ -0,0 +1,330 @@
#ifndef HX_CFFI_LOADER_H
#define HX_CFFI_LOADER_H
/*
This file will only be incuded in one cpp file in the ndll library -
the one with IMPLEMENT_API #defined.
The other files will refer to the val_ functions via the "extern" in CFFI.h
For dynamic linking, a macro (DEFFUNC) implements the "val_..." functions as function pointers,
and the cpp code calls these function pointers directly.
The pointers starts off as function pointers to bootstrap code, so when they are first called
the bootstrap uses the "ResolveProc" to find the correct version of the function for the particular
platform, and replaces the function pointer with this value. Subsequent calls then go directly
to the correct fucntion.
The ResolveProc can come from:
Explicitly setting - the proc is set when a dll is loaded into the hxcpp exe
Via 'GetProcAddress' on the exe - if symbols are needed and the proc has not been set
Internal implementation (CFFINekoLoader) - when linking agaist a neko process.
- Old code used to find this in NekoApi.dll, but the glue code is now built into each ndll directly.
For static linking, the functions are resolved at link time.
For HXCPP_JS_PRIME, these functions are implemented in CFFIJsPrime
*/
#ifdef ANDROID
#include <android/log.h>
#endif
#ifdef NEKO_WINDOWS
#include <windows.h>
#include <stdio.h>
// Stoopid windows ...
#ifdef RegisterClass
#undef RegisterClass
#endif
#ifdef abs
#undef abs
#endif
#else // NOT NEKO_WINDOWS
#ifdef NEKO_LINUX
#define EXT "dso"
#define NEKO_EXT "so"
//#define __USE_GNU 1
#elif defined(HX_MACOS)
#include <mach-o/dyld.h>
#define EXT "dylib"
#define NEKO_EXT "dylib"
#else
#if defined(EMSCRIPTEN)
#define EXT "ll"
#else
#define EXT "so"
#endif
#endif
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#endif
#if defined(BLACKBERRY)
using namespace std;
#endif
typedef void *(*ResolveProc)(const char *inName);
static ResolveProc sResolveProc = 0;
extern "C" {
EXPORT void hx_set_loader(ResolveProc inProc)
{
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "haxe plugin", "Got Load Proc %p", inProc );
#endif
sResolveProc = inProc;
}
}
#ifdef HXCPP_JS_PRIME // { js prime
#define DEFFUNC(name,ret,def_args,call_args) \
extern "C" ret name def_args;
#include "CFFIJsPrime.h"
#elif defined(STATIC_LINK) // js prime } { not js prime, static link
#define DEFFUNC(name,ret,def_args,call_args) \
extern "C" ret name def_args;
#else // static link } { Dynamic link
#ifdef NEKO_COMPATIBLE
#include "CFFINekoLoader.h"
#endif // NEKO_COMPATIBLE
// This code will get run when the library is compiled against a newer version of hxcpp,
// and the application code uses an older version.
bool default_val_is_buffer(void *inBuffer)
{
typedef void *(ValToBufferFunc)(void *);
static ValToBufferFunc *valToBuffer = 0;
if (!valToBuffer)
valToBuffer = (ValToBufferFunc *)sResolveProc("val_to_buffer");
if (valToBuffer)
return valToBuffer(inBuffer)!=0;
return false;
}
// Neko, old cpp and js_prime are all utf8 based - and go through here
#ifdef HXCPP_PRIME
struct DynAlloc : public hx::IStringAlloc
{
#define WANT_DYNALLOC_ALLOC_BYTES
void *allocBytes(size_t n);
};
HxString default_string_wchar(const wchar_t *src,int len)
{
hx::strbuf buf;
const char *str = cffi::to_utf8(src,len,&buf);
return HxString(str,len);
}
HxString default_string_utf8(const char *str,int len)
{
return HxString(str,len);
}
HxString default_string_utf16(const char16_t *src,int len)
{
hx::strbuf buf;
const char *str = cffi::to_utf8(src,len,&buf);
return HxString(str,len);
}
const char *default_to_utf8(const HxString &str,hx::IStringAlloc *alloc)
{
return str.c_str();
}
const wchar_t *default_to_wchar(const HxString &str,hx::IStringAlloc *alloc)
{
DynAlloc d;
if (!alloc)
alloc = &d;
return cffi::from_utf8<wchar_t>(str.c_str(),str.size(),alloc);
}
const char16_t *default_to_utf16(const HxString &str,hx::IStringAlloc *alloc)
{
DynAlloc d;
if (!alloc)
alloc = &d;
return cffi::from_utf8<char16_t>(str.c_str(),str.size(),alloc);
}
#endif
hx::StringEncoding default_get_encoding(void *inPtr) { return hx::StringUtf8; }
void * default_alloc_empty_string(int) { return 0; }
// Do nothing on earlier versions of hxcpp that do not know what to do
void default_gc_change_managed_memory(int,const char *) { }
void *ResolveDefault(const char *inName)
{
void *result = sResolveProc(inName);
if (result)
return result;
if (!strcmp(inName,"val_is_buffer"))
return (void *)default_val_is_buffer;
if (!strcmp(inName,"alloc_empty_string"))
return (void *)default_alloc_empty_string;
if (!strcmp(inName,"gc_change_managed_memory"))
return (void *)default_gc_change_managed_memory;
if (!strcmp(inName,"hxs_encoding"))
return (void *)default_get_encoding;
#ifdef HXCPP_PRIME
if (!strcmp(inName,"alloc_hxs_wchar"))
return (void *)default_string_wchar;
if (!strcmp(inName,"alloc_hxs_utf16"))
return (void *)default_string_utf16;
if (!strcmp(inName,"alloc_hxs_utf8"))
return (void *)default_string_utf8;
if (!strcmp(inName,"hxs_utf8"))
return (void *)default_to_utf8;
if (!strcmp(inName,"hxs_utf16"))
return (void *)default_to_utf16;
if (!strcmp(inName,"hxs_wchar"))
return (void *)default_to_wchar;
#endif
return 0;
}
#ifdef NEKO_WINDOWS // {
void *LoadFunc(const char *inName)
{
#ifndef HX_WINRT
static const char *modules[] = { 0, "hxcpp", "hxcpp-debug" };
for(int i=0; i<3 && sResolveProc==0; i++)
{
HMODULE handle = GetModuleHandleA(modules[i]);
if (handle)
{
sResolveProc = (ResolveProc)GetProcAddress(handle,"hx_cffi");
if (sResolveProc==0)
FreeLibrary(handle);
}
}
#endif
#ifdef NEKO_COMPATIBLE
if (sResolveProc==0)
{
sResolveProc = InitDynamicNekoLoader();
}
#endif
if (sResolveProc==0)
{
fprintf(stderr,"Could not link plugin to process (hxCFFILoader.h %d)\n",__LINE__);
exit(1);
}
return ResolveDefault(inName);
}
#else // windows } { not windows
void *LoadFunc(const char *inName)
{
#ifndef ANDROID // {
if (sResolveProc==0)
{
sResolveProc = (ResolveProc)dlsym(RTLD_DEFAULT,"hx_cffi");
}
#ifdef NEKO_COMPATIBLE
if (sResolveProc==0)
{
sResolveProc = InitDynamicNekoLoader();
}
#endif
#endif // !Android }
if (sResolveProc==0)
{
#ifdef ANDROID
__android_log_print(ANDROID_LOG_ERROR, "CFFILoader.h", "Could not API %s", inName);
return 0;
#else
#ifdef NEKO_COMPATIBLE
fprintf(stderr,"Could not link plugin to process (CFFILoader.h %d) - with neko\n",__LINE__);
#else
fprintf(stderr,"Could not link plugin to process (CFFILoader.h %d)\n",__LINE__);
#endif
exit(1);
#endif
}
return ResolveDefault(inName);
}
#undef EXT
#endif // not windows }
#ifndef ANDROID // not android {
#define DEFFUNC(name,ret,def_args,call_args) \
typedef ret (*FUNC_##name)def_args; \
extern FUNC_##name name; \
ret IMPL_##name def_args \
{ \
name = (FUNC_##name)LoadFunc(#name); \
if (!name) \
{ \
fprintf(stderr,"Could not find function:" #name " \n"); \
exit(1); \
} \
return name call_args; \
}\
FUNC_##name name = IMPL_##name;
#ifdef NEKO_COMPATIBLE
DEFINE_PRIM(neko_init,5)
#endif
#else // not android } { android
#define DEFFUNC(name,ret,def_args,call_args) \
typedef ret (*FUNC_##name)def_args; \
extern FUNC_##name name; \
ret IMPL_##name def_args \
{ \
name = (FUNC_##name)LoadFunc(#name); \
if (!name) \
{ \
__android_log_print(ANDROID_LOG_ERROR,"CFFILoader", "Could not find function:" #name "\n"); \
} \
return name call_args; \
}\
FUNC_##name name = IMPL_##name;
#endif // android }
#endif // dynamic link }
#endif

Some files were not shown because too many files have changed in this diff Show More