Update Files
This commit is contained in:
		
							
								
								
									
										11
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | root = true | ||||||
|  |  | ||||||
|  | [*] | ||||||
|  | charset = utf-8 | ||||||
|  | tab_width = 4 | ||||||
|  | indent_style = tab | ||||||
|  |  | ||||||
|  | [*.py] | ||||||
|  | indent_size = 4 | ||||||
|  | tab_width = 4 | ||||||
|  | indent_style = space | ||||||
							
								
								
									
										8
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | { | ||||||
|  | 	"editor.detectIndentation": false, | ||||||
|  | 	"editor.tabSize": 4, | ||||||
|  | 	"editor.insertSpaces": false, | ||||||
|  | 	"[python]": { | ||||||
|  | 		"editor.insertSpaces": true | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										79
									
								
								Kha/.clang-format
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								Kha/.clang-format
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | |||||||
|  | Language:        Cpp | ||||||
|  | BasedOnStyle:  LLVM | ||||||
|  | AccessModifierOffset: -4 | ||||||
|  | AlignAfterOpenBracket: Align | ||||||
|  | AlignConsecutiveAssignments: false | ||||||
|  | AlignConsecutiveDeclarations: false | ||||||
|  | AlignEscapedNewlinesLeft: false | ||||||
|  | AlignOperands:   true | ||||||
|  | AlignTrailingComments: true | ||||||
|  | AllowAllParametersOfDeclarationOnNextLine: true | ||||||
|  | AllowShortBlocksOnASingleLine: false | ||||||
|  | AllowShortCaseLabelsOnASingleLine: false | ||||||
|  | AllowShortFunctionsOnASingleLine: Empty | ||||||
|  | AllowShortIfStatementsOnASingleLine: true | ||||||
|  | AllowShortLoopsOnASingleLine: true | ||||||
|  | AlwaysBreakAfterDefinitionReturnType: None | ||||||
|  | AlwaysBreakAfterReturnType: None | ||||||
|  | AlwaysBreakBeforeMultilineStrings: false | ||||||
|  | AlwaysBreakTemplateDeclarations: false | ||||||
|  | BinPackArguments: true | ||||||
|  | BinPackParameters: true | ||||||
|  | BraceWrapping:    | ||||||
|  |   AfterClass:      false | ||||||
|  |   AfterControlStatement: false | ||||||
|  |   AfterEnum:       false | ||||||
|  |   AfterFunction:   false | ||||||
|  |   AfterNamespace:  false | ||||||
|  |   AfterObjCDeclaration: false | ||||||
|  |   AfterStruct:     false | ||||||
|  |   AfterUnion:      false | ||||||
|  |   BeforeCatch:     false | ||||||
|  |   BeforeElse:      true | ||||||
|  |   IndentBraces:    false | ||||||
|  | BreakBeforeBinaryOperators: None | ||||||
|  | BreakBeforeBraces: Custom | ||||||
|  | BreakBeforeTernaryOperators: true | ||||||
|  | BreakConstructorInitializersBeforeComma: false | ||||||
|  | ColumnLimit:     160 | ||||||
|  | CommentPragmas:  '^ IWYU pragma:' | ||||||
|  | ConstructorInitializerAllOnOneLineOrOnePerLine: false | ||||||
|  | ConstructorInitializerIndentWidth: 4 | ||||||
|  | ContinuationIndentWidth: 4 | ||||||
|  | Cpp11BracedListStyle: true | ||||||
|  | DerivePointerAlignment: false | ||||||
|  | DisableFormat:   false | ||||||
|  | FixNamespaceComments: false | ||||||
|  | IndentCaseLabels: false | ||||||
|  | IndentWidth:     4 | ||||||
|  | IndentWrappedFunctionNames: false | ||||||
|  | KeepEmptyLinesAtTheStartOfBlocks: true | ||||||
|  | MacroBlockBegin: '' | ||||||
|  | MacroBlockEnd:   '' | ||||||
|  | MaxEmptyLinesToKeep: 1 | ||||||
|  | NamespaceIndentation: All | ||||||
|  | ObjCBlockIndentWidth: 4 | ||||||
|  | ObjCSpaceAfterProperty: false | ||||||
|  | ObjCSpaceBeforeProtocolList: true | ||||||
|  | PenaltyBreakBeforeFirstCallParameter: 19 | ||||||
|  | PenaltyBreakComment: 300 | ||||||
|  | PenaltyBreakFirstLessLess: 120 | ||||||
|  | PenaltyBreakString: 1000 | ||||||
|  | PenaltyExcessCharacter: 1000000 | ||||||
|  | PenaltyReturnTypeOnItsOwnLine: 60 | ||||||
|  | PointerAlignment: Right | ||||||
|  | ReflowComments:  true | ||||||
|  | SortIncludes:    true | ||||||
|  | SpaceAfterCStyleCast: false | ||||||
|  | SpaceBeforeAssignmentOperators: true | ||||||
|  | SpaceBeforeParens: ControlStatements | ||||||
|  | SpaceInEmptyParentheses: false | ||||||
|  | SpacesBeforeTrailingComments: 1 | ||||||
|  | SpacesInAngles:  false | ||||||
|  | SpacesInContainerLiterals: true | ||||||
|  | SpacesInCStyleCastParentheses: false | ||||||
|  | SpacesInParentheses: false | ||||||
|  | SpacesInSquareBrackets: false | ||||||
|  | Standard:        Cpp03 | ||||||
|  | TabWidth:        4 | ||||||
|  | UseTab:          ForIndentation | ||||||
							
								
								
									
										6
									
								
								Kha/.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Kha/.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | { | ||||||
|  | 	"[haxe]": { | ||||||
|  | 		"editor.formatOnSave": true, | ||||||
|  | 		"editor.formatOnPaste": false | ||||||
|  | 	}, | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								Kha/Backends/Empty/kha/Blob.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Kha/Backends/Empty/kha/Blob.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | typedef Blob = kha.internal.BytesBlob; | ||||||
							
								
								
									
										75
									
								
								Kha/Backends/Empty/kha/Display.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								Kha/Backends/Empty/kha/Display.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | class Display { | ||||||
|  | 	static var instance: Display = new Display(); | ||||||
|  |  | ||||||
|  | 	function new() {} | ||||||
|  |  | ||||||
|  | 	public static function init(): Void {} | ||||||
|  |  | ||||||
|  | 	public static var primary(get, never): Display; | ||||||
|  |  | ||||||
|  | 	static function get_primary(): Display { | ||||||
|  | 		return instance; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var all(get, never): Array<Display>; | ||||||
|  |  | ||||||
|  | 	static function get_all(): Array<Display> { | ||||||
|  | 		return [primary]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var available(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	function get_available(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var name(get, never): String; | ||||||
|  |  | ||||||
|  | 	function get_name(): String { | ||||||
|  | 		return "Display"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var x(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_x(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var y(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_y(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var width(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return 1920; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return 1080; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var frequency(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_frequency(): Int { | ||||||
|  | 		return 60; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var pixelsPerInch(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_pixelsPerInch(): Int { | ||||||
|  | 		return 96; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var modes(get, never): Array<DisplayMode>; | ||||||
|  |  | ||||||
|  | 	function get_modes(): Array<DisplayMode> { | ||||||
|  | 		return []; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								Kha/Backends/Empty/kha/DisplayImpl.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Kha/Backends/Empty/kha/DisplayImpl.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | class DisplayImpl { | ||||||
|  | 	public static function count(): Int { | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function width(index: Int): Int { | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function height(index: Int): Int { | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function x(index: Int): Int { | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function y(index: Int): Int { | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function isPrimary(index: Int): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								Kha/Backends/Empty/kha/EnvironmentVariables.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Kha/Backends/Empty/kha/EnvironmentVariables.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | class EnvironmentVariables { | ||||||
|  | 	public static function get(name: String): String { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								Kha/Backends/Empty/kha/Font.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Kha/Backends/Empty/kha/Font.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | typedef Font = kha.Kravur; | ||||||
							
								
								
									
										173
									
								
								Kha/Backends/Empty/kha/Image.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								Kha/Backends/Empty/kha/Image.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,173 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import kha.graphics4.DepthStencilFormat; | ||||||
|  | import kha.graphics4.TextureFormat; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  |  | ||||||
|  | class Image implements Canvas implements Resource { | ||||||
|  | 	public static function create(width: Int, height: Int, format: TextureFormat = null, usage: Usage = null): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function create3D(width: Int, height: Int, depth: Int, format: TextureFormat = null, usage: Usage = null): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function createRenderTarget(width: Int, height: Int, format: TextureFormat = null, | ||||||
|  | 			depthStencil: DepthStencilFormat = DepthStencilFormat.NoDepthAndStencil, antiAliasingSamples: Int = 1): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromBytes(bytes: Bytes, width: Int, height: Int, format: TextureFormat = null, usage: Usage = null): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromBytes3D(bytes: Bytes, width: Int, height: Int, depth: Int, format: TextureFormat = null, usage: Usage = null): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var maxSize(get, never): Int; | ||||||
|  |  | ||||||
|  | 	static function get_maxSize(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var nonPow2Supported(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	static function get_nonPow2Supported(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function renderTargetsInvertedY(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function isOpaque(x: Int, y: Int): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Returns the color of a pixel identified by its x/y-coordinates. This only works for images for which | ||||||
|  | 	 * the readable flag is set to true because by default images only exist in video-memory. To load images | ||||||
|  | 	 * which are readable use a line ala project.addAssets('Assets/image.png', { readable: true }); in | ||||||
|  | 	 * your khafile. | ||||||
|  | 	 * For reading the content of render-targets use getPixels() instead. | ||||||
|  | 	 */ | ||||||
|  | 	public function at(x: Int, y: Int): Color { | ||||||
|  | 		return Color.Black; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unload(): Void {} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Returns a writable Bytes object. Once unlock() is called the content of the Bytes object | ||||||
|  | 	 * is written into the image. | ||||||
|  | 	 * This can not be used to read the current content of an image - for this use at() or getPixels() instead. | ||||||
|  | 	 */ | ||||||
|  | 	public function lock(level: Int = 0): Bytes { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(): Void {} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Returns the content of an image. This only works if the image is a render-target and it is very slow | ||||||
|  | 	 * because data will be copied from video-memory to main-memory. This is useful for making screenshots | ||||||
|  | 	 * but please avoid using it for regular rendering. | ||||||
|  | 	 * For reading the content of images which are not render-targets use at() instead. | ||||||
|  | 	 */ | ||||||
|  | 	public function getPixels(): Bytes { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function generateMipmaps(levels: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function setMipmaps(mipmaps: Array<Image>): Void {} | ||||||
|  |  | ||||||
|  | 	public function setDepthStencilFrom(image: Image): Void {} | ||||||
|  |  | ||||||
|  | 	public function clear(x: Int, y: Int, z: Int, width: Int, height: Int, depth: Int, color: Color): Void {} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Returns the original width of the image. | ||||||
|  | 	 */ | ||||||
|  | 	public var width(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Returns the original height of the image. | ||||||
|  | 	 */ | ||||||
|  | 	public var height(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var depth(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_depth(): Int { | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var format(get, never): TextureFormat; | ||||||
|  |  | ||||||
|  | 	function get_format(): TextureFormat { | ||||||
|  | 		return TextureFormat.RGBA32; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Very old GPUs only supported power of two texture-widths. | ||||||
|  | 	 * When an Image is created on such a GPU, Kha automatically increases | ||||||
|  | 	 * its size to a power of two and realWidth returns this new, internal | ||||||
|  | 	 * size. Knowing the real size is important for calculating | ||||||
|  | 	 * texture-coordinates correctly but all of this is irrelevant unless | ||||||
|  | 	 * you really want to support very very old GPUs. | ||||||
|  | 	 */ | ||||||
|  | 	public var realWidth(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_realWidth(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Very old GPUs only supported power of two texture-heights. | ||||||
|  | 	 * When an Image is created on such a GPU, Kha automatically increases | ||||||
|  | 	 * its size to a power of two and realHeight returns this new, internal | ||||||
|  | 	 * size. Knowing the real size is important for calculating | ||||||
|  | 	 * texture-coordinates correctly but all of this is irrelevant unless | ||||||
|  | 	 * you really want to support very very old GPUs. | ||||||
|  | 	 */ | ||||||
|  | 	public var realHeight(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_realHeight(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var stride(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_stride(): 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 { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								Kha/Backends/Empty/kha/LoaderImpl.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								Kha/Backends/Empty/kha/LoaderImpl.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import kha.FontStyle; | ||||||
|  | import kha.Blob; | ||||||
|  | import kha.Kravur; | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import haxe.io.BytesData; | ||||||
|  |  | ||||||
|  | class LoaderImpl { | ||||||
|  | 	public static function getImageFormats(): Array<String> { | ||||||
|  | 		return ["png", "jpg"]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadImageFromDescription(desc: Dynamic, done: kha.Image->Void, failed: AssetError->Void) {} | ||||||
|  |  | ||||||
|  | 	public static function getSoundFormats(): Array<String> { | ||||||
|  | 		return ["mp4", "ogg"]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadSoundFromDescription(desc: Dynamic, done: kha.Sound->Void, failed: AssetError->Void) {} | ||||||
|  |  | ||||||
|  | 	public static function getVideoFormats(): Array<String> { | ||||||
|  | 		return ["mp4", "webm"]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadVideoFromDescription(desc: Dynamic, done: kha.Video->Void, failed: AssetError->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public static function loadBlobFromDescription(desc: Dynamic, done: Blob->Void, failed: AssetError->Void) {} | ||||||
|  |  | ||||||
|  | 	public static function loadFontFromDescription(desc: Dynamic, done: Font->Void, failed: AssetError->Void): Void {} | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								Kha/Backends/Empty/kha/Storage.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Kha/Backends/Empty/kha/Storage.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import haxe.io.BytesBuffer; | ||||||
|  | import haxe.io.BytesData; | ||||||
|  |  | ||||||
|  | class Storage { | ||||||
|  | 	public static function namedFile(name: String): StorageFile { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function defaultFile(): StorageFile { | ||||||
|  | 		return namedFile("default.kha"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										139
									
								
								Kha/Backends/Empty/kha/SystemImpl.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								Kha/Backends/Empty/kha/SystemImpl.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,139 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import kha.graphics4.TextureFormat; | ||||||
|  | import kha.input.Gamepad; | ||||||
|  | import kha.input.Keyboard; | ||||||
|  | import kha.input.Mouse; | ||||||
|  | import kha.input.MouseImpl; | ||||||
|  | import kha.input.Surface; | ||||||
|  | import kha.System; | ||||||
|  |  | ||||||
|  | class SystemImpl { | ||||||
|  | 	public static function init(options: SystemOptions, callback: Window->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public static function getScreenRotation(): ScreenRotation { | ||||||
|  | 		return ScreenRotation.RotationNone; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getTime(): Float { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function windowWidth(id: Int): Int { | ||||||
|  | 		return 640; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function windowHeight(id: Int): Int { | ||||||
|  | 		return 480; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function screenDpi(): Int { | ||||||
|  | 		return 96; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getVsync(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getRefreshRate(): Int { | ||||||
|  | 		return 60; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getSystemId(): String { | ||||||
|  | 		return "Empty"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function vibrate(ms: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public static function getLanguage(): String { | ||||||
|  | 		return "en"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function requestShutdown(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getMouse(num: Int): Mouse { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getKeyboard(num: Int): Keyboard { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function lockMouse(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function unlockMouse(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function canLockMouse(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function isMouseLocked(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function notifyOfMouseLockChange(func: Void->Void, error: Void->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public static function removeFromMouseLockChange(func: Void->Void, error: Void->Void): Void {} | ||||||
|  |  | ||||||
|  | 	static function unload(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function canSwitchFullscreen(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function isFullscreen(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function requestFullscreen(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function exitFullscreen(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function notifyOfFullscreenChange(func: Void->Void, error: Void->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public static function removeFromFullscreenChange(func: Void->Void, error: Void->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public static function changeResolution(width: Int, height: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public static function setKeepScreenOn(on: Bool): Void {} | ||||||
|  |  | ||||||
|  | 	public static function loadUrl(url: String): Void {} | ||||||
|  |  | ||||||
|  | 	public static function getGamepadId(index: Int): String { | ||||||
|  | 		return "unknown"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getGamepadVendor(index: Int): String { | ||||||
|  | 		return "unknown"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function setGamepadRumble(index: Int, leftAmount: Float, rightAmount: Float) {} | ||||||
|  |  | ||||||
|  | 	public static function getPen(num: Int): kha.input.Pen { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function safeZone(): Float { | ||||||
|  | 		return 1.0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function login(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function automaticSafeZone(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function setSafeZone(value: Float): Void {} | ||||||
|  |  | ||||||
|  | 	public static function unlockAchievement(id: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public static function waitingForLogin(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function disallowUserChange(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function allowUserChange(): Void {} | ||||||
|  | } | ||||||
							
								
								
									
										134
									
								
								Kha/Backends/Empty/kha/Window.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								Kha/Backends/Empty/kha/Window.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,134 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | class Window { | ||||||
|  | 	static var windows: Array<Window> = []; | ||||||
|  |  | ||||||
|  | 	var defaultWidth: Int; | ||||||
|  | 	var defaultHeight: Int; | ||||||
|  |  | ||||||
|  | 	@:noCompletion | ||||||
|  | 	@:noDoc | ||||||
|  | 	public function new(defaultWidth: Int, defaultHeight: Int) { | ||||||
|  | 		windows.push(this); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function create(win: WindowOptions = null, frame: FramebufferOptions = null): Window { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function destroy(window: Window): Void {} | ||||||
|  |  | ||||||
|  | 	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; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function resize(width: Int, height: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function move(x: Int, y: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function changeWindowFeatures(features: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function changeFramebuffer(frame: FramebufferOptions): Void {} | ||||||
|  |  | ||||||
|  | 	public var x(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_x(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_x(value: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var y(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_y(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_y(value: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var width(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return 800; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_width(value: Int): Int { | ||||||
|  | 		return 800; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return 600; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_height(value: Int): Int { | ||||||
|  | 		return 600; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var mode(get, set): WindowMode; | ||||||
|  |  | ||||||
|  | 	function get_mode(): WindowMode { | ||||||
|  | 		return Windowed; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_mode(mode: WindowMode): WindowMode { | ||||||
|  | 		if (mode == Fullscreen || mode == ExclusiveFullscreen) { | ||||||
|  | 			if (!isFullscreen()) { | ||||||
|  | 				requestFullscreen(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			if (isFullscreen()) { | ||||||
|  | 				exitFullscreen(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return mode; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function isFullscreen(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function requestFullscreen(): Void {} | ||||||
|  |  | ||||||
|  | 	function exitFullscreen(): Void {} | ||||||
|  |  | ||||||
|  | 	public var visible(get, set): Bool; | ||||||
|  |  | ||||||
|  | 	function get_visible(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_visible(value: Bool): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var title(get, set): String; | ||||||
|  |  | ||||||
|  | 	function get_title(): String { | ||||||
|  | 		return "Kha"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_title(value: String): String { | ||||||
|  | 		return "Kha"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function notifyOnResize(callback: Int->Int->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public var vSynced(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	function get_vSynced(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										153
									
								
								Kha/Backends/Empty/kha/arrays/ByteArray.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								Kha/Backends/Empty/kha/arrays/ByteArray.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,153 @@ | |||||||
|  | package kha.arrays; | ||||||
|  |  | ||||||
|  | import kha.FastFloat; | ||||||
|  |  | ||||||
|  | class ByteArray { | ||||||
|  | 	public var buffer(get, never): ByteBuffer; | ||||||
|  |  | ||||||
|  | 	inline function get_buffer(): ByteBuffer { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function new(buffer: ByteBuffer, ?byteOffset: Int, ?byteLength: Int) {} | ||||||
|  |  | ||||||
|  | 	static public function make(byteLength: Int): ByteArray { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var byteLength(get, never): Int; | ||||||
|  |  | ||||||
|  | 	inline function get_byteLength(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var byteOffset(get, never): Int; | ||||||
|  |  | ||||||
|  | 	inline function get_byteOffset(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt8(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint8(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt16(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint16(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt32(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint32(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat32(byteOffset: Int): FastFloat { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat64(byteOffset: Int): Float { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt8(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setUint8(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setInt16(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setUint16(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setInt32(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setUint32(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat32(byteOffset: Int, value: FastFloat): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat64(byteOffset: Int, value: Float): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function getInt16LE(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint16LE(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt32LE(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint32LE(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat32LE(byteOffset: Int): FastFloat { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat64LE(byteOffset: Int): Float { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt16LE(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setUint16LE(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setInt32LE(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setUint32LE(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat32LE(byteOffset: Int, value: FastFloat): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat64LE(byteOffset: Int, value: Float): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function getInt16BE(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint16BE(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt32BE(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint32BE(byteOffset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat32BE(byteOffset: Int): FastFloat { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat64BE(byteOffset: Int): Float { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt16BE(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setUint16BE(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setInt32BE(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setUint32BE(byteOffset: Int, value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat32BE(byteOffset: Int, value: FastFloat): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat64BE(byteOffset: Int, value: Float): Void {} | ||||||
|  |  | ||||||
|  | 	public inline function subarray(start: Int, ?end: Int): ByteArray { | ||||||
|  | 		return new ByteArray(buffer, start, end != null ? end - start : null); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								Kha/Backends/Empty/kha/arrays/ByteBuffer.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Kha/Backends/Empty/kha/arrays/ByteBuffer.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | package kha.arrays; | ||||||
|  |  | ||||||
|  | class ByteBuffer { | ||||||
|  | 	public static function create(length: Int): ByteBuffer { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function new(length: Int) {} | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								Kha/Backends/Empty/kha/audio1/Audio.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Kha/Backends/Empty/kha/audio1/Audio.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | package kha.audio1; | ||||||
|  |  | ||||||
|  | import kha.Sound; | ||||||
|  |  | ||||||
|  | class Audio { | ||||||
|  | 	/** | ||||||
|  | 	 * Plays a sound immediately. | ||||||
|  | 	 * @param sound | ||||||
|  | 	 * The sound to play | ||||||
|  | 	 * @param loop | ||||||
|  | 	 * Whether or not to automatically loop the sound | ||||||
|  | 	 * @return A channel object that can be used to control the playing sound. Please be a ware that Null is returned when the maximum number of simultaneously played channels was reached. | ||||||
|  | 	 */ | ||||||
|  | 	public static function play(sound: Sound, loop: Bool = false): AudioChannel { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function stream(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function _playAgain(channel: kha.audio2.AudioChannel): Void {} | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								Kha/Backends/Empty/kha/audio2/Audio.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Kha/Backends/Empty/kha/audio2/Audio.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | package kha.audio2; | ||||||
|  |  | ||||||
|  | import kha.Sound; | ||||||
|  | import kha.internal.IntBox; | ||||||
|  |  | ||||||
|  | class Audio { | ||||||
|  | 	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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								Kha/Backends/Empty/kha/graphics4/CubeMap.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								Kha/Backends/Empty/kha/graphics4/CubeMap.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  |  | ||||||
|  | class CubeMap implements Canvas implements Resource { | ||||||
|  | 	public static function createRenderTarget(size: Int, format: TextureFormat = null, depthStencil: DepthStencilFormat = null): CubeMap { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unload(): Void {} | ||||||
|  |  | ||||||
|  | 	public function lock(level: Int = 0): Bytes { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(): Void {} | ||||||
|  |  | ||||||
|  | 	public var width(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, never): Int; | ||||||
|  |  | ||||||
|  | 	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 { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								Kha/Backends/Empty/kha/graphics4/FragmentShader.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Kha/Backends/Empty/kha/graphics4/FragmentShader.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | class FragmentShader { | ||||||
|  | 	public var sources: Array<String>; | ||||||
|  | 	public var type: Dynamic; | ||||||
|  | 	public var shader: Dynamic; | ||||||
|  | 	public var files: Array<String>; | ||||||
|  |  | ||||||
|  | 	public function new(sources: Array<Blob>, files: Array<String>) {} | ||||||
|  |  | ||||||
|  | 	public static function fromSource(source: String): FragmentShader { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		shader = null; | ||||||
|  | 		sources = null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								Kha/Backends/Empty/kha/graphics4/IndexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Kha/Backends/Empty/kha/graphics4/IndexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  |  | ||||||
|  | class IndexBuffer { | ||||||
|  | 	public function new(indexCount: Int, usage: Usage, canRead: Bool = false) {} | ||||||
|  |  | ||||||
|  | 	public function lock(?start: Int, ?count: Int): Array<Int> { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(?count: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function set(): Void {} | ||||||
|  |  | ||||||
|  | 	public function count(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								Kha/Backends/Empty/kha/graphics4/PipelineState.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								Kha/Backends/Empty/kha/graphics4/PipelineState.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import kha.graphics4.FragmentShader; | ||||||
|  | import kha.graphics4.VertexData; | ||||||
|  | import kha.graphics4.VertexShader; | ||||||
|  | import kha.graphics4.VertexStructure; | ||||||
|  |  | ||||||
|  | class PipelineState extends PipelineStateBase { | ||||||
|  | 	public function new() { | ||||||
|  | 		super(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function compile(): Void {} | ||||||
|  |  | ||||||
|  | 	public function set(): Void {} | ||||||
|  |  | ||||||
|  | 	public function getConstantLocation(name: String): kha.graphics4.ConstantLocation { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function getTextureUnit(name: String): kha.graphics4.TextureUnit { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										28
									
								
								Kha/Backends/Empty/kha/graphics4/VertexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								Kha/Backends/Empty/kha/graphics4/VertexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import kha.arrays.Float32Array; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  | import kha.graphics4.VertexStructure; | ||||||
|  | import kha.graphics4.VertexData; | ||||||
|  |  | ||||||
|  | class VertexBuffer { | ||||||
|  | 	public function new(vertexCount: Int, structure: VertexStructure, usage: Usage, instanceDataStepRate: Int = 0, canRead: Bool = false) {} | ||||||
|  |  | ||||||
|  | 	public function lock(?start: Int, ?count: Int): Float32Array { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(?count: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function stride(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function count(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function set(offset: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								Kha/Backends/Empty/kha/graphics4/VertexShader.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Kha/Backends/Empty/kha/graphics4/VertexShader.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | class VertexShader { | ||||||
|  | 	public var sources: Array<String>; | ||||||
|  | 	public var type: Dynamic; | ||||||
|  | 	public var shader: Dynamic; | ||||||
|  | 	public var files: Array<String>; | ||||||
|  |  | ||||||
|  | 	public function new(sources: Array<Blob>, files: Array<String>) {} | ||||||
|  |  | ||||||
|  | 	public static function fromSource(source: String): FragmentShader { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		shader = null; | ||||||
|  | 		sources = null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								Kha/Backends/Empty/kha/input/MouseImpl.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Kha/Backends/Empty/kha/input/MouseImpl.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | package kha.input; | ||||||
|  |  | ||||||
|  | class MouseImpl extends kha.input.Mouse { | ||||||
|  | 	public function new() { | ||||||
|  | 		super(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								Kha/Backends/Empty/kha/netsync/Network.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Kha/Backends/Empty/kha/netsync/Network.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | package kha.netsync; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  |  | ||||||
|  | class Network { | ||||||
|  | 	public function new(url: String, port: Int, errorCallback: Void->Void, closeCallback: Void->Void) {} | ||||||
|  |  | ||||||
|  | 	public function send(bytes: Bytes, mandatory: Bool): Void {} | ||||||
|  |  | ||||||
|  | 	public function listen(listener: Bytes->Void): Void {} | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								Kha/Backends/Empty/kha/network/Http.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Kha/Backends/Empty/kha/network/Http.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | package kha.network; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  |  | ||||||
|  | class Http { | ||||||
|  | 	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 {} | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								Kha/Backends/HTML5-Worker/kha/Blob.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Kha/Backends/HTML5-Worker/kha/Blob.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | typedef Blob = kha.internal.BytesBlob; | ||||||
							
								
								
									
										77
									
								
								Kha/Backends/HTML5-Worker/kha/Display.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								Kha/Backends/HTML5-Worker/kha/Display.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import js.Browser; | ||||||
|  |  | ||||||
|  | class Display { | ||||||
|  | 	static var instance: Display = new Display(); | ||||||
|  |  | ||||||
|  | 	function new() {} | ||||||
|  |  | ||||||
|  | 	public static function init(): Void {} | ||||||
|  |  | ||||||
|  | 	public static var primary(get, never): Display; | ||||||
|  |  | ||||||
|  | 	static function get_primary(): Display { | ||||||
|  | 		return instance; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var all(get, never): Array<Display>; | ||||||
|  |  | ||||||
|  | 	static function get_all(): Array<Display> { | ||||||
|  | 		return [primary]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var available(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	function get_available(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var name(get, never): String; | ||||||
|  |  | ||||||
|  | 	function get_name(): String { | ||||||
|  | 		return "Display"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var x(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_x(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var y(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_y(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var width(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return 800; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return 600; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var frequency(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_frequency(): Int { | ||||||
|  | 		return 60; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var pixelsPerInch(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_pixelsPerInch(): Int { | ||||||
|  | 		return 96; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var modes(get, never): Array<DisplayMode>; | ||||||
|  |  | ||||||
|  | 	function get_modes(): Array<DisplayMode> { | ||||||
|  | 		return []; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								Kha/Backends/HTML5-Worker/kha/Font.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Kha/Backends/HTML5-Worker/kha/Font.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | typedef Font = kha.Kravur; | ||||||
							
								
								
									
										222
									
								
								Kha/Backends/HTML5-Worker/kha/Image.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								Kha/Backends/HTML5-Worker/kha/Image.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,222 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import kha.graphics4.Graphics; | ||||||
|  | import kha.graphics4.DepthStencilFormat; | ||||||
|  | import kha.graphics4.TextureFormat; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  |  | ||||||
|  | class Image implements Canvas implements Resource { | ||||||
|  | 	public var id: Int; | ||||||
|  | 	public var _rtid: Int; | ||||||
|  |  | ||||||
|  | 	public static var _lastId: Int = -1; | ||||||
|  | 	static var lastRtId: Int = -1; | ||||||
|  |  | ||||||
|  | 	var w: Int; | ||||||
|  | 	var h: Int; | ||||||
|  | 	var rw: Int; | ||||||
|  | 	var rh: Int; | ||||||
|  | 	var myFormat: TextureFormat; | ||||||
|  | 	var bytes: Bytes = null; | ||||||
|  |  | ||||||
|  | 	public function new(id: Int, rtid: Int, width: Int, height: Int, realWidth: Int, realHeight: Int, format: TextureFormat) { | ||||||
|  | 		this.id = id; | ||||||
|  | 		this._rtid = rtid; | ||||||
|  | 		w = width; | ||||||
|  | 		h = height; | ||||||
|  | 		rw = realWidth; | ||||||
|  | 		rh = realHeight; | ||||||
|  | 		myFormat = format; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function create(width: Int, height: Int, format: TextureFormat = null, usage: Usage = null, readable: Bool = false): Image { | ||||||
|  | 		if (format == null) | ||||||
|  | 			format = TextureFormat.RGBA32; | ||||||
|  | 		if (usage == null) | ||||||
|  | 			usage = Usage.StaticUsage; | ||||||
|  | 		var id = ++_lastId; | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'createImage', | ||||||
|  | 			id: id, | ||||||
|  | 			width: width, | ||||||
|  | 			height: height, | ||||||
|  | 			format: format, | ||||||
|  | 			usage: usage | ||||||
|  | 		}); | ||||||
|  | 		return new Image(id, -1, width, height, width, height, format); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function create3D(width: Int, height: Int, depth: Int, format: TextureFormat = null, usage: Usage = null, readable: Bool = false): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function createRenderTarget(width: Int, height: Int, format: TextureFormat = null, | ||||||
|  | 			depthStencil: DepthStencilFormat = DepthStencilFormat.NoDepthAndStencil, antiAliasingSamples: Int = 1): Image { | ||||||
|  | 		if (format == null) | ||||||
|  | 			format = TextureFormat.RGBA32; | ||||||
|  | 		var rtid = ++lastRtId; | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'createRenderTarget', | ||||||
|  | 			id: rtid, | ||||||
|  | 			width: width, | ||||||
|  | 			height: height | ||||||
|  | 		}); | ||||||
|  | 		return new Image(-1, rtid, width, height, width, height, format); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromBytes(bytes: Bytes, width: Int, height: Int, format: TextureFormat = null, usage: Usage = null, readable: Bool = false): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromBytes3D(bytes: Bytes, width: Int, height: Int, depth: Int, format: TextureFormat = null, usage: Usage = null, | ||||||
|  | 			readable: Bool = false): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var maxSize(get, never): Int; | ||||||
|  |  | ||||||
|  | 	static function get_maxSize(): Int { | ||||||
|  | 		return 1024 * 4; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var nonPow2Supported(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	static function get_nonPow2Supported(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function renderTargetsInvertedY(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function isOpaque(x: Int, y: Int): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unload(): Void {} | ||||||
|  |  | ||||||
|  | 	public function lock(level: Int = 0): Bytes { | ||||||
|  | 		if (bytes == null) { | ||||||
|  | 			switch (myFormat) { | ||||||
|  | 				case RGBA32: | ||||||
|  | 					bytes = Bytes.alloc(4 * width * height); | ||||||
|  | 				case L8: | ||||||
|  | 					bytes = Bytes.alloc(width * height); | ||||||
|  | 				case RGBA128: | ||||||
|  | 					bytes = Bytes.alloc(16 * width * height); | ||||||
|  | 				case DEPTH16: | ||||||
|  | 					bytes = Bytes.alloc(2 * width * height); | ||||||
|  | 				case RGBA64: | ||||||
|  | 					bytes = Bytes.alloc(8 * width * height); | ||||||
|  | 				case A32: | ||||||
|  | 					bytes = Bytes.alloc(4 * width * height); | ||||||
|  | 				case A16: | ||||||
|  | 					bytes = Bytes.alloc(2 * width * height); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return bytes; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(): Void { | ||||||
|  | 		Worker.postMessage({command: 'unlockImage', id: id, bytes: bytes.getData()}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function getPixels(): Bytes { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function generateMipmaps(levels: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function setMipmaps(mipmaps: Array<Image>): Void {} | ||||||
|  |  | ||||||
|  | 	public function setDepthStencilFrom(image: Image): Void {} | ||||||
|  |  | ||||||
|  | 	public function clear(x: Int, y: Int, z: Int, width: Int, height: Int, depth: Int, color: Color): Void {} | ||||||
|  |  | ||||||
|  | 	public var width(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return w; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return h; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var depth(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_depth(): Int { | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var format(get, never): TextureFormat; | ||||||
|  |  | ||||||
|  | 	function get_format(): TextureFormat { | ||||||
|  | 		return myFormat; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var realWidth(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_realWidth(): Int { | ||||||
|  | 		return rw; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var realHeight(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_realHeight(): Int { | ||||||
|  | 		return rh; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	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 var stride(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_stride(): Int { | ||||||
|  | 		return formatByteSize(myFormat) * width; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var graphics1: kha.graphics1.Graphics; | ||||||
|  | 	var graphics2: kha.graphics2.Graphics; | ||||||
|  | 	var graphics4: kha.graphics4.Graphics; | ||||||
|  |  | ||||||
|  | 	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.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.html5worker.Graphics(this); | ||||||
|  | 		} | ||||||
|  | 		return graphics4; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										80
									
								
								Kha/Backends/HTML5-Worker/kha/LoaderImpl.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								Kha/Backends/HTML5-Worker/kha/LoaderImpl.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import kha.graphics4.TextureFormat; | ||||||
|  |  | ||||||
|  | class LoaderImpl { | ||||||
|  | 	static var loadingImages: Map<Int, Image->Void> = new Map(); | ||||||
|  | 	static var loadingSounds: Map<Int, Sound->Void> = new Map(); | ||||||
|  | 	static var soundId = -1; | ||||||
|  | 	static var loadingVideos: Map<Int, Video->Void> = new Map(); | ||||||
|  | 	static var videoId = -1; | ||||||
|  | 	static var loadingBlobs: Map<Int, Blob->Void> = new Map(); | ||||||
|  | 	static var blobId = -1; | ||||||
|  | 	static var sounds: Map<Int, Sound> = new Map(); | ||||||
|  |  | ||||||
|  | 	public static function getImageFormats(): Array<String> { | ||||||
|  | 		return ["png", "jpg", "hdr"]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadImageFromDescription(desc: Dynamic, done: kha.Image->Void, failed: AssetError->Void) { | ||||||
|  | 		++kha.Image._lastId; | ||||||
|  | 		loadingImages[kha.Image._lastId] = done; | ||||||
|  | 		Worker.postMessage({command: 'loadImage', file: desc.files[0], id: kha.Image._lastId}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function _loadedImage(value: Dynamic) { | ||||||
|  | 		var image = new Image(value.id, -1, value.width, value.height, value.realWidth, value.realHeight, TextureFormat.RGBA32); | ||||||
|  | 		loadingImages[value.id](image); | ||||||
|  | 		loadingImages.remove(value.id); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getSoundFormats(): Array<String> { | ||||||
|  | 		return ["mp4"]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadSoundFromDescription(desc: Dynamic, done: kha.Sound->Void, failed: AssetError->Void) { | ||||||
|  | 		++soundId; | ||||||
|  | 		loadingSounds[soundId] = done; | ||||||
|  | 		Worker.postMessage({command: 'loadSound', file: desc.files[0], id: soundId}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function _loadedSound(value: Dynamic) { | ||||||
|  | 		var sound = new kha.html5worker.Sound(value.id); | ||||||
|  | 		loadingSounds[value.id](sound); | ||||||
|  | 		loadingSounds.remove(value.id); | ||||||
|  | 		sounds.set(value.id, sound); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function _uncompressedSound(value: Dynamic): Void { | ||||||
|  | 		cast(sounds[value.id], kha.html5worker.Sound)._callback(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getVideoFormats(): Array<String> { | ||||||
|  | 		return ["mp4"]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadVideoFromDescription(desc: Dynamic, done: kha.Video->Void, failed: AssetError->Void): Void { | ||||||
|  | 		++videoId; | ||||||
|  | 		loadingVideos[videoId] = done; | ||||||
|  | 		Worker.postMessage({command: 'loadVideo', file: desc.files[0], id: videoId}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadBlobFromDescription(desc: Dynamic, done: Blob->Void, failed: AssetError->Void) { | ||||||
|  | 		++blobId; | ||||||
|  | 		loadingBlobs[blobId] = done; | ||||||
|  | 		Worker.postMessage({command: 'loadBlob', file: desc.files[0], id: blobId}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function _loadedBlob(value: Dynamic) { | ||||||
|  | 		var blob = new Blob(Bytes.ofData(value.data)); | ||||||
|  | 		loadingBlobs[value.id](blob); | ||||||
|  | 		loadingBlobs.remove(value.id); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadFontFromDescription(desc: Dynamic, done: Font->Void, failed: AssetError->Void): Void { | ||||||
|  | 		loadBlobFromDescription(desc, function(blob: Blob) { | ||||||
|  | 			done(new Kravur(blob)); | ||||||
|  | 		}, failed); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										89
									
								
								Kha/Backends/HTML5-Worker/kha/Starter.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								Kha/Backends/HTML5-Worker/kha/Starter.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import kha.Game; | ||||||
|  | import kha.input.Gamepad; | ||||||
|  | import kha.input.Keyboard; | ||||||
|  | import kha.js.WorkerGraphics; | ||||||
|  | import kha.Key; | ||||||
|  | import kha.Loader; | ||||||
|  |  | ||||||
|  | class Starter { | ||||||
|  | 	var gameToStart: Game; | ||||||
|  |  | ||||||
|  | 	static var frame: Framebuffer = null; | ||||||
|  | 	static var keyboard: Keyboard; | ||||||
|  | 	static var mouse: kha.input.Mouse; | ||||||
|  | 	static var gamepad: Gamepad; | ||||||
|  |  | ||||||
|  | 	public static var mouseX: Int; | ||||||
|  | 	public static var mouseY: Int; | ||||||
|  |  | ||||||
|  | 	public function new() { | ||||||
|  | 		Worker.handleMessages(messageHandler); | ||||||
|  | 		keyboard = new Keyboard(); | ||||||
|  | 		mouse = new kha.input.Mouse(); | ||||||
|  | 		gamepad = new Gamepad(); | ||||||
|  |  | ||||||
|  | 		Loader.init(new kha.js.Loader()); | ||||||
|  | 		Scheduler.init(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function start(game: Game): Void { | ||||||
|  | 		gameToStart = game; | ||||||
|  | 		Configuration.setScreen(new EmptyScreen(Color.fromBytes(0, 0, 0))); | ||||||
|  | 		Loader.the.loadProject(loadFinished); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function loadFinished() { | ||||||
|  | 		Loader.the.initProject(); | ||||||
|  |  | ||||||
|  | 		gameToStart.width = Loader.the.width; | ||||||
|  | 		gameToStart.height = Loader.the.height; | ||||||
|  |  | ||||||
|  | 		Sys.init(gameToStart.width, gameToStart.height); | ||||||
|  | 		frame = new Framebuffer(new WorkerGraphics(gameToStart.width, gameToStart.height), null); | ||||||
|  | 		Scheduler.start(); | ||||||
|  |  | ||||||
|  | 		Configuration.setScreen(gameToStart); | ||||||
|  |  | ||||||
|  | 		gameToStart.loadFinished(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function lockMouse(): Void {} | ||||||
|  |  | ||||||
|  | 	public function unlockMouse(): Void {} | ||||||
|  |  | ||||||
|  | 	public function canLockMouse(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function isMouseLocked(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function notifyOfMouseLockChange(func: Void->Void, error: Void->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public function removeFromMouseLockChange(func: Void->Void, error: Void->Void): Void {} | ||||||
|  |  | ||||||
|  | 	function messageHandler(value: Dynamic): Void { | ||||||
|  | 		switch (value.data.command) { | ||||||
|  | 			case 'loadedBlob': | ||||||
|  | 				cast(Loader.the, kha.js.Loader).loadedBlob(value.data); | ||||||
|  | 			case 'loadedImage': | ||||||
|  | 				cast(Loader.the, kha.js.Loader).loadedImage(value.data); | ||||||
|  | 			case 'loadedSound': | ||||||
|  | 				cast(Loader.the, kha.js.Loader).loadedSound(value.data); | ||||||
|  | 			case 'loadedMusic': | ||||||
|  | 				cast(Loader.the, kha.js.Loader).loadedMusic(value.data); | ||||||
|  | 			case 'frame': | ||||||
|  | 				if (frame != null) { | ||||||
|  | 					Scheduler.executeFrame(); | ||||||
|  | 					Configuration.screen().render(frame); | ||||||
|  | 				} | ||||||
|  | 			case 'keyDown': | ||||||
|  | 				Configuration.screen().keyDown(Key.createByIndex(value.data.key), value.data.char); | ||||||
|  | 			case 'keyUp': | ||||||
|  | 				Configuration.screen().keyUp(Key.createByIndex(value.data.key), value.data.char); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								Kha/Backends/HTML5-Worker/kha/Storage.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Kha/Backends/HTML5-Worker/kha/Storage.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import haxe.io.BytesData; | ||||||
|  | import js.lib.ArrayBuffer; | ||||||
|  |  | ||||||
|  | class Storage { | ||||||
|  | 	public static function namedFile(name: String): StorageFile { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function defaultFile(): StorageFile { | ||||||
|  | 		return namedFile("default.kha"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										241
									
								
								Kha/Backends/HTML5-Worker/kha/SystemImpl.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								Kha/Backends/HTML5-Worker/kha/SystemImpl.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,241 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import kha.input.Gamepad; | ||||||
|  | import kha.input.Keyboard; | ||||||
|  | import kha.input.KeyCode; | ||||||
|  | import kha.input.Mouse; | ||||||
|  | import kha.input.Surface; | ||||||
|  | import kha.System; | ||||||
|  |  | ||||||
|  | class GamepadStates { | ||||||
|  | 	public var axes: Array<Float>; | ||||||
|  | 	public var buttons: Array<Float>; | ||||||
|  |  | ||||||
|  | 	public function new() { | ||||||
|  | 		axes = new Array<Float>(); | ||||||
|  | 		buttons = new Array<Float>(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class SystemImpl { | ||||||
|  | 	static var options: SystemOptions; | ||||||
|  | 	@:allow(kha.Window) | ||||||
|  | 	static var width: Int = 800; | ||||||
|  | 	@:allow(kha.Window) | ||||||
|  | 	static var height: Int = 600; | ||||||
|  | 	static var dpi: Int = 96; | ||||||
|  | 	static inline var maxGamepads: Int = 4; | ||||||
|  | 	static var frame: Framebuffer; | ||||||
|  | 	static var keyboard: Keyboard = null; | ||||||
|  | 	static var mouse: kha.input.Mouse; | ||||||
|  | 	static var surface: Surface; | ||||||
|  | 	static var gamepads: Array<Gamepad>; | ||||||
|  |  | ||||||
|  | 	public static function init(options: SystemOptions, callback: Window->Void) { | ||||||
|  | 		Worker.handleMessages(messageHandler); | ||||||
|  |  | ||||||
|  | 		Shaders.init(); | ||||||
|  | 		var shaders = new Array<Dynamic>(); | ||||||
|  | 		for (field in Reflect.fields(Shaders)) { | ||||||
|  | 			if (field != "init" && field != "__name__" && field.substr(field.length - 5, 4) != "Data") { | ||||||
|  | 				var shader = Reflect.field(Shaders, field); | ||||||
|  | 				shaders.push({ | ||||||
|  | 					name: field, | ||||||
|  | 					files: shader.files, | ||||||
|  | 					sources: shader.sources | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		Worker.postMessage({command: 'setShaders', shaders: shaders}); | ||||||
|  |  | ||||||
|  | 		SystemImpl.options = options; | ||||||
|  |  | ||||||
|  | 		// haxe.Log.trace = untyped js.Boot.__trace; // Hack for JS trace problems | ||||||
|  |  | ||||||
|  | 		keyboard = new Keyboard(); | ||||||
|  | 		mouse = new Mouse(); | ||||||
|  | 		surface = new Surface(); | ||||||
|  | 		gamepads = new Array<Gamepad>(); | ||||||
|  | 		for (i in 0...maxGamepads) { | ||||||
|  | 			gamepads[i] = new Gamepad(i); | ||||||
|  | 		} | ||||||
|  | 		var window = new Window(); | ||||||
|  |  | ||||||
|  | 		var g4 = new kha.html5worker.Graphics(); | ||||||
|  | 		frame = new Framebuffer(0, null, null, g4); | ||||||
|  | 		frame.init(new kha.graphics2.Graphics1(frame), new kha.graphics4.Graphics2(frame), g4); | ||||||
|  |  | ||||||
|  | 		Scheduler.init(); | ||||||
|  | 		Scheduler.start(); | ||||||
|  |  | ||||||
|  | 		callback(window); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function windowWidth(windowId: Int = 0): Int { | ||||||
|  | 		return Window.get(0).width; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function windowHeight(windowId: Int = 0): Int { | ||||||
|  | 		return Window.get(0).height; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function screenDpi(): Int { | ||||||
|  | 		return dpi; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getScreenRotation(): ScreenRotation { | ||||||
|  | 		return ScreenRotation.RotationNone; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getTime(): Float { | ||||||
|  | 		return js.Syntax.code("Date.now()") / 1000; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getVsync(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getRefreshRate(): Int { | ||||||
|  | 		return 60; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getSystemId(): String { | ||||||
|  | 		return "HTML5-Worker"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function vibrate(ms: Int): Void { | ||||||
|  | 		js.Browser.navigator.vibrate(ms); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getLanguage(): String { | ||||||
|  | 		final lang = js.Browser.navigator.language; | ||||||
|  | 		return lang.substr(0, 2).toLowerCase(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function requestShutdown(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getMouse(num: Int): Mouse { | ||||||
|  | 		if (num != 0) | ||||||
|  | 			return null; | ||||||
|  | 		return mouse; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getKeyboard(num: Int): Keyboard { | ||||||
|  | 		if (num != 0) | ||||||
|  | 			return null; | ||||||
|  | 		return keyboard; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function lockMouse(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function unlockMouse(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function canLockMouse(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function isMouseLocked(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function notifyOfMouseLockChange(func: Void->Void, error: Void->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public static function removeFromMouseLockChange(func: Void->Void, error: Void->Void): Void {} | ||||||
|  |  | ||||||
|  | 	static function unload(_): Void {} | ||||||
|  |  | ||||||
|  | 	public static function canSwitchFullscreen(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function isFullscreen(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function requestFullscreen(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function exitFullscreen(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function notifyOfFullscreenChange(func: Void->Void, error: Void->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public static function removeFromFullscreenChange(func: Void->Void, error: Void->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public static function changeResolution(width: Int, height: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public static function setKeepScreenOn(on: Bool): Void {} | ||||||
|  |  | ||||||
|  | 	public static function loadUrl(url: String): Void {} | ||||||
|  |  | ||||||
|  | 	public static function getGamepadId(index: Int): String { | ||||||
|  | 		return "unknown"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getGamepadVendor(index: Int): String { | ||||||
|  | 		return "unknown"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function setGamepadRumble(index: Int, leftAmount: Float, rightAmount: Float) {} | ||||||
|  |  | ||||||
|  | 	static function messageHandler(value: Dynamic): Void { | ||||||
|  | 		switch (value.data.command) { | ||||||
|  | 			case 'patch': | ||||||
|  | 				js.Lib.eval(value.data.source); | ||||||
|  | 			case 'loadedImage': | ||||||
|  | 				LoaderImpl._loadedImage(value.data); | ||||||
|  | 			case 'loadedSound': | ||||||
|  | 				LoaderImpl._loadedSound(value.data); | ||||||
|  | 			case 'loadedBlob': | ||||||
|  | 				LoaderImpl._loadedBlob(value.data); | ||||||
|  | 			case 'uncompressedSound': | ||||||
|  | 				LoaderImpl._uncompressedSound(value.data); | ||||||
|  | 			case 'frame': | ||||||
|  | 				if (frame != null) { | ||||||
|  | 					Scheduler.executeFrame(); | ||||||
|  | 					Worker.postMessage({command: 'beginFrame'}); | ||||||
|  | 					System.render([frame]); | ||||||
|  | 					Worker.postMessage({command: 'endFrame'}); | ||||||
|  | 				} | ||||||
|  | 			case 'setWindowSize': | ||||||
|  | 				width = value.data.width; | ||||||
|  | 				height = value.data.height; | ||||||
|  | 			case 'keyDown': | ||||||
|  | 				keyboard.sendDownEvent(cast value.data.key); | ||||||
|  | 			case 'keyUp': | ||||||
|  | 				keyboard.sendUpEvent(cast value.data.key); | ||||||
|  | 			case 'keyPress': | ||||||
|  | 				keyboard.sendPressEvent(value.data.character); | ||||||
|  | 			case 'mouseDown': | ||||||
|  | 				mouse.sendDownEvent(0, value.data.button, value.data.x, value.data.y); | ||||||
|  | 			case 'mouseUp': | ||||||
|  | 				mouse.sendUpEvent(0, value.data.button, value.data.x, value.data.y); | ||||||
|  | 			case 'mouseMove': | ||||||
|  | 				mouse.sendMoveEvent(0, value.data.x, value.data.y, value.data.mx, value.data.my); | ||||||
|  | 			case 'mouseWheel': | ||||||
|  | 				mouse.sendWheelEvent(0, value.data.delta); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function safeZone(): Float { | ||||||
|  | 		return 1.0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function login(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function automaticSafeZone(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function setSafeZone(value: Float): Void {} | ||||||
|  |  | ||||||
|  | 	public static function unlockAchievement(id: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public static function waitingForLogin(): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function disallowUserChange(): Void {} | ||||||
|  |  | ||||||
|  | 	public static function allowUserChange(): Void {} | ||||||
|  | } | ||||||
							
								
								
									
										119
									
								
								Kha/Backends/HTML5-Worker/kha/Window.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								Kha/Backends/HTML5-Worker/kha/Window.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | class Window { | ||||||
|  | 	static var instance: Window; | ||||||
|  |  | ||||||
|  | 	@:allow(kha.SystemImpl) | ||||||
|  | 	function new() { | ||||||
|  | 		instance = this; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function create(win: WindowOptions = null, frame: FramebufferOptions = null): Window { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function destroy(window: Window): Void {} | ||||||
|  |  | ||||||
|  | 	public static function get(index: Int): Window { | ||||||
|  | 		if (index == 0) { | ||||||
|  | 			return instance; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var all(get, never): Array<Window>; | ||||||
|  |  | ||||||
|  | 	static function get_all(): Array<Window> { | ||||||
|  | 		return [instance]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function resize(width: Int, height: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function move(x: Int, y: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function changeWindowFeatures(features: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function changeFramebuffer(frame: FramebufferOptions): Void {} | ||||||
|  |  | ||||||
|  | 	public var x(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_x(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_x(value: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var y(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_y(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_y(value: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var width(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return SystemImpl.width; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_width(value: Int): Int { | ||||||
|  | 		return SystemImpl.width; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return SystemImpl.height; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_height(value: Int): Int { | ||||||
|  | 		return SystemImpl.height; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var mode(get, set): WindowMode; | ||||||
|  |  | ||||||
|  | 	function get_mode(): WindowMode { | ||||||
|  | 		return Windowed; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_mode(value: WindowMode): WindowMode { | ||||||
|  | 		return Windowed; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var visible(get, set): Bool; | ||||||
|  |  | ||||||
|  | 	function get_visible(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_visible(value: Bool): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var title(get, set): String; | ||||||
|  |  | ||||||
|  | 	function get_title(): String { | ||||||
|  | 		return "Kha"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_title(value: String): String { | ||||||
|  | 		return "Kha"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function notifyOnResize(callback: Int->Int->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public function notifyOnPpiChange(callback: Int->Void): Void {} | ||||||
|  |  | ||||||
|  | 	public var vSynced(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	function get_vSynced(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								Kha/Backends/HTML5-Worker/kha/Worker.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Kha/Backends/HTML5-Worker/kha/Worker.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | class Worker { | ||||||
|  | 	public static function postMessage(m: Dynamic): Void { | ||||||
|  | 		try { | ||||||
|  | 			js.Syntax.code("self.postMessage(m)"); | ||||||
|  | 		} | ||||||
|  | 		catch (e:Dynamic) { | ||||||
|  | 			trace(e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function handleMessages(messageHandler: Dynamic->Void) { | ||||||
|  | 		untyped js.Syntax.code("self.onmessage = messageHandler"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										187
									
								
								Kha/Backends/HTML5-Worker/kha/arrays/ByteArray.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								Kha/Backends/HTML5-Worker/kha/arrays/ByteArray.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,187 @@ | |||||||
|  | package kha.arrays; | ||||||
|  |  | ||||||
|  | import js.lib.DataView; | ||||||
|  | import kha.FastFloat; | ||||||
|  |  | ||||||
|  | @:forward | ||||||
|  | abstract ByteArray(DataView) to DataView { | ||||||
|  | 	static final LITTLE_ENDIAN: Bool = js.Syntax.code("new Uint8Array(new Uint32Array([0x12345678]).buffer)[0] === 0x78"); | ||||||
|  |  | ||||||
|  | 	public var buffer(get, never): ByteBuffer; | ||||||
|  |  | ||||||
|  | 	inline function get_buffer(): ByteBuffer { | ||||||
|  | 		return cast this.buffer; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function new(buffer: ByteBuffer, ?byteOffset: Int, ?byteLength: Int) { | ||||||
|  | 		this = new DataView(buffer, byteOffset, byteLength); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static public function make(byteLength: Int): ByteArray { | ||||||
|  | 		return new ByteArray(ByteBuffer.create(byteLength)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt8(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt8(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint8(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint8(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt16(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt16(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint16(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint16(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt32(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt32(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint32(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint32(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat32(byteOffset: Int): FastFloat { | ||||||
|  | 		return this.getFloat32(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat64(byteOffset: Int): Float { | ||||||
|  | 		return this.getFloat64(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt8(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt8(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint8(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint8(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt16(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt16(byteOffset, value, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint16(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint16(byteOffset, value, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt32(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt32(byteOffset, value, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint32(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint32(byteOffset, value, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat32(byteOffset: Int, value: FastFloat): Void { | ||||||
|  | 		this.setFloat32(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat64(byteOffset: Int, value: Float): Void { | ||||||
|  | 		this.setFloat64(byteOffset, value, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt16LE(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt16(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint16LE(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint16(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt32LE(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt32(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint32LE(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint32(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat32LE(byteOffset: Int): FastFloat { | ||||||
|  | 		return this.getFloat32(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat64LE(byteOffset: Int): Float { | ||||||
|  | 		return this.getFloat64(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt16LE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt16(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint16LE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint16(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt32LE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt32(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint32LE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint32(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat32LE(byteOffset: Int, value: FastFloat): Void { | ||||||
|  | 		this.setFloat32(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat64LE(byteOffset: Int, value: Float): Void { | ||||||
|  | 		this.setFloat64(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt16BE(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt16(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint16BE(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint16(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt32BE(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt32(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint32BE(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint32(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat32BE(byteOffset: Int): FastFloat { | ||||||
|  | 		return this.getFloat32(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat64BE(byteOffset: Int): Float { | ||||||
|  | 		return this.getFloat64(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt16BE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt16(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint16BE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint16(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt32BE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt32(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint32BE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint32(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat32BE(byteOffset: Int, value: FastFloat): Void { | ||||||
|  | 		this.setFloat32(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat64BE(byteOffset: Int, value: Float): Void { | ||||||
|  | 		this.setFloat64(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function subarray(start: Int, ?end: Int): ByteArray { | ||||||
|  | 		return new ByteArray(buffer, start, end != null ? end - start : null); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								Kha/Backends/HTML5-Worker/kha/arrays/ByteBuffer.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Kha/Backends/HTML5-Worker/kha/arrays/ByteBuffer.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | package kha.arrays; | ||||||
|  |  | ||||||
|  | import js.lib.ArrayBuffer; | ||||||
|  |  | ||||||
|  | @:forward | ||||||
|  | abstract ByteBuffer(ArrayBuffer) from ArrayBuffer to ArrayBuffer { | ||||||
|  | 	public static function create(length: Int): ByteBuffer { | ||||||
|  | 		return new ByteBuffer(length); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function new(length: Int) { | ||||||
|  | 		this = new ArrayBuffer(length); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								Kha/Backends/HTML5-Worker/kha/audio1/Audio.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Kha/Backends/HTML5-Worker/kha/audio1/Audio.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | package kha.audio1; | ||||||
|  |  | ||||||
|  | class Audio { | ||||||
|  | 	public static function play(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel { | ||||||
|  | 		Worker.postMessage({command: 'playSound', id: cast(sound, kha.html5worker.Sound)._id, loop: loop}); | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function stream(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel { | ||||||
|  | 		Worker.postMessage({command: 'streamSound', id: cast(sound, kha.html5worker.Sound)._id, loop: loop}); | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								Kha/Backends/HTML5-Worker/kha/audio2/Audio.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Kha/Backends/HTML5-Worker/kha/audio2/Audio.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | package kha.audio2; | ||||||
|  |  | ||||||
|  | import kha.Sound; | ||||||
|  |  | ||||||
|  | class Audio { | ||||||
|  | 	public static var disableGcInteractions = false; | ||||||
|  | 	public static var samplesPerSecond: Int; | ||||||
|  | 	public static var audioCallback: Int->Buffer->Void; | ||||||
|  |  | ||||||
|  | 	public static function stream(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/CubeMap.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/CubeMap.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  |  | ||||||
|  | class CubeMap implements Canvas implements Resource { | ||||||
|  | 	public static function createRenderTarget(size: Int, format: TextureFormat, depthStencil: DepthStencilFormat = NoDepthAndStencil): CubeMap { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	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; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return 512; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return 512; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var g1(get, never): kha.graphics1.Graphics; | ||||||
|  | 	public var g2(get, never): kha.graphics2.Graphics; | ||||||
|  | 	public var g4(get, never): kha.graphics4.Graphics; | ||||||
|  |  | ||||||
|  | 	function get_g1(): kha.graphics1.Graphics { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function get_g2(): kha.graphics2.Graphics { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function get_g4(): kha.graphics4.Graphics { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/FragmentShader.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/FragmentShader.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | class FragmentShader { | ||||||
|  | 	public var sources: Array<String>; | ||||||
|  | 	public var shader: Dynamic; | ||||||
|  | 	public var files: Array<String>; | ||||||
|  |  | ||||||
|  | 	public function new(sources: Array<Blob>, files: Array<String>) { | ||||||
|  | 		this.sources = []; | ||||||
|  | 		for (source in sources) { | ||||||
|  | 			this.sources.push(source.toString()); | ||||||
|  | 		} | ||||||
|  | 		this.shader = null; | ||||||
|  | 		this.files = files; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromSource(source: String): FragmentShader { | ||||||
|  | 		var shader = new FragmentShader([], ["runtime-string"]); | ||||||
|  | 		shader.sources.push(source); | ||||||
|  | 		return shader; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		shader = null; | ||||||
|  | 		sources = null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/IndexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/IndexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import kha.arrays.Uint32Array; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  |  | ||||||
|  | class IndexBuffer { | ||||||
|  | 	static var lastId: Int = -1; | ||||||
|  |  | ||||||
|  | 	public var _id: Int; | ||||||
|  | 	public var _data: Uint32Array; | ||||||
|  |  | ||||||
|  | 	var mySize: Int; | ||||||
|  | 	var usage: Usage; | ||||||
|  | 	var lockStart: Int = 0; | ||||||
|  | 	var lockEnd: Int = 0; | ||||||
|  |  | ||||||
|  | 	public function new(indexCount: Int, usage: Usage, canRead: Bool = false) { | ||||||
|  | 		this.usage = usage; | ||||||
|  | 		mySize = indexCount; | ||||||
|  | 		_data = new Uint32Array(indexCount); | ||||||
|  | 		_id = ++lastId; | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'createIndexBuffer', | ||||||
|  | 			id: _id, | ||||||
|  | 			size: indexCount, | ||||||
|  | 			usage: usage | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		_data = null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function lock(?start: Int, ?count: Int): Uint32Array { | ||||||
|  | 		lockStart = start != null ? start : 0; | ||||||
|  | 		lockEnd = count != null ? start + count : mySize; | ||||||
|  | 		return _data.subarray(lockStart, lockEnd); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(?count: Int): Void { | ||||||
|  | 		if (count != null) | ||||||
|  | 			lockEnd = lockStart + count; | ||||||
|  | 		Worker.postMessage({command: 'updateIndexBuffer', id: _id, data: _data.subarray(lockStart, lockEnd).buffer}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function set(): Void {} | ||||||
|  |  | ||||||
|  | 	public function count(): Int { | ||||||
|  | 		return mySize; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										117
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/PipelineState.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/PipelineState.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,117 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import kha.graphics4.FragmentShader; | ||||||
|  | import kha.graphics4.VertexData; | ||||||
|  | import kha.graphics4.VertexShader; | ||||||
|  | import kha.graphics4.VertexStructure; | ||||||
|  |  | ||||||
|  | class PipelineState extends PipelineStateBase { | ||||||
|  | 	static var lastId: Int = -1; | ||||||
|  |  | ||||||
|  | 	public var _id: Int; | ||||||
|  |  | ||||||
|  | 	var textures: Array<String>; | ||||||
|  | 	var textureValues: Array<Dynamic>; | ||||||
|  |  | ||||||
|  | 	public function new() { | ||||||
|  | 		super(); | ||||||
|  | 		_id = ++lastId; | ||||||
|  | 		textures = new Array<String>(); | ||||||
|  | 		textureValues = new Array<Dynamic>(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void {} | ||||||
|  |  | ||||||
|  | 	public function compile(): Void { | ||||||
|  | 		var index = 0; | ||||||
|  | 		for (structure in inputLayout) { | ||||||
|  | 			for (element in structure.elements) { | ||||||
|  | 				if (element.data == VertexData.Float4x4) { | ||||||
|  | 					index += 4; | ||||||
|  | 				} | ||||||
|  | 				else { | ||||||
|  | 					++index; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var layout = new Array<Dynamic>(); | ||||||
|  | 		for (input in inputLayout) { | ||||||
|  | 			var elements = new Array<Dynamic>(); | ||||||
|  | 			for (element in input.elements) { | ||||||
|  | 				elements.push({ | ||||||
|  | 					name: element.name, | ||||||
|  | 					data: element.data | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 			layout.push({ | ||||||
|  | 				elements: elements | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var stencilValue = -1; | ||||||
|  | 		switch (stencilReferenceValue) { | ||||||
|  | 			case Static(value): | ||||||
|  | 				stencilValue = value; | ||||||
|  | 			case Dynamic: | ||||||
|  | 				stencilValue = -1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var state = { | ||||||
|  | 			cullMode: cullMode, | ||||||
|  | 			depthWrite: depthWrite, | ||||||
|  | 			depthMode: depthMode, | ||||||
|  | 			stencilFrontMode: stencilFrontMode, | ||||||
|  | 			stencilFrontBothPass: stencilFrontBothPass, | ||||||
|  | 			stencilFrontDepthFail: stencilFrontDepthFail, | ||||||
|  | 			stencilFrontFail: stencilFrontFail, | ||||||
|  | 			stencilBackMode: stencilBackMode, | ||||||
|  | 			stencilBackBothPass: stencilBackBothPass, | ||||||
|  | 			stencilBackDepthFail: stencilBackDepthFail, | ||||||
|  | 			stencilBackFail: stencilBackFail, | ||||||
|  | 			stencilReferenceValue: stencilValue, | ||||||
|  | 			stencilReadMask: stencilReadMask, | ||||||
|  | 			stencilWriteMask: stencilWriteMask, | ||||||
|  | 			blendSource: blendSource, | ||||||
|  | 			blendDestination: blendDestination, | ||||||
|  | 			alphaBlendSource: alphaBlendSource, | ||||||
|  | 			alphaBlendDestination: alphaBlendDestination, | ||||||
|  | 			colorWriteMaskRed: colorWriteMaskRed, | ||||||
|  | 			colorWriteMaskGreen: colorWriteMaskGreen, | ||||||
|  | 			colorWriteMaskBlue: colorWriteMaskBlue, | ||||||
|  | 			colorWriteMaskAlpha: colorWriteMaskAlpha, | ||||||
|  | 			conservativeRasterization: conservativeRasterization | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'compilePipeline', | ||||||
|  | 			id: _id, | ||||||
|  | 			frag: fragmentShader.files[0], | ||||||
|  | 			vert: vertexShader.files[0], | ||||||
|  | 			layout: layout, | ||||||
|  | 			state: state | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function getConstantLocation(name: String): kha.graphics4.ConstantLocation { | ||||||
|  | 		var loc = new kha.html5worker.ConstantLocation(); | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'createConstantLocation', | ||||||
|  | 			id: loc._id, | ||||||
|  | 			name: name, | ||||||
|  | 			pipeline: _id | ||||||
|  | 		}); | ||||||
|  | 		return loc; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function getTextureUnit(name: String): kha.graphics4.TextureUnit { | ||||||
|  | 		var unit = new kha.html5worker.TextureUnit(); | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'createTextureUnit', | ||||||
|  | 			id: unit._id, | ||||||
|  | 			name: name, | ||||||
|  | 			pipeline: _id | ||||||
|  | 		}); | ||||||
|  | 		return unit; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										115
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/VertexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/VertexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,115 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import kha.arrays.Float32Array; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  | import kha.graphics4.VertexStructure; | ||||||
|  | import kha.graphics4.VertexData; | ||||||
|  |  | ||||||
|  | class VertexBuffer { | ||||||
|  | 	static var lastId: Int = -1; | ||||||
|  |  | ||||||
|  | 	public var _id: Int; | ||||||
|  | 	public var _data: Float32Array; | ||||||
|  |  | ||||||
|  | 	var mySize: Int; | ||||||
|  | 	var myStride: Int; | ||||||
|  | 	var sizes: Array<Int>; | ||||||
|  | 	var offsets: Array<Int>; | ||||||
|  | 	var usage: Usage; | ||||||
|  | 	var instanceDataStepRate: Int; | ||||||
|  | 	var lockStart: Int = 0; | ||||||
|  | 	var lockCount: Int = 0; | ||||||
|  |  | ||||||
|  | 	public function new(vertexCount: Int, structure: VertexStructure, usage: Usage, instanceDataStepRate: Int = 0, canRead: Bool = false) { | ||||||
|  | 		this.usage = usage; | ||||||
|  | 		this.instanceDataStepRate = instanceDataStepRate; | ||||||
|  | 		mySize = vertexCount; | ||||||
|  | 		myStride = 0; | ||||||
|  | 		for (element in structure.elements) { | ||||||
|  | 			myStride += VertexStructure.dataByteSize(element.data); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		_data = new Float32Array(Std.int(vertexCount * myStride / 4)); | ||||||
|  |  | ||||||
|  | 		sizes = new Array<Int>(); | ||||||
|  | 		offsets = new Array<Int>(); | ||||||
|  | 		sizes[structure.elements.length - 1] = 0; | ||||||
|  | 		offsets[structure.elements.length - 1] = 0; | ||||||
|  |  | ||||||
|  | 		var offset = 0; | ||||||
|  | 		var index = 0; | ||||||
|  | 		for (element in structure.elements) { | ||||||
|  | 			var size = 0; | ||||||
|  | 			size += Std.int(VertexStructure.dataByteSize(element.data) / 4); | ||||||
|  | 			sizes[index] = size; | ||||||
|  | 			offsets[index] = offset; | ||||||
|  | 			offset += VertexStructure.dataByteSize(element.data); | ||||||
|  | 			++index; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		_id = ++lastId; | ||||||
|  | 		var elements = new Array<Dynamic>(); | ||||||
|  | 		for (element in structure.elements) { | ||||||
|  | 			elements.push({ | ||||||
|  | 				name: element.name, | ||||||
|  | 				data: element.data | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'createVertexBuffer', | ||||||
|  | 			id: _id, | ||||||
|  | 			size: vertexCount, | ||||||
|  | 			structure: {elements: elements}, | ||||||
|  | 			usage: usage | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		_data = null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function lock(?start: Int, ?count: Int): Float32Array { | ||||||
|  | 		lockStart = start != null ? start : 0; | ||||||
|  | 		lockCount = count != null ? count : mySize; | ||||||
|  | 		return _data.subarray(Std.int(lockStart * stride() / 4), Std.int((lockStart + lockCount) * stride() / 4)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(?count: Int): Void { | ||||||
|  | 		if (count != null) | ||||||
|  | 			lockCount = count; | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'updateVertexBuffer', | ||||||
|  | 			id: _id, | ||||||
|  | 			data: _data.subarray(Std.int(lockStart * stride() / 4), Std.int((lockStart + lockCount) * stride() / 4)).buffer, | ||||||
|  | 			start: lockStart, | ||||||
|  | 			count: lockCount | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function stride(): Int { | ||||||
|  | 		return myStride; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function count(): Int { | ||||||
|  | 		return mySize; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function set(offset: Int): Int { | ||||||
|  | 		var attributesOffset = 0; | ||||||
|  | 		for (i in 0...sizes.length) { | ||||||
|  | 			if (sizes[i] > 4) { | ||||||
|  | 				var size = sizes[i]; | ||||||
|  | 				var addonOffset = 0; | ||||||
|  | 				while (size > 0) { | ||||||
|  | 					size -= 4; | ||||||
|  | 					addonOffset += 4 * 4; | ||||||
|  | 					++attributesOffset; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				++attributesOffset; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return attributesOffset; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/VertexShader.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Kha/Backends/HTML5-Worker/kha/graphics4/VertexShader.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | class VertexShader { | ||||||
|  | 	public var sources: Array<String>; | ||||||
|  | 	public var shader: Dynamic; | ||||||
|  | 	public var files: Array<String>; | ||||||
|  |  | ||||||
|  | 	public function new(sources: Array<Blob>, files: Array<String>) { | ||||||
|  | 		this.sources = []; | ||||||
|  | 		for (source in sources) { | ||||||
|  | 			this.sources.push(source.toString()); | ||||||
|  | 		} | ||||||
|  | 		this.shader = null; | ||||||
|  | 		this.files = files; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromSource(source: String): VertexShader { | ||||||
|  | 		var shader = new VertexShader([], ["runtime-string"]); | ||||||
|  | 		shader.sources.push(source); | ||||||
|  | 		return shader; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		shader = null; | ||||||
|  | 		sources = null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -0,0 +1,11 @@ | |||||||
|  | package kha.html5worker; | ||||||
|  |  | ||||||
|  | class ConstantLocation implements kha.graphics4.ConstantLocation { | ||||||
|  | 	static var lastId: Int = -1; | ||||||
|  |  | ||||||
|  | 	public var _id: Int; | ||||||
|  |  | ||||||
|  | 	public function new() { | ||||||
|  | 		_id = ++lastId; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										345
									
								
								Kha/Backends/HTML5-Worker/kha/html5worker/Graphics.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										345
									
								
								Kha/Backends/HTML5-Worker/kha/html5worker/Graphics.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,345 @@ | |||||||
|  | package kha.html5worker; | ||||||
|  |  | ||||||
|  | import kha.arrays.Float32Array; | ||||||
|  | import kha.Canvas; | ||||||
|  | import kha.graphics4.IndexBuffer; | ||||||
|  | import kha.graphics4.MipMapFilter; | ||||||
|  | import kha.graphics4.PipelineState; | ||||||
|  | import kha.graphics4.TextureAddressing; | ||||||
|  | import kha.graphics4.TextureFilter; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  | import kha.graphics4.VertexBuffer; | ||||||
|  | import kha.graphics4.VertexStructure; | ||||||
|  | import kha.math.FastMatrix3; | ||||||
|  | import kha.math.FastMatrix4; | ||||||
|  | import kha.math.FastVector2; | ||||||
|  | import kha.math.FastVector3; | ||||||
|  | import kha.math.FastVector4; | ||||||
|  |  | ||||||
|  | class Graphics implements kha.graphics4.Graphics { | ||||||
|  | 	var renderTarget: Image; | ||||||
|  |  | ||||||
|  | 	public function new(renderTarget: Canvas = null) { | ||||||
|  | 		if (Std.isOfType(renderTarget, Image)) { | ||||||
|  | 			this.renderTarget = cast renderTarget; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function begin(additionalRenderTargets: Array<Canvas> = null): Void { | ||||||
|  | 		Worker.postMessage({command: 'begin', renderTarget: renderTarget == null ? -1 : renderTarget._rtid}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function beginFace(face: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function beginEye(eye: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function end(): Void { | ||||||
|  | 		Worker.postMessage({command: 'end'}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function flush(): Void {} | ||||||
|  |  | ||||||
|  | 	public function vsynced(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function refreshRate(): Int { | ||||||
|  | 		return 60; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function clear(?color: Color, ?depth: Float, ?stencil: Int): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'clear', | ||||||
|  | 			color: color == null ? null : color.value, | ||||||
|  | 			hasDepth: depth != null, | ||||||
|  | 			depth: depth, | ||||||
|  | 			hasStencil: stencil != null, | ||||||
|  | 			stencil: stencil | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function viewport(x: Int, y: Int, width: Int, height: Int): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'viewport', | ||||||
|  | 			x: x, | ||||||
|  | 			y: y, | ||||||
|  | 			width: width, | ||||||
|  | 			height: height | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function createVertexBuffer(vertexCount: Int, structure: VertexStructure, usage: Usage, canRead: Bool = false): kha.graphics4.VertexBuffer { | ||||||
|  | 		return new VertexBuffer(vertexCount, structure, usage); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVertexBuffer(vertexBuffer: kha.graphics4.VertexBuffer): Void { | ||||||
|  | 		Worker.postMessage({command: 'setVertexBuffer', id: vertexBuffer._id}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVertexBuffers(vertexBuffers: Array<kha.graphics4.VertexBuffer>): Void { | ||||||
|  | 		var ids = new Array<Int>(); | ||||||
|  | 		for (buffer in vertexBuffers) { | ||||||
|  | 			ids.push(buffer._id); | ||||||
|  | 		} | ||||||
|  | 		Worker.postMessage({command: 'setVertexBuffers', ids: ids}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function createIndexBuffer(indexCount: Int, usage: Usage, canRead: Bool = false): kha.graphics4.IndexBuffer { | ||||||
|  | 		return new IndexBuffer(indexCount, usage); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setIndexBuffer(indexBuffer: kha.graphics4.IndexBuffer): Void { | ||||||
|  | 		Worker.postMessage({command: 'setIndexBuffer', id: indexBuffer._id}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setTexture(stage: kha.graphics4.TextureUnit, texture: kha.Image): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setTexture', | ||||||
|  | 			stage: cast(stage, kha.html5worker.TextureUnit)._id, | ||||||
|  | 			texture: texture == null ? -1 : texture.id, | ||||||
|  | 			renderTarget: texture == null ? -1 : texture._rtid | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setTextureDepth(stage: kha.graphics4.TextureUnit, texture: kha.Image): Void {} | ||||||
|  |  | ||||||
|  | 	public function setTextureArray(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {} | ||||||
|  |  | ||||||
|  | 	public function setVideoTexture(unit: kha.graphics4.TextureUnit, texture: kha.Video): Void {} | ||||||
|  |  | ||||||
|  | 	public function setImageTexture(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {} | ||||||
|  |  | ||||||
|  | 	public function setTextureParameters(texunit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing, | ||||||
|  | 			minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setTextureParameters', | ||||||
|  | 			id: cast(texunit, kha.html5worker.TextureUnit)._id, | ||||||
|  | 			uAddressing: uAddressing, | ||||||
|  | 			vAddressing: vAddressing, | ||||||
|  | 			minificationFilter: minificationFilter, | ||||||
|  | 			magnificationFilter: magnificationFilter, | ||||||
|  | 			mipmapFilter: mipmapFilter | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setTexture3DParameters(texunit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing, | ||||||
|  | 		wAddressing: TextureAddressing, minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void {} | ||||||
|  |  | ||||||
|  | 	public function setTextureCompareMode(texunit: kha.graphics4.TextureUnit, enabled: Bool): Void {} | ||||||
|  |  | ||||||
|  | 	public function setCubeMapCompareMode(texunit: kha.graphics4.TextureUnit, enabled: Bool): Void {} | ||||||
|  |  | ||||||
|  | 	public function setCubeMap(stage: kha.graphics4.TextureUnit, cubeMap: kha.graphics4.CubeMap): Void {} | ||||||
|  |  | ||||||
|  | 	public function setCubeMapDepth(stage: kha.graphics4.TextureUnit, cubeMap: kha.graphics4.CubeMap): Void {} | ||||||
|  |  | ||||||
|  | 	public function setPipeline(pipe: PipelineState): Void { | ||||||
|  | 		Worker.postMessage({command: 'setPipeline', id: pipe._id}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setStencilReferenceValue(value: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function setBool(location: kha.graphics4.ConstantLocation, value: Bool): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setBool', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			value: value | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setInt(location: kha.graphics4.ConstantLocation, value: Int): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setInt', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			value: value | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setInt2(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setInt2', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			_0: value1, | ||||||
|  | 			_1: value2 | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setInt3(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int, value3: Int): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setInt3', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			_0: value1, | ||||||
|  | 			_1: value2, | ||||||
|  | 			_2: value3 | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setInt4(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int, value3: Int, value4: Int): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setInt4', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			_0: value1, | ||||||
|  | 			_1: value2, | ||||||
|  | 			_2: value3, | ||||||
|  | 			_3: value4 | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setInts(location: kha.graphics4.ConstantLocation, values: kha.arrays.Int32Array): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setInts', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			values: values | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setFloat(location: kha.graphics4.ConstantLocation, value: FastFloat): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setFloat', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			value: value | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setFloat2(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setFloat2', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			_0: value1, | ||||||
|  | 			_1: value2 | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setFloat3(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setFloat3', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			_0: value1, | ||||||
|  | 			_1: value2, | ||||||
|  | 			_2: value3 | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setFloat4(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat, value4: FastFloat): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setFloat4', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			_0: value1, | ||||||
|  | 			_1: value2, | ||||||
|  | 			_2: value3, | ||||||
|  | 			_3: value4 | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setFloats(location: kha.graphics4.ConstantLocation, values: Float32Array): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setFloats', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			values: values | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVector2(location: kha.graphics4.ConstantLocation, value: FastVector2): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setVector2', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			x: value.x, | ||||||
|  | 			y: value.y | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVector3(location: kha.graphics4.ConstantLocation, value: FastVector3): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setVector3', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			x: value.x, | ||||||
|  | 			y: value.y, | ||||||
|  | 			z: value.z | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVector4(location: kha.graphics4.ConstantLocation, value: FastVector4): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setVector4', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			x: value.x, | ||||||
|  | 			y: value.y, | ||||||
|  | 			z: value.z, | ||||||
|  | 			w: value.w | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setMatrix(location: kha.graphics4.ConstantLocation, matrix: FastMatrix4): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setMatrix4', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			_00: matrix._00, | ||||||
|  | 			_01: matrix._01, | ||||||
|  | 			_02: matrix._02, | ||||||
|  | 			_03: matrix._03, | ||||||
|  | 			_10: matrix._10, | ||||||
|  | 			_11: matrix._11, | ||||||
|  | 			_12: matrix._12, | ||||||
|  | 			_13: matrix._13, | ||||||
|  | 			_20: matrix._20, | ||||||
|  | 			_21: matrix._21, | ||||||
|  | 			_22: matrix._22, | ||||||
|  | 			_23: matrix._23, | ||||||
|  | 			_30: matrix._30, | ||||||
|  | 			_31: matrix._31, | ||||||
|  | 			_32: matrix._32, | ||||||
|  | 			_33: matrix._33 | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setMatrix3(location: kha.graphics4.ConstantLocation, matrix: FastMatrix3): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'setMatrix3', | ||||||
|  | 			location: cast(location, kha.html5worker.ConstantLocation)._id, | ||||||
|  | 			_00: matrix._00, | ||||||
|  | 			_01: matrix._01, | ||||||
|  | 			_02: matrix._02, | ||||||
|  | 			_10: matrix._10, | ||||||
|  | 			_11: matrix._11, | ||||||
|  | 			_12: matrix._12, | ||||||
|  | 			_20: matrix._20, | ||||||
|  | 			_21: matrix._21, | ||||||
|  | 			_22: matrix._22 | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function drawIndexedVertices(start: Int = 0, count: Int = -1): Void { | ||||||
|  | 		Worker.postMessage({command: 'drawIndexedVertices', start: start, count: count}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function scissor(x: Int, y: Int, width: Int, height: Int): Void { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'scissor', | ||||||
|  | 			x: x, | ||||||
|  | 			y: y, | ||||||
|  | 			width: width, | ||||||
|  | 			height: height | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function disableScissor(): Void { | ||||||
|  | 		Worker.postMessage({command: 'disableScissor'}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function drawIndexedVerticesInstanced(instanceCount: Int, start: Int = 0, count: Int = -1) { | ||||||
|  | 		Worker.postMessage({ | ||||||
|  | 			command: 'drawIndexedVerticesInstanced', | ||||||
|  | 			instanceCount: instanceCount, | ||||||
|  | 			start: start, | ||||||
|  | 			count: count | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function instancedRenderingAvailable(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function maxBoundTextures(): Int { | ||||||
|  | 		return 16; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								Kha/Backends/HTML5-Worker/kha/html5worker/Sound.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Kha/Backends/HTML5-Worker/kha/html5worker/Sound.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | package kha.html5worker; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import haxe.ds.Vector; | ||||||
|  |  | ||||||
|  | class Sound extends kha.Sound { | ||||||
|  | 	public var _id: Int; | ||||||
|  | 	public var _callback: Void->Void; | ||||||
|  |  | ||||||
|  | 	public function new(id: Int) { | ||||||
|  | 		super(); | ||||||
|  | 		this._id = id; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function uncompress(done: Void->Void): Void { | ||||||
|  | 		compressedData = null; | ||||||
|  | 		Worker.postMessage({command: 'uncompressSound', id: _id}); | ||||||
|  | 		_callback = done; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function unload() { | ||||||
|  | 		compressedData = null; | ||||||
|  | 		uncompressedData = null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								Kha/Backends/HTML5-Worker/kha/html5worker/TextureUnit.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Kha/Backends/HTML5-Worker/kha/html5worker/TextureUnit.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | package kha.html5worker; | ||||||
|  |  | ||||||
|  | class TextureUnit implements kha.graphics4.TextureUnit { | ||||||
|  | 	static var lastId: Int = -1; | ||||||
|  |  | ||||||
|  | 	public var _id: Int; | ||||||
|  |  | ||||||
|  | 	public function new() { | ||||||
|  | 		_id = ++lastId; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								Kha/Backends/HTML5/kha/Blob.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Kha/Backends/HTML5/kha/Blob.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | typedef Blob = kha.internal.BytesBlob; | ||||||
							
								
								
									
										234
									
								
								Kha/Backends/HTML5/kha/CanvasImage.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								Kha/Backends/HTML5/kha/CanvasImage.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,234 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import js.Browser; | ||||||
|  | import js.lib.Uint8Array; | ||||||
|  | import js.html.VideoElement; | ||||||
|  | import js.html.webgl.GL; | ||||||
|  | import kha.graphics4.TextureFormat; | ||||||
|  | import kha.js.CanvasGraphics; | ||||||
|  |  | ||||||
|  | class CanvasImage extends Image { | ||||||
|  | 	public var image: Dynamic; | ||||||
|  | 	public var video: VideoElement; | ||||||
|  |  | ||||||
|  | 	static var context: Dynamic; | ||||||
|  |  | ||||||
|  | 	var data: Dynamic; | ||||||
|  |  | ||||||
|  | 	var myWidth: Int; | ||||||
|  | 	var myHeight: Int; | ||||||
|  | 	var myFormat: TextureFormat; | ||||||
|  | 	var renderTarget: Bool; | ||||||
|  |  | ||||||
|  | 	public var frameBuffer: Dynamic; | ||||||
|  |  | ||||||
|  | 	var graphics1: kha.graphics1.Graphics; | ||||||
|  | 	var g2canvas: CanvasGraphics = null; | ||||||
|  |  | ||||||
|  | 	public static function init() { | ||||||
|  | 		var canvas: Dynamic = Browser.document.createElement("canvas"); | ||||||
|  | 		if (canvas != null) { | ||||||
|  | 			context = canvas.getContext("2d"); | ||||||
|  | 			canvas.width = 2048; | ||||||
|  | 			canvas.height = 2048; | ||||||
|  | 			context.globalCompositeOperation = "copy"; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function new(width: Int, height: Int, format: TextureFormat, renderTarget: Bool) { | ||||||
|  | 		myWidth = width; | ||||||
|  | 		myHeight = height; | ||||||
|  | 		myFormat = format; | ||||||
|  | 		this.renderTarget = renderTarget; | ||||||
|  | 		image = null; | ||||||
|  | 		video = null; | ||||||
|  | 		if (renderTarget) | ||||||
|  | 			createTexture(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_g1(): kha.graphics1.Graphics { | ||||||
|  | 		if (graphics1 == null) { | ||||||
|  | 			graphics1 = new kha.graphics2.Graphics1(this); | ||||||
|  | 		} | ||||||
|  | 		return graphics1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_g2(): kha.graphics2.Graphics { | ||||||
|  | 		if (g2canvas == null) { | ||||||
|  | 			var canvas: Dynamic = Browser.document.createElement("canvas"); | ||||||
|  | 			image = canvas; | ||||||
|  | 			var context = canvas.getContext("2d"); | ||||||
|  | 			canvas.width = width; | ||||||
|  | 			canvas.height = height; | ||||||
|  | 			g2canvas = new CanvasGraphics(context); | ||||||
|  | 		} | ||||||
|  | 		return g2canvas; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_g4(): kha.graphics4.Graphics { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_width(): Int { | ||||||
|  | 		return myWidth; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_height(): Int { | ||||||
|  | 		return myHeight; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_format(): TextureFormat { | ||||||
|  | 		return myFormat; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_realWidth(): Int { | ||||||
|  | 		return myWidth; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_realHeight(): Int { | ||||||
|  | 		return myHeight; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_stride(): Int { | ||||||
|  | 		return myFormat == TextureFormat.RGBA32 ? 4 * width : width; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function isOpaque(x: Int, y: Int): Bool { | ||||||
|  | 		if (data == null) { | ||||||
|  | 			if (context == null) | ||||||
|  | 				return true; | ||||||
|  | 			else | ||||||
|  | 				createImageData(); | ||||||
|  | 		} | ||||||
|  | 		return (data.data[y * Std.int(image.width) * 4 + x * 4 + 3] != 0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function at(x: Int, y: Int): Color { | ||||||
|  | 		if (data == null) { | ||||||
|  | 			if (context == null) | ||||||
|  | 				return Color.Black; | ||||||
|  | 			else | ||||||
|  | 				createImageData(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var r = data.data[y * Std.int(image.width) * 4 + x * 4]; | ||||||
|  | 		var g = data.data[y * Std.int(image.width) * 4 + x * 4 + 1]; | ||||||
|  | 		var b = data.data[y * Std.int(image.width) * 4 + x * 4 + 2]; | ||||||
|  | 		var a = data.data[y * Std.int(image.width) * 4 + x * 4 + 3]; | ||||||
|  |  | ||||||
|  | 		return Color.fromValue((a << 24) | (r << 16) | (g << 8) | b); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function createImageData() { | ||||||
|  | 		context.strokeStyle = "rgba(0,0,0,0)"; | ||||||
|  | 		context.fillStyle = "rgba(0,0,0,0)"; | ||||||
|  | 		context.fillRect(0, 0, image.width, image.height); | ||||||
|  | 		context.drawImage(image, 0, 0, image.width, image.height, 0, 0, image.width, image.height); | ||||||
|  | 		data = context.getImageData(0, 0, image.width, image.height); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var texture: Dynamic; | ||||||
|  |  | ||||||
|  | 	static function upperPowerOfTwo(v: Int): Int { | ||||||
|  | 		v--; | ||||||
|  | 		v |= v >>> 1; | ||||||
|  | 		v |= v >>> 2; | ||||||
|  | 		v |= v >>> 4; | ||||||
|  | 		v |= v >>> 8; | ||||||
|  | 		v |= v >>> 16; | ||||||
|  | 		v++; | ||||||
|  | 		return v; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function createTexture() { | ||||||
|  | 		if (SystemImpl.gl == null) | ||||||
|  | 			return; | ||||||
|  | 		texture = SystemImpl.gl.createTexture(); | ||||||
|  | 		// texture.image = image; | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); | ||||||
|  | 		// Sys.gl.pixelStorei(Sys.gl.UNPACK_FLIP_Y_WEBGL, true); | ||||||
|  |  | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR); | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); | ||||||
|  | 		if (renderTarget) { | ||||||
|  | 			frameBuffer = SystemImpl.gl.createFramebuffer(); | ||||||
|  | 			SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  | 			SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, realWidth, realHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null); | ||||||
|  | 			SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, texture, 0); | ||||||
|  | 			SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null); | ||||||
|  | 		} | ||||||
|  | 		else if (video != null) | ||||||
|  | 			SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, video); | ||||||
|  | 		else | ||||||
|  | 			SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, image); | ||||||
|  | 		// Sys.gl.generateMipmap(Sys.gl.TEXTURE_2D); | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_2D, null); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function set(stage: Int): Void { | ||||||
|  | 		SystemImpl.gl.activeTexture(GL.TEXTURE0 + stage); | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); | ||||||
|  | 		if (video != null) | ||||||
|  | 			SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, video); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var bytes: Bytes; | ||||||
|  |  | ||||||
|  | 	override public function lock(level: Int = 0): Bytes { | ||||||
|  | 		bytes = Bytes.alloc(myFormat == TextureFormat.RGBA32 ? 4 * width * height : width * height); | ||||||
|  | 		return bytes; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function unlock(): Void { | ||||||
|  | 		data = null; | ||||||
|  |  | ||||||
|  | 		if (SystemImpl.gl != null) { | ||||||
|  | 			texture = SystemImpl.gl.createTexture(); | ||||||
|  | 			// texture.image = image; | ||||||
|  | 			SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); | ||||||
|  | 			// Sys.gl.pixelStorei(Sys.gl.UNPACK_FLIP_Y_WEBGL, true); | ||||||
|  |  | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR); | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); | ||||||
|  | 			SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.LUMINANCE, width, height, 0, GL.LUMINANCE, GL.UNSIGNED_BYTE, new Uint8Array(bytes.getData())); | ||||||
|  |  | ||||||
|  | 			if (SystemImpl.ie && SystemImpl.gl.getError() == 1282) { // no LUMINANCE support in IE11 | ||||||
|  | 				var rgbaBytes = Bytes.alloc(width * height * 4); | ||||||
|  | 				for (y in 0...height) | ||||||
|  | 					for (x in 0...width) { | ||||||
|  | 						var value = bytes.get(y * width + x); | ||||||
|  | 						rgbaBytes.set(y * width * 4 + x * 4 + 0, value); | ||||||
|  | 						rgbaBytes.set(y * width * 4 + x * 4 + 1, value); | ||||||
|  | 						rgbaBytes.set(y * width * 4 + x * 4 + 2, value); | ||||||
|  | 						rgbaBytes.set(y * width * 4 + x * 4 + 3, 255); | ||||||
|  | 					} | ||||||
|  | 				SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, width, height, 0, GL.RGBA, GL.UNSIGNED_BYTE, new Uint8Array(rgbaBytes.getData())); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Sys.gl.generateMipmap(Sys.gl.TEXTURE_2D); | ||||||
|  | 			SystemImpl.gl.bindTexture(GL.TEXTURE_2D, null); | ||||||
|  | 			bytes = null; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function getPixels(): Bytes { | ||||||
|  | 		@:privateAccess var context: js.html.CanvasRenderingContext2D = g2canvas.canvas; | ||||||
|  | 		var imageData: js.html.ImageData = context.getImageData(0, 0, width, height); | ||||||
|  | 		var bytes = Bytes.alloc(imageData.data.length); | ||||||
|  | 		for (i in 0...imageData.data.length) { | ||||||
|  | 			bytes.set(i, imageData.data[i]); | ||||||
|  | 		} | ||||||
|  | 		return bytes; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function unload(): Void { | ||||||
|  | 		image = null; | ||||||
|  | 		video = null; | ||||||
|  | 		data = null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										86
									
								
								Kha/Backends/HTML5/kha/Display.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								Kha/Backends/HTML5/kha/Display.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import js.Browser; | ||||||
|  |  | ||||||
|  | class Display { | ||||||
|  | 	static var instance: Display = new Display(); | ||||||
|  |  | ||||||
|  | 	function new() {} | ||||||
|  |  | ||||||
|  | 	public static function init(): Void {} | ||||||
|  |  | ||||||
|  | 	public static var primary(get, never): Display; | ||||||
|  |  | ||||||
|  | 	static function get_primary(): Display { | ||||||
|  | 		return instance; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var all(get, never): Array<Display>; | ||||||
|  |  | ||||||
|  | 	static function get_all(): Array<Display> { | ||||||
|  | 		return [primary]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var available(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	function get_available(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var name(get, never): String; | ||||||
|  |  | ||||||
|  | 	function get_name(): String { | ||||||
|  | 		return "Display"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var x(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_x(): Int { | ||||||
|  | 		return js.Browser.window.screen.left; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var y(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_y(): Int { | ||||||
|  | 		return js.Browser.window.screen.top; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var width(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return js.Browser.window.screen.width; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return js.Browser.window.screen.height; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var frequency(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_frequency(): Int { | ||||||
|  | 		return SystemImpl.estimatedRefreshRate; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var pixelsPerInch(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_pixelsPerInch(): Int { | ||||||
|  | 		var dpiElement = Browser.document.createElement("div"); | ||||||
|  | 		dpiElement.style.position = "absolute"; | ||||||
|  | 		dpiElement.style.width = "1in"; | ||||||
|  | 		dpiElement.style.height = "1in"; | ||||||
|  | 		dpiElement.style.left = "-100%"; | ||||||
|  | 		dpiElement.style.top = "-100%"; | ||||||
|  | 		Browser.document.body.appendChild(dpiElement); | ||||||
|  | 		var dpi: Int = dpiElement.offsetHeight; | ||||||
|  | 		dpiElement.remove(); | ||||||
|  | 		return dpi; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var modes(get, never): Array<DisplayMode>; | ||||||
|  |  | ||||||
|  | 	function get_modes(): Array<DisplayMode> { | ||||||
|  | 		return []; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								Kha/Backends/HTML5/kha/EnvironmentVariables.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								Kha/Backends/HTML5/kha/EnvironmentVariables.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import js.Browser; | ||||||
|  |  | ||||||
|  | class EnvironmentVariables { | ||||||
|  | 	public static function get(name: String): String { | ||||||
|  | 		try { | ||||||
|  | 			var query = Browser.location.href.substr(Browser.location.href.indexOf("?") + 1); | ||||||
|  | 			var parts = query.split("&"); | ||||||
|  |  | ||||||
|  | 			for (part in parts) { | ||||||
|  | 				var subparts = part.split("="); | ||||||
|  | 				if (subparts[0] == name) { | ||||||
|  | 					return subparts[1]; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		catch (error:Dynamic) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								Kha/Backends/HTML5/kha/Font.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Kha/Backends/HTML5/kha/Font.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | typedef Font = kha.Kravur; | ||||||
							
								
								
									
										221
									
								
								Kha/Backends/HTML5/kha/Image.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								Kha/Backends/HTML5/kha/Image.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,221 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import js.html.ImageElement; | ||||||
|  | import js.html.CanvasElement; | ||||||
|  | import js.html.webgl.GL; | ||||||
|  | import kha.graphics4.TextureFormat; | ||||||
|  | import kha.graphics4.DepthStencilFormat; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  |  | ||||||
|  | class Image implements Canvas implements Resource { | ||||||
|  | 	public static function create(width: Int, height: Int, format: TextureFormat = null, usage: Usage = null, readable: Bool = false): Image { | ||||||
|  | 		if (format == null) | ||||||
|  | 			format = TextureFormat.RGBA32; | ||||||
|  | 		if (usage == null) | ||||||
|  | 			usage = Usage.StaticUsage; | ||||||
|  | 		if (SystemImpl.gl == null) | ||||||
|  | 			return new CanvasImage(width, height, format, false); | ||||||
|  | 		else | ||||||
|  | 			return new WebGLImage(width, height, format, false, DepthStencilFormat.NoDepthAndStencil, 1, readable); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function create3D(width: Int, height: Int, depth: Int, format: TextureFormat = null, usage: Usage = null, readable: Bool = false): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function createRenderTarget(width: Int, height: Int, format: TextureFormat = null, | ||||||
|  | 			depthStencil: DepthStencilFormat = DepthStencilFormat.NoDepthAndStencil, antiAliasingSamples: Int = 1): Image { | ||||||
|  | 		if (format == null) | ||||||
|  | 			format = TextureFormat.RGBA32; | ||||||
|  | 		if (SystemImpl.gl == null) | ||||||
|  | 			return new CanvasImage(width, height, format, true); | ||||||
|  | 		else | ||||||
|  | 			return new WebGLImage(width, height, format, true, depthStencil, antiAliasingSamples, false); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromCanvas(canvas: CanvasElement): Image { | ||||||
|  | 		if (SystemImpl.gl == null) { | ||||||
|  | 			var img = new CanvasImage(canvas.width, canvas.height, TextureFormat.RGBA32, false); | ||||||
|  | 			img.image = canvas; | ||||||
|  | 			img.createTexture(); | ||||||
|  | 			return img; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			var img = new WebGLImage(canvas.width, canvas.height, TextureFormat.RGBA32, false, DepthStencilFormat.NoDepthAndStencil, 1, false); | ||||||
|  | 			img.image = canvas; | ||||||
|  | 			img.createTexture(); | ||||||
|  | 			return img; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromImage(image: ImageElement, readable: Bool): Image { | ||||||
|  | 		if (SystemImpl.gl == null) { | ||||||
|  | 			var img = new CanvasImage(image.width, image.height, TextureFormat.RGBA32, false); | ||||||
|  | 			img.image = image; | ||||||
|  | 			img.createTexture(); | ||||||
|  | 			return img; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			var img = new WebGLImage(image.width, image.height, TextureFormat.RGBA32, false, DepthStencilFormat.NoDepthAndStencil, 1, readable); | ||||||
|  | 			img.image = image; | ||||||
|  | 			img.createTexture(); | ||||||
|  | 			return img; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromBytes(bytes: Bytes, width: Int, height: Int, format: TextureFormat = null, usage: Usage = null, readable: Bool = false): Image { | ||||||
|  | 		if (format == null) | ||||||
|  | 			format = TextureFormat.RGBA32; | ||||||
|  | 		if (usage == null) | ||||||
|  | 			usage = Usage.StaticUsage; | ||||||
|  | 		if (SystemImpl.gl != null) { | ||||||
|  | 			var img = new WebGLImage(width, height, format, false, DepthStencilFormat.NoDepthAndStencil, 1, readable); | ||||||
|  | 			img.image = img.bytesToArray(bytes); | ||||||
|  | 			img.createTexture(); | ||||||
|  | 			return img; | ||||||
|  | 		} | ||||||
|  | 		var img = new CanvasImage(width, height, format, false); | ||||||
|  | 		var g2: kha.js.CanvasGraphics = cast img.g2; | ||||||
|  | 		@:privateAccess var canvas = g2.canvas; | ||||||
|  | 		var imageData = new js.html.ImageData(new js.lib.Uint8ClampedArray(bytes.getData()), width, height); | ||||||
|  | 		canvas.putImageData(imageData, 0, 0); | ||||||
|  | 		return img; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromBytes3D(bytes: Bytes, width: Int, height: Int, depth: Int, format: TextureFormat = null, usage: Usage = null, | ||||||
|  | 			readable: Bool = false): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromEncodedBytes(bytes: Bytes, fileExtention: String, doneCallback: Image->Void, errorCallback: String->Void, | ||||||
|  | 			readable: Bool = false): Void { | ||||||
|  | 		var dataUrl = "data:image;base64," + haxe.crypto.Base64.encode(bytes); | ||||||
|  | 		var imageElement = cast(js.Browser.document.createElement("img"), ImageElement); | ||||||
|  | 		imageElement.onload = function() doneCallback(fromImage(imageElement, readable)); | ||||||
|  | 		imageElement.onerror = function() errorCallback("Image was not created"); | ||||||
|  | 		imageElement.src = dataUrl; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromVideo(video: kha.Video): Image { | ||||||
|  | 		final jsvideo: kha.js.Video = cast video; | ||||||
|  |  | ||||||
|  | 		if (SystemImpl.gl == null) { | ||||||
|  | 			var img = new CanvasImage(jsvideo.element.videoWidth, jsvideo.element.videoHeight, TextureFormat.RGBA32, false); | ||||||
|  | 			img.video = jsvideo.element; | ||||||
|  | 			img.createTexture(); | ||||||
|  | 			return img; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			var img = new WebGLImage(jsvideo.element.videoWidth, jsvideo.element.videoHeight, TextureFormat.RGBA32, false, | ||||||
|  | 				DepthStencilFormat.NoDepthAndStencil, 1, false); | ||||||
|  | 			img.video = jsvideo.element; | ||||||
|  | 			img.createTexture(); | ||||||
|  | 			return img; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var maxSize(get, never): Int; | ||||||
|  |  | ||||||
|  | 	static function get_maxSize(): Int { | ||||||
|  | 		return SystemImpl.gl == null ? 1024 * 8 : SystemImpl.gl.getParameter(GL.MAX_TEXTURE_SIZE); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var nonPow2Supported(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	static function get_nonPow2Supported(): Bool { | ||||||
|  | 		return SystemImpl.gl != null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function renderTargetsInvertedY(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function isOpaque(x: Int, y: Int): Bool { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function at(x: Int, y: Int): Color { | ||||||
|  | 		return Color.Black; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unload(): Void {} | ||||||
|  |  | ||||||
|  | 	public function lock(level: Int = 0): Bytes { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(): Void {} | ||||||
|  |  | ||||||
|  | 	public function getPixels(): Bytes { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function generateMipmaps(levels: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function setMipmaps(mipmaps: Array<Image>): Void {} | ||||||
|  |  | ||||||
|  | 	public function setDepthStencilFrom(image: Image): Void {} | ||||||
|  |  | ||||||
|  | 	public function clear(x: Int, y: Int, z: Int, width: Int, height: Int, depth: Int, color: Color): Void {} | ||||||
|  |  | ||||||
|  | 	public var width(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var depth(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_depth(): Int { | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var format(get, never): TextureFormat; | ||||||
|  |  | ||||||
|  | 	function get_format(): TextureFormat { | ||||||
|  | 		return TextureFormat.RGBA32; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var realWidth(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_realWidth(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var realHeight(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_realHeight(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var stride(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_stride(): 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 { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										236
									
								
								Kha/Backends/HTML5/kha/LoaderImpl.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								Kha/Backends/HTML5/kha/LoaderImpl.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,236 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import js.html.FileReader; | ||||||
|  | import js.Syntax; | ||||||
|  | import js.Browser; | ||||||
|  | import js.html.ImageElement; | ||||||
|  | import js.html.XMLHttpRequest; | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import kha.Blob; | ||||||
|  | import kha.js.WebAudioSound; | ||||||
|  | import kha.js.MobileWebAudioSound; | ||||||
|  | import kha.graphics4.TextureFormat; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  |  | ||||||
|  | using StringTools; | ||||||
|  |  | ||||||
|  | class LoaderImpl { | ||||||
|  | 	@:allow(kha.SystemImpl) | ||||||
|  | 	static var dropFiles = new Map<String, js.html.File>(); | ||||||
|  |  | ||||||
|  | 	public static function getImageFormats(): Array<String> { | ||||||
|  | 		return ["png", "jpg", "hdr"]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadImageFromDescription(desc: Dynamic, done: kha.Image->Void, failed: AssetError->Void) { | ||||||
|  | 		var readable = Reflect.hasField(desc, "readable") ? desc.readable : false; | ||||||
|  | 		if (StringTools.endsWith(desc.files[0], ".hdr")) { | ||||||
|  | 			loadBlobFromDescription(desc, function(blob) { | ||||||
|  | 				var hdrImage = kha.internal.HdrFormat.parse(blob.toBytes()); | ||||||
|  | 				done(Image.fromBytes(hdrImage.data.view.buffer, hdrImage.width, hdrImage.height, TextureFormat.RGBA128, | ||||||
|  | 					readable ? Usage.DynamicUsage : Usage.StaticUsage)); | ||||||
|  | 			}, failed); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			var img: ImageElement = cast Browser.document.createElement("img"); | ||||||
|  | 			img.onerror = function(event: Dynamic) failed({url: desc.files[0], error: event}); | ||||||
|  | 			img.onload = function(event: Dynamic) done(Image.fromImage(img, readable)); | ||||||
|  | 			img.crossOrigin = ""; | ||||||
|  | 			img.src = desc.files[0]; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getSoundFormats(): Array<String> { | ||||||
|  | 		var element = Browser.document.createAudioElement(); | ||||||
|  | 		var formats = new Array<String>(); | ||||||
|  | 		#if !kha_debug_html5 | ||||||
|  | 		if (element.canPlayType("audio/mp4") != "") | ||||||
|  | 			formats.push("mp4"); | ||||||
|  | 		if (element.canPlayType("audio/mp3") != "") | ||||||
|  | 			formats.push("mp3"); | ||||||
|  | 		if (element.canPlayType("audio/wav") != "") | ||||||
|  | 			formats.push("wav"); | ||||||
|  | 		#end | ||||||
|  | 		if (SystemImpl._hasWebAudio || element.canPlayType("audio/ogg") != "") | ||||||
|  | 			formats.push("ogg"); | ||||||
|  | 		return formats; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadSoundFromDescription(desc: Dynamic, done: kha.Sound->Void, failed: AssetError->Void) { | ||||||
|  | 		if (SystemImpl._hasWebAudio) { | ||||||
|  | 			#if !kha_debug_html5 | ||||||
|  | 			var element = Browser.document.createAudioElement(); | ||||||
|  | 			if (element.canPlayType("audio/mp4") != "") { | ||||||
|  | 				for (i in 0...desc.files.length) { | ||||||
|  | 					var file: String = desc.files[i]; | ||||||
|  | 					if (file.endsWith(".mp4")) { | ||||||
|  | 						new WebAudioSound(file, done, failed); | ||||||
|  | 						return; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if (element.canPlayType("audio/mp3") != "") { | ||||||
|  | 				for (i in 0...desc.files.length) { | ||||||
|  | 					var file: String = desc.files[i]; | ||||||
|  | 					if (file.endsWith(".mp3")) { | ||||||
|  | 						new WebAudioSound(file, done, failed); | ||||||
|  | 						return; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if (element.canPlayType("audio/wav") != "") { | ||||||
|  | 				for (i in 0...desc.files.length) { | ||||||
|  | 					var file: String = desc.files[i]; | ||||||
|  | 					if (file.endsWith(".wav")) { | ||||||
|  | 						new WebAudioSound(file, done, failed); | ||||||
|  | 						return; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			#end | ||||||
|  | 			for (i in 0...desc.files.length) { | ||||||
|  | 				var file: String = desc.files[i]; | ||||||
|  | 				if (file.endsWith(".ogg")) { | ||||||
|  | 					new WebAudioSound(file, done, failed); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			failed({ | ||||||
|  | 				url: desc.files.join(","), | ||||||
|  | 				error: "Unable to find sound files with supported audio formats", | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 		else if (SystemImpl.mobile) { | ||||||
|  | 			var element = Browser.document.createAudioElement(); | ||||||
|  | 			if (element.canPlayType("audio/mp4") != "") { | ||||||
|  | 				for (i in 0...desc.files.length) { | ||||||
|  | 					var file: String = desc.files[i]; | ||||||
|  | 					if (file.endsWith(".mp4")) { | ||||||
|  | 						new MobileWebAudioSound(file, done, failed); | ||||||
|  | 						return; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if (element.canPlayType("audio/mp3") != "") { | ||||||
|  | 				for (i in 0...desc.files.length) { | ||||||
|  | 					var file: String = desc.files[i]; | ||||||
|  | 					if (file.endsWith(".mp3")) { | ||||||
|  | 						new MobileWebAudioSound(file, done, failed); | ||||||
|  | 						return; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if (element.canPlayType("audio/wav") != "") { | ||||||
|  | 				for (i in 0...desc.files.length) { | ||||||
|  | 					var file: String = desc.files[i]; | ||||||
|  | 					if (file.endsWith(".wav")) { | ||||||
|  | 						new MobileWebAudioSound(file, done, failed); | ||||||
|  | 						return; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			for (i in 0...desc.files.length) { | ||||||
|  | 				var file: String = desc.files[i]; | ||||||
|  | 				if (file.endsWith(".ogg")) { | ||||||
|  | 					new MobileWebAudioSound(file, done, failed); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			failed({ | ||||||
|  | 				url: desc.files.join(","), | ||||||
|  | 				error: "Unable to find sound files with supported audio formats", | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			new kha.js.Sound(desc.files, done, failed); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function getVideoFormats(): Array<String> { | ||||||
|  | 		#if kha_debug_html5 | ||||||
|  | 		return ["webm"]; | ||||||
|  | 		#else | ||||||
|  | 		return ["mp4", "webm"]; | ||||||
|  | 		#end | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadVideoFromDescription(desc: Dynamic, done: kha.Video->Void, failed: AssetError->Void): Void { | ||||||
|  | 		kha.js.Video.fromFile(desc.files, done); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadRemote(desc: Dynamic, done: Blob->Void, failed: AssetError->Void) { | ||||||
|  | 		var request = untyped new XMLHttpRequest(); | ||||||
|  | 		request.open("GET", desc.files[0], true); | ||||||
|  | 		request.responseType = "arraybuffer"; | ||||||
|  |  | ||||||
|  | 		request.onreadystatechange = function() { | ||||||
|  | 			if (request.readyState != 4) | ||||||
|  | 				return; | ||||||
|  | 			if ((request.status >= 200 && request.status < 400) | ||||||
|  | 				|| (request.status == 0 && request.statusText == "")) { // Blobs loaded using --allow-file-access-from-files | ||||||
|  | 				var bytes: Bytes = null; | ||||||
|  | 				var arrayBuffer = request.response; | ||||||
|  | 				if (arrayBuffer != null) { | ||||||
|  | 					var byteArray: Dynamic = Syntax.code("new Uint8Array(arrayBuffer)"); | ||||||
|  | 					bytes = Bytes.ofData(byteArray); | ||||||
|  | 				} | ||||||
|  | 				else if (request.responseBody != null) { | ||||||
|  | 					var data: Dynamic = untyped Syntax.code("VBArray(request.responseBody).toArray()"); | ||||||
|  | 					bytes = Bytes.alloc(data.length); | ||||||
|  | 					for (i in 0...data.length) | ||||||
|  | 						bytes.set(i, data[i]); | ||||||
|  | 				} | ||||||
|  | 				else { | ||||||
|  | 					failed({url: desc.files[0]}); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				done(new Blob(bytes)); | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				failed({url: desc.files[0]}); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		request.send(null); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadBlobFromDescription(desc: Dynamic, done: Blob->Void, failed: AssetError->Void) { | ||||||
|  | 		#if kha_debug_html5 | ||||||
|  | 		var file: String = desc.files[0]; | ||||||
|  |  | ||||||
|  | 		if (file.startsWith("http://") || file.startsWith("https://")) { | ||||||
|  | 			loadRemote(desc, done, failed); | ||||||
|  | 		} | ||||||
|  | 		else if (file.startsWith("drop://")) { | ||||||
|  | 			var dropFile = dropFiles.get(file.substring(7)); | ||||||
|  | 			if (dropFile == null) | ||||||
|  | 				failed({url: file, error: 'file not found'}); | ||||||
|  | 			else { | ||||||
|  | 				var reader = new FileReader(); | ||||||
|  | 				reader.onloadend = () -> { | ||||||
|  | 					done(new Blob(Bytes.ofData(reader.result))); | ||||||
|  | 				}; | ||||||
|  | 				reader.onerror = () -> failed({url: file, error: reader.error}); | ||||||
|  | 				reader.readAsArrayBuffer(dropFile); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			var loadBlob = Syntax.code("window.electron.loadBlob"); | ||||||
|  | 			loadBlob(desc, (byteArray: Dynamic) -> { | ||||||
|  | 				var bytes = Bytes.alloc(byteArray.byteLength); | ||||||
|  | 				for (i in 0...byteArray.byteLength) | ||||||
|  | 					bytes.set(i, byteArray[i]); | ||||||
|  | 				done(new Blob(bytes)); | ||||||
|  | 			}, failed); | ||||||
|  | 		} | ||||||
|  | 		#else | ||||||
|  | 		loadRemote(desc, done, failed); | ||||||
|  | 		#end | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function loadFontFromDescription(desc: Dynamic, done: Font->Void, failed: AssetError->Void): Void { | ||||||
|  | 		loadBlobFromDescription(desc, function(blob: Blob) { | ||||||
|  | 			done(new Font(blob)); | ||||||
|  | 		}, failed); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								Kha/Backends/HTML5/kha/Macros.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Kha/Backends/HTML5/kha/Macros.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.macro.Context; | ||||||
|  | import haxe.macro.Expr; | ||||||
|  |  | ||||||
|  | class Macros { | ||||||
|  | 	public static macro function canvasId(): Expr { | ||||||
|  | 		return { | ||||||
|  | 			expr: EConst(CString(Context.getDefines().get("canvas_id"))), | ||||||
|  | 			pos: Context.currentPos() | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										102
									
								
								Kha/Backends/HTML5/kha/Storage.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								Kha/Backends/HTML5/kha/Storage.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import haxe.io.BytesBuffer; | ||||||
|  | import haxe.io.BytesData; | ||||||
|  | import js.Browser; | ||||||
|  |  | ||||||
|  | using StringTools; | ||||||
|  |  | ||||||
|  | class LocalStorageFile extends StorageFile { | ||||||
|  | 	var name: String; | ||||||
|  |  | ||||||
|  | 	public function new(name: String) { | ||||||
|  | 		this.name = name; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function read(): Blob { | ||||||
|  | 		var storage = Browser.getLocalStorage(); | ||||||
|  | 		if (storage == null) | ||||||
|  | 			return null; | ||||||
|  | 		var value: String = storage.getItem(System.title + "_" + name); | ||||||
|  | 		if (value == null) | ||||||
|  | 			return null; | ||||||
|  | 		else | ||||||
|  | 			return Blob.fromBytes(decode(value)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function write(data: Blob): Void { | ||||||
|  | 		var storage = Browser.getLocalStorage(); | ||||||
|  | 		if (storage == null) | ||||||
|  | 			return; | ||||||
|  | 		storage.setItem(System.title + "_" + name, encode(data.bytes.getData())); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Encodes byte array to yEnc string (from SASStore). | ||||||
|  | 	 * @param  {Array}  source Byte array to convert to yEnc. | ||||||
|  | 	 * @return {string}        Resulting yEnc string from byte array. | ||||||
|  | 	 */ | ||||||
|  | 	static function encode(source: BytesData): String { | ||||||
|  | 		var reserved = [0, 10, 13, 61]; | ||||||
|  | 		var output = ""; | ||||||
|  | 		var converted, ele; | ||||||
|  | 		var bytes = new js.lib.Uint8Array(source); | ||||||
|  | 		for (i in 0...bytes.length) { | ||||||
|  | 			ele = bytes[i]; | ||||||
|  | 			converted = (ele + 42) % 256; | ||||||
|  | 			if (!Lambda.has(reserved, converted)) { | ||||||
|  | 				output += String.fromCharCode(converted); | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				converted = (converted + 64) % 256; | ||||||
|  | 				output += "=" + String.fromCharCode(converted); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return output; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Decodes yEnc string to byte array (from SASStore). | ||||||
|  | 	 * @param  {string} source yEnc string to decode to byte array. | ||||||
|  | 	 * @return {Array}         Resulting byte array from yEnc string. | ||||||
|  | 	 */ | ||||||
|  | 	static function decode(source: String): Bytes { | ||||||
|  | 		var output = new BytesBuffer(); | ||||||
|  | 		var ck = false; | ||||||
|  | 		var c; | ||||||
|  | 		for (i in 0...source.length) { | ||||||
|  | 			c = source.fastCodeAt(i); | ||||||
|  | 			// ignore newlines | ||||||
|  | 			if (c == 13 || c == 10) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			// if we're an "=" and we haven't been flagged, set flag | ||||||
|  | 			if (c == 61 && !ck) { | ||||||
|  | 				ck = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (ck) { | ||||||
|  | 				ck = false; | ||||||
|  | 				c = c - 64; | ||||||
|  | 			} | ||||||
|  | 			if (c < 42 && c > 0) { | ||||||
|  | 				output.addByte(c + 214); | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				output.addByte(c - 42); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return output.getBytes(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class Storage { | ||||||
|  | 	public static function namedFile(name: String): StorageFile { | ||||||
|  | 		return new LocalStorageFile(name); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function defaultFile(): StorageFile { | ||||||
|  | 		return namedFile("default.kha"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										1346
									
								
								Kha/Backends/HTML5/kha/SystemImpl.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1346
									
								
								Kha/Backends/HTML5/kha/SystemImpl.hx
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										584
									
								
								Kha/Backends/HTML5/kha/WebGLImage.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										584
									
								
								Kha/Backends/HTML5/kha/WebGLImage.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,584 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import js.Browser; | ||||||
|  | import js.lib.Uint8Array; | ||||||
|  | import js.lib.Uint16Array; | ||||||
|  | import js.lib.Float32Array; | ||||||
|  | import js.html.VideoElement; | ||||||
|  | import js.html.webgl.GL; | ||||||
|  | import js.html.webgl.Framebuffer; | ||||||
|  | import js.html.webgl.Renderbuffer; | ||||||
|  | import js.html.webgl.Texture; | ||||||
|  | import kha.graphics4.TextureFormat; | ||||||
|  | import kha.graphics4.DepthStencilFormat; | ||||||
|  | import kha.js.graphics4.Graphics; | ||||||
|  |  | ||||||
|  | class WebGLImage extends Image { | ||||||
|  | 	public var image: Dynamic; | ||||||
|  | 	public var video: VideoElement; | ||||||
|  |  | ||||||
|  | 	static var context: js.html.CanvasRenderingContext2D; | ||||||
|  |  | ||||||
|  | 	var data: js.html.ImageData; | ||||||
|  |  | ||||||
|  | 	var myWidth: Int; | ||||||
|  | 	var myHeight: Int; | ||||||
|  | 	var myFormat: TextureFormat; | ||||||
|  | 	var renderTarget: Bool; | ||||||
|  | 	var samples: Int; | ||||||
|  |  | ||||||
|  | 	public var frameBuffer: Framebuffer = null; | ||||||
|  | 	public var renderBuffer: Renderbuffer = null; | ||||||
|  | 	public var texture: Texture = null; | ||||||
|  | 	public var depthTexture: Texture = null; | ||||||
|  | 	public var MSAAFrameBuffer: Framebuffer = null; | ||||||
|  |  | ||||||
|  | 	var MSAAColorBuffer: Renderbuffer; | ||||||
|  | 	var MSAADepthBuffer: Renderbuffer; | ||||||
|  |  | ||||||
|  | 	var graphics1: kha.graphics1.Graphics; | ||||||
|  | 	var graphics2: kha.graphics2.Graphics; | ||||||
|  | 	var graphics4: kha.graphics4.Graphics; | ||||||
|  |  | ||||||
|  | 	var depthStencilFormat: DepthStencilFormat; | ||||||
|  |  | ||||||
|  | 	var readable: Bool; | ||||||
|  |  | ||||||
|  | 	// WebGL2 constants | ||||||
|  | 	static inline var GL_RGBA16F = 0x881A; | ||||||
|  | 	static inline var GL_RGBA32F = 0x8814; | ||||||
|  | 	static inline var GL_R16F = 0x822D; | ||||||
|  | 	static inline var GL_R32F = 0x822E; | ||||||
|  | 	static inline var GL_RED = 0x1903; | ||||||
|  | 	static inline var GL_DEPTH_COMPONENT24 = 0x81A6; | ||||||
|  | 	static inline var GL_DEPTH24_STENCIL8 = 0x88F0; | ||||||
|  | 	static inline var GL_DEPTH32F_STENCIL8 = 0x8CAD; | ||||||
|  |  | ||||||
|  | 	static var canvas: js.html.CanvasElement; | ||||||
|  |  | ||||||
|  | 	public static function init() { | ||||||
|  | 		if (context == null) { | ||||||
|  | 			// create only once | ||||||
|  | 			canvas = Browser.document.createCanvasElement(); | ||||||
|  | 			if (canvas != null) { | ||||||
|  | 				context = canvas.getContext("2d"); | ||||||
|  | 				canvas.width = 4096; | ||||||
|  | 				canvas.height = 4096; | ||||||
|  | 				context.globalCompositeOperation = "copy"; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function new(width: Int, height: Int, format: TextureFormat, renderTarget: Bool, depthStencilFormat: DepthStencilFormat, samples: Int, | ||||||
|  | 			readable: Bool) { | ||||||
|  | 		myWidth = width; | ||||||
|  | 		myHeight = height; | ||||||
|  | 		myFormat = format; | ||||||
|  | 		this.renderTarget = renderTarget; | ||||||
|  | 		this.samples = samples; | ||||||
|  | 		this.readable = readable; | ||||||
|  | 		image = null; | ||||||
|  | 		video = null; | ||||||
|  | 		this.depthStencilFormat = depthStencilFormat; | ||||||
|  | 		init(); | ||||||
|  | 		if (renderTarget) | ||||||
|  | 			createTexture(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_g1(): kha.graphics1.Graphics { | ||||||
|  | 		if (graphics1 == null) { | ||||||
|  | 			graphics1 = new kha.graphics2.Graphics1(this); | ||||||
|  | 		} | ||||||
|  | 		return graphics1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_g2(): kha.graphics2.Graphics { | ||||||
|  | 		if (graphics2 == null) { | ||||||
|  | 			graphics2 = new kha.js.graphics4.Graphics2(this); | ||||||
|  | 		} | ||||||
|  | 		return graphics2; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_g4(): kha.graphics4.Graphics { | ||||||
|  | 		if (graphics4 == null) { | ||||||
|  | 			graphics4 = new Graphics(this); | ||||||
|  | 		} | ||||||
|  | 		return graphics4; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_width(): Int { | ||||||
|  | 		return myWidth; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_height(): Int { | ||||||
|  | 		return myHeight; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_format(): TextureFormat { | ||||||
|  | 		return myFormat; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_realWidth(): Int { | ||||||
|  | 		return myWidth; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_realHeight(): Int { | ||||||
|  | 		return myHeight; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_stride(): Int { | ||||||
|  | 		return formatByteSize(myFormat) * width; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function isOpaque(x: Int, y: Int): Bool { | ||||||
|  | 		if (data == null) { | ||||||
|  | 			if (context == null) | ||||||
|  | 				return true; | ||||||
|  | 			else | ||||||
|  | 				createImageData(); | ||||||
|  | 		} | ||||||
|  | 		return (data.data[y * Std.int(image.width) * 4 + x * 4 + 3] != 0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function at(x: Int, y: Int): Color { | ||||||
|  | 		if (bytes != null) { | ||||||
|  | 			var r = bytes.get(y * width * 4 + x * 4); | ||||||
|  | 			var g = bytes.get(y * width * 4 + x * 4 + 1); | ||||||
|  | 			var b = bytes.get(y * width * 4 + x * 4 + 2); | ||||||
|  | 			var a = bytes.get(y * width * 4 + x * 4 + 3); | ||||||
|  |  | ||||||
|  | 			return Color.fromValue((a << 24) | (r << 16) | (g << 8) | b); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			if (data == null) { | ||||||
|  | 				if (context == null) | ||||||
|  | 					return Color.Black; | ||||||
|  | 				else | ||||||
|  | 					createImageData(); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var r = data.data[y * width * 4 + x * 4]; | ||||||
|  | 			var g = data.data[y * width * 4 + x * 4 + 1]; | ||||||
|  | 			var b = data.data[y * width * 4 + x * 4 + 2]; | ||||||
|  | 			var a = data.data[y * width * 4 + x * 4 + 3]; | ||||||
|  |  | ||||||
|  | 			return Color.fromValue((a << 24) | (r << 16) | (g << 8) | b); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function createImageData() { | ||||||
|  | 		if (Std.isOfType(image, Uint8Array)) { | ||||||
|  | 			data = new js.html.ImageData(new js.lib.Uint8ClampedArray(image.buffer), this.width, this.height); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			if (this.width > canvas.width || this.height > canvas.height) { | ||||||
|  | 				var cw = canvas.width; | ||||||
|  | 				var ch = canvas.height; | ||||||
|  | 				while (this.width > cw || this.height > ch) { | ||||||
|  | 					cw *= 2; | ||||||
|  | 					ch *= 2; | ||||||
|  | 				} | ||||||
|  | 				canvas.width = cw; | ||||||
|  | 				canvas.height = ch; | ||||||
|  | 			} | ||||||
|  | 			context.strokeStyle = "rgba(0,0,0,0)"; | ||||||
|  | 			context.fillStyle = "rgba(0,0,0,0)"; | ||||||
|  | 			context.fillRect(0, 0, image.width, image.height); | ||||||
|  | 			context.drawImage(image, 0, 0, image.width, image.height, 0, 0, image.width, image.height); | ||||||
|  | 			data = context.getImageData(0, 0, image.width, image.height); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static function upperPowerOfTwo(v: Int): Int { | ||||||
|  | 		v--; | ||||||
|  | 		v |= v >>> 1; | ||||||
|  | 		v |= v >>> 2; | ||||||
|  | 		v |= v >>> 4; | ||||||
|  | 		v |= v >>> 8; | ||||||
|  | 		v |= v >>> 16; | ||||||
|  | 		v++; | ||||||
|  | 		return v; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function createTexture(): Void { | ||||||
|  | 		if (SystemImpl.gl == null) | ||||||
|  | 			return; | ||||||
|  | 		texture = SystemImpl.gl.createTexture(); | ||||||
|  | 		// texture.image = image; | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); | ||||||
|  | 		// Sys.gl.pixelStorei(Sys.gl.UNPACK_FLIP_Y_WEBGL, true); | ||||||
|  |  | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR); | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); | ||||||
|  | 		if (renderTarget) { | ||||||
|  | 			frameBuffer = SystemImpl.gl.createFramebuffer(); | ||||||
|  | 			SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  | 			switch (myFormat) { | ||||||
|  | 				case DEPTH16: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL.DEPTH_COMPONENT16 : GL.DEPTH_COMPONENT, realWidth, realHeight, 0, | ||||||
|  | 						GL.DEPTH_COMPONENT, GL.UNSIGNED_SHORT, null); | ||||||
|  | 				case RGBA128: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_RGBA32F : GL.RGBA, realWidth, realHeight, 0, GL.RGBA, GL.FLOAT, null); | ||||||
|  | 				case RGBA64: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_RGBA16F : GL.RGBA, realWidth, realHeight, 0, GL.RGBA, | ||||||
|  | 						SystemImpl.halfFloat.HALF_FLOAT_OES, null); | ||||||
|  | 				case RGBA32: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, realWidth, realHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null); | ||||||
|  | 				case A32: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_R32F : GL.ALPHA, realWidth, realHeight, 0, | ||||||
|  | 						SystemImpl.gl2 ? GL_RED : GL.ALPHA, GL.FLOAT, null); | ||||||
|  | 				case A16: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_R16F : GL.ALPHA, realWidth, realHeight, 0, | ||||||
|  | 						SystemImpl.gl2 ? GL_RED : GL.ALPHA, SystemImpl.halfFloat.HALF_FLOAT_OES, null); | ||||||
|  | 				default: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, realWidth, realHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (myFormat == DEPTH16) { | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.NEAREST); | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST); | ||||||
|  | 				SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_2D, texture, 0); | ||||||
|  | 				// Some WebGL implementations throw incomplete framebuffer error, create color attachment | ||||||
|  | 				if (!SystemImpl.gl2) { | ||||||
|  | 					var colortex = SystemImpl.gl.createTexture(); | ||||||
|  | 					SystemImpl.gl.bindTexture(GL.TEXTURE_2D, colortex); | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, realWidth, realHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null); | ||||||
|  | 					SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, colortex, 0); | ||||||
|  | 					SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				if (samples > 1 && SystemImpl.gl2) { | ||||||
|  | 					MSAAFrameBuffer = SystemImpl.gl.createFramebuffer(); | ||||||
|  | 					MSAAColorBuffer = SystemImpl.gl.createRenderbuffer(); | ||||||
|  | 					SystemImpl.gl.bindRenderbuffer(GL.RENDERBUFFER, MSAAColorBuffer); | ||||||
|  | 					var MSAAFormat = switch (myFormat) { | ||||||
|  | 						case RGBA128: | ||||||
|  | 							untyped SystemImpl.gl.RGBA32F; | ||||||
|  | 						case RGBA64: | ||||||
|  | 							untyped SystemImpl.gl.RGBA16F; | ||||||
|  | 						case RGBA32: | ||||||
|  | 							untyped SystemImpl.gl.RGBA8; | ||||||
|  | 						case A32: | ||||||
|  | 							GL_R32F; | ||||||
|  | 						case A16: | ||||||
|  | 							GL_R16F; | ||||||
|  | 						default: | ||||||
|  | 							untyped SystemImpl.gl.RGBA8; | ||||||
|  | 					}; | ||||||
|  | 					untyped SystemImpl.gl.renderbufferStorageMultisample(GL.RENDERBUFFER, samples, MSAAFormat, realWidth, realHeight); | ||||||
|  | 					SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  | 					SystemImpl.gl.framebufferRenderbuffer(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.RENDERBUFFER, MSAAColorBuffer); | ||||||
|  | 					SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, MSAAFrameBuffer); | ||||||
|  | 				} | ||||||
|  | 				SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, texture, 0); | ||||||
|  | 				SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			initDepthStencilBuffer(depthStencilFormat); | ||||||
|  | 			var e = SystemImpl.gl.checkFramebufferStatus(GL.FRAMEBUFFER); | ||||||
|  | 			if (e != GL.FRAMEBUFFER_COMPLETE) { | ||||||
|  | 				trace("checkframebufferStatus error " + e); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			SystemImpl.gl.bindRenderbuffer(GL.RENDERBUFFER, null); | ||||||
|  | 			SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null); | ||||||
|  | 		} | ||||||
|  | 		else if (video != null) { | ||||||
|  | 			SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, video); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			switch (myFormat) { | ||||||
|  | 				case RGBA128: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_RGBA32F : GL.RGBA, myWidth, myHeight, 0, GL.RGBA, GL.FLOAT, image); | ||||||
|  | 				case RGBA64: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_RGBA16F : GL.RGBA, myWidth, myHeight, 0, GL.RGBA, | ||||||
|  | 						SystemImpl.halfFloat.HALF_FLOAT_OES, image); | ||||||
|  | 				case RGBA32: | ||||||
|  | 					if (Std.isOfType(image, Uint8Array)) { | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, myWidth, myHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, image); | ||||||
|  | 					} | ||||||
|  | 					else { | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, image); | ||||||
|  | 					} | ||||||
|  | 				case A32: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_R32F : GL.ALPHA, myWidth, myHeight, 0, SystemImpl.gl2 ? GL_RED : GL.ALPHA, | ||||||
|  | 						GL.FLOAT, image); | ||||||
|  | 				case A16: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_R16F : GL.ALPHA, myWidth, myHeight, 0, SystemImpl.gl2 ? GL_RED : GL.ALPHA, | ||||||
|  | 						SystemImpl.halfFloat.HALF_FLOAT_OES, image); | ||||||
|  | 				case L8: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.LUMINANCE, myWidth, myHeight, 0, GL.LUMINANCE, GL.UNSIGNED_BYTE, image); | ||||||
|  | 				default: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, image); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_2D, null); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function initDepthStencilBuffer(depthStencilFormat: DepthStencilFormat) { | ||||||
|  | 		switch (depthStencilFormat) { | ||||||
|  | 			case NoDepthAndStencil: | ||||||
|  | 			case DepthOnly, Depth16: | ||||||
|  | 				{ | ||||||
|  | 					if (SystemImpl.depthTexture == null) { | ||||||
|  | 						renderBuffer = SystemImpl.gl.createRenderbuffer(); | ||||||
|  | 						SystemImpl.gl.bindRenderbuffer(GL.RENDERBUFFER, renderBuffer); | ||||||
|  | 						SystemImpl.gl.renderbufferStorage(GL.RENDERBUFFER, GL.DEPTH_COMPONENT16, realWidth, realHeight); | ||||||
|  | 						SystemImpl.gl.framebufferRenderbuffer(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.RENDERBUFFER, renderBuffer); | ||||||
|  | 					} | ||||||
|  | 					else { | ||||||
|  | 						depthTexture = SystemImpl.gl.createTexture(); | ||||||
|  | 						SystemImpl.gl.bindTexture(GL.TEXTURE_2D, depthTexture); | ||||||
|  | 						if (depthStencilFormat == DepthOnly) | ||||||
|  | 							SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_DEPTH_COMPONENT24 : GL.DEPTH_COMPONENT, realWidth, realHeight, 0, | ||||||
|  | 								GL.DEPTH_COMPONENT, GL.UNSIGNED_INT, null); | ||||||
|  | 						else | ||||||
|  | 							SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL.DEPTH_COMPONENT16 : GL.DEPTH_COMPONENT, realWidth, realHeight, 0, | ||||||
|  | 								GL.DEPTH_COMPONENT, GL.UNSIGNED_SHORT, null); | ||||||
|  | 						SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.NEAREST); | ||||||
|  | 						SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST); | ||||||
|  | 						SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); | ||||||
|  | 						SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); | ||||||
|  | 						SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  |  | ||||||
|  | 						if (samples > 1 && SystemImpl.gl2) { | ||||||
|  | 							MSAADepthBuffer = SystemImpl.gl.createRenderbuffer(); | ||||||
|  | 							SystemImpl.gl.bindRenderbuffer(GL.RENDERBUFFER, MSAADepthBuffer); | ||||||
|  | 							if (depthStencilFormat == DepthOnly) | ||||||
|  | 								untyped SystemImpl.gl.renderbufferStorageMultisample(GL.RENDERBUFFER, samples, GL_DEPTH_COMPONENT24, realWidth, realHeight); | ||||||
|  | 							else | ||||||
|  | 								untyped SystemImpl.gl.renderbufferStorageMultisample(GL.RENDERBUFFER, samples, GL.DEPTH_COMPONENT16, realWidth, realHeight); | ||||||
|  | 							SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  | 							SystemImpl.gl.framebufferRenderbuffer(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.RENDERBUFFER, MSAADepthBuffer); | ||||||
|  | 							SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, MSAAFrameBuffer); | ||||||
|  | 						} | ||||||
|  | 						SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_2D, depthTexture, 0); | ||||||
|  | 						SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			case DepthAutoStencilAuto, Depth24Stencil8, Depth32Stencil8: | ||||||
|  | 				if (SystemImpl.depthTexture == null) { | ||||||
|  | 					renderBuffer = SystemImpl.gl.createRenderbuffer(); | ||||||
|  | 					SystemImpl.gl.bindRenderbuffer(GL.RENDERBUFFER, renderBuffer); | ||||||
|  | 					SystemImpl.gl.renderbufferStorage(GL.RENDERBUFFER, GL.DEPTH_STENCIL, realWidth, realHeight); | ||||||
|  | 					SystemImpl.gl.framebufferRenderbuffer(GL.FRAMEBUFFER, GL.DEPTH_STENCIL_ATTACHMENT, GL.RENDERBUFFER, renderBuffer); | ||||||
|  | 				} | ||||||
|  | 				else { | ||||||
|  | 					depthTexture = SystemImpl.gl.createTexture(); | ||||||
|  | 					SystemImpl.gl.bindTexture(GL.TEXTURE_2D, depthTexture); | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_DEPTH24_STENCIL8 : GL.DEPTH_STENCIL, realWidth, realHeight, 0, | ||||||
|  | 						GL.DEPTH_STENCIL, SystemImpl.depthTexture.UNSIGNED_INT_24_8_WEBGL, null); | ||||||
|  | 					SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.NEAREST); | ||||||
|  | 					SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST); | ||||||
|  | 					SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); | ||||||
|  | 					SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); | ||||||
|  | 					SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  | 					if (samples > 1 && SystemImpl.gl2) { | ||||||
|  | 						MSAADepthBuffer = SystemImpl.gl.createRenderbuffer(); | ||||||
|  | 						SystemImpl.gl.bindRenderbuffer(GL.RENDERBUFFER, MSAADepthBuffer); | ||||||
|  | 						untyped SystemImpl.gl.renderbufferStorageMultisample(GL.RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, realWidth, realHeight); | ||||||
|  | 						SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  | 						SystemImpl.gl.framebufferRenderbuffer(GL.FRAMEBUFFER, GL.DEPTH_STENCIL_ATTACHMENT, GL.RENDERBUFFER, MSAADepthBuffer); | ||||||
|  | 						SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, MSAAFrameBuffer); | ||||||
|  | 					} | ||||||
|  | 					SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_STENCIL_ATTACHMENT, GL.TEXTURE_2D, depthTexture, 0); | ||||||
|  | 				} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function set(stage: Int): Void { | ||||||
|  | 		SystemImpl.gl.activeTexture(GL.TEXTURE0 + stage); | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); | ||||||
|  | 		if (video != null) | ||||||
|  | 			SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, video); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setDepth(stage: Int): Void { | ||||||
|  | 		SystemImpl.gl.activeTexture(GL.TEXTURE0 + stage); | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_2D, depthTexture); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function setDepthStencilFrom(image: Image): Void { | ||||||
|  | 		depthTexture = cast(image, WebGLImage).depthTexture; | ||||||
|  | 		SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  | 		SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_2D, depthTexture, 0); | ||||||
|  | 		if (samples > 1 && SystemImpl.gl2) { | ||||||
|  | 			MSAADepthBuffer = cast(image, WebGLImage).MSAADepthBuffer; | ||||||
|  | 			SystemImpl.gl.framebufferRenderbuffer(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.RENDERBUFFER, MSAADepthBuffer); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	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 bytesToArray(bytes: Bytes): js.lib.ArrayBufferView { | ||||||
|  | 		return switch (myFormat) { | ||||||
|  | 			case RGBA32, L8: | ||||||
|  | 				new Uint8Array(bytes.getData()); | ||||||
|  | 			case RGBA128, RGBA64, A32, A16: | ||||||
|  | 				new Float32Array(bytes.getData()); | ||||||
|  | 			default: | ||||||
|  | 				new Uint8Array(bytes.getData()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var bytes: Bytes; | ||||||
|  |  | ||||||
|  | 	override public function lock(level: Int = 0): Bytes { | ||||||
|  | 		bytes = Bytes.alloc(formatByteSize(myFormat) * width * height); | ||||||
|  | 		return bytes; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function unlock(): Void { | ||||||
|  | 		data = null; | ||||||
|  | 		image = null; | ||||||
|  |  | ||||||
|  | 		if (SystemImpl.gl != null) { | ||||||
|  | 			texture = SystemImpl.gl.createTexture(); | ||||||
|  | 			// texture.image = image; | ||||||
|  | 			SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); | ||||||
|  | 			// Sys.gl.pixelStorei(Sys.gl.UNPACK_FLIP_Y_WEBGL, true); | ||||||
|  |  | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR); | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); | ||||||
|  |  | ||||||
|  | 			switch (myFormat) { | ||||||
|  | 				case L8: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.LUMINANCE, width, height, 0, GL.LUMINANCE, GL.UNSIGNED_BYTE, bytesToArray(bytes)); | ||||||
|  |  | ||||||
|  | 					if (SystemImpl.ie && SystemImpl.gl.getError() == 1282) { // no LUMINANCE support in IE11 | ||||||
|  | 						var rgbaBytes = Bytes.alloc(width * height * 4); | ||||||
|  | 						for (y in 0...height) | ||||||
|  | 							for (x in 0...width) { | ||||||
|  | 								var value = bytes.get(y * width + x); | ||||||
|  | 								rgbaBytes.set(y * width * 4 + x * 4 + 0, value); | ||||||
|  | 								rgbaBytes.set(y * width * 4 + x * 4 + 1, value); | ||||||
|  | 								rgbaBytes.set(y * width * 4 + x * 4 + 2, value); | ||||||
|  | 								rgbaBytes.set(y * width * 4 + x * 4 + 3, 255); | ||||||
|  | 							} | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, width, height, 0, GL.RGBA, GL.UNSIGNED_BYTE, bytesToArray(rgbaBytes)); | ||||||
|  | 					} | ||||||
|  | 				case RGBA128: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_RGBA32F : GL.RGBA, width, height, 0, GL.RGBA, GL.FLOAT, | ||||||
|  | 						bytesToArray(bytes)); | ||||||
|  | 				case RGBA64: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_RGBA16F : GL.RGBA, width, height, 0, GL.RGBA, | ||||||
|  | 						SystemImpl.halfFloat.HALF_FLOAT_OES, bytesToArray(bytes)); | ||||||
|  | 				case A32: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_R32F : GL.ALPHA, width, height, 0, SystemImpl.gl2 ? GL_RED : GL.ALPHA, | ||||||
|  | 						GL.FLOAT, bytesToArray(bytes)); | ||||||
|  | 				case A16: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, SystemImpl.gl2 ? GL_R16F : GL.ALPHA, width, height, 0, SystemImpl.gl2 ? GL_RED : GL.ALPHA, | ||||||
|  | 						SystemImpl.halfFloat.HALF_FLOAT_OES, bytesToArray(bytes)); | ||||||
|  | 				case RGBA32: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, width, height, 0, GL.RGBA, GL.UNSIGNED_BYTE, bytesToArray(bytes)); | ||||||
|  | 				default: | ||||||
|  | 					SystemImpl.gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, width, height, 0, GL.RGBA, GL.UNSIGNED_BYTE, bytesToArray(bytes)); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			SystemImpl.gl.bindTexture(GL.TEXTURE_2D, null); | ||||||
|  |  | ||||||
|  | 			if (!readable) { | ||||||
|  | 				bytes = null; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var pixels: js.lib.ArrayBufferView = null; | ||||||
|  |  | ||||||
|  | 	override public function getPixels(): Bytes { | ||||||
|  | 		if (frameBuffer == null) | ||||||
|  | 			return null; | ||||||
|  | 		if (pixels == null) { | ||||||
|  | 			switch (myFormat) { | ||||||
|  | 				case RGBA128, A32: | ||||||
|  | 					pixels = new Float32Array(Std.int(formatByteSize(myFormat) / 4) * width * height); | ||||||
|  | 				case RGBA64, A16: | ||||||
|  | 					pixels = new Uint16Array(Std.int(formatByteSize(myFormat) / 2) * width * height); | ||||||
|  | 				case RGBA32, L8: | ||||||
|  | 					pixels = new Uint8Array(formatByteSize(myFormat) * width * height); | ||||||
|  | 				default: | ||||||
|  | 					pixels = new Uint8Array(formatByteSize(myFormat) * width * height); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  | 		switch (myFormat) { | ||||||
|  | 			case RGBA128: | ||||||
|  | 				SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, GL.RGBA, GL.FLOAT, pixels); | ||||||
|  | 			case RGBA64: | ||||||
|  | 				SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, GL.RGBA, SystemImpl.halfFloat.HALF_FLOAT_OES, pixels); | ||||||
|  | 			case RGBA32: | ||||||
|  | 				SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, GL.RGBA, GL.UNSIGNED_BYTE, pixels); | ||||||
|  | 			case A32: | ||||||
|  | 				SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, SystemImpl.gl2 ? GL_RED : GL.ALPHA, GL.FLOAT, pixels); | ||||||
|  | 			case A16: | ||||||
|  | 				SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, SystemImpl.gl2 ? GL_RED : GL.ALPHA, SystemImpl.halfFloat.HALF_FLOAT_OES, pixels); | ||||||
|  | 			case L8: | ||||||
|  | 				SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, SystemImpl.gl2 ? GL_RED : GL.ALPHA, GL.UNSIGNED_BYTE, pixels); | ||||||
|  | 			default: | ||||||
|  | 				SystemImpl.gl.readPixels(0, 0, myWidth, myHeight, GL.RGBA, GL.UNSIGNED_BYTE, pixels); | ||||||
|  | 		} | ||||||
|  | 		return Bytes.ofData(pixels.buffer); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function unload(): Void { | ||||||
|  | 		if (texture != null) | ||||||
|  | 			SystemImpl.gl.deleteTexture(texture); | ||||||
|  | 		if (depthTexture != null) | ||||||
|  | 			SystemImpl.gl.deleteTexture(depthTexture); | ||||||
|  | 		if (frameBuffer != null) | ||||||
|  | 			SystemImpl.gl.deleteFramebuffer(frameBuffer); | ||||||
|  | 		if (renderBuffer != null) | ||||||
|  | 			SystemImpl.gl.deleteRenderbuffer(renderBuffer); | ||||||
|  | 		if (MSAAFrameBuffer != null) | ||||||
|  | 			SystemImpl.gl.deleteFramebuffer(MSAAFrameBuffer); | ||||||
|  | 		if (MSAAColorBuffer != null) | ||||||
|  | 			SystemImpl.gl.deleteRenderbuffer(MSAAColorBuffer); | ||||||
|  | 		if (MSAADepthBuffer != null) | ||||||
|  | 			SystemImpl.gl.deleteRenderbuffer(MSAADepthBuffer); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function generateMipmaps(levels: Int): Void { | ||||||
|  | 		// WebGL requires to generate all mipmaps down to 1x1 size, ignoring levels for now | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); | ||||||
|  | 		SystemImpl.gl.generateMipmap(GL.TEXTURE_2D); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function setMipmaps(mipmaps: Array<Image>): Void { | ||||||
|  | 		// Similar to generateMipmaps, specify all the levels down to 1x1 size | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_2D, texture); | ||||||
|  | 		if (myFormat == TextureFormat.RGBA128) { | ||||||
|  | 			for (i in 0...mipmaps.length) { | ||||||
|  | 				SystemImpl.gl.texImage2D(GL.TEXTURE_2D, i + 1, SystemImpl.gl2 ? GL_RGBA32F : GL.RGBA, mipmaps[i].width, mipmaps[i].height, 0, GL.RGBA, | ||||||
|  | 					GL.FLOAT, cast(mipmaps[i], WebGLImage).image); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (myFormat == TextureFormat.RGBA64) { | ||||||
|  | 			for (i in 0...mipmaps.length) { | ||||||
|  | 				SystemImpl.gl.texImage2D(GL.TEXTURE_2D, i + 1, SystemImpl.gl2 ? GL_RGBA16F : GL.RGBA, mipmaps[i].width, mipmaps[i].height, 0, GL.RGBA, | ||||||
|  | 					SystemImpl.halfFloat.HALF_FLOAT_OES, cast(mipmaps[i], WebGLImage).image); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			for (i in 0...mipmaps.length) { | ||||||
|  | 				SystemImpl.gl.texImage2D(GL.TEXTURE_2D, i + 1, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, cast(mipmaps[i], WebGLImage).image); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										195
									
								
								Kha/Backends/HTML5/kha/Window.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								Kha/Backends/HTML5/kha/Window.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,195 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import js.Syntax; | ||||||
|  | import js.html.MutationObserver; | ||||||
|  |  | ||||||
|  | class Window { | ||||||
|  | 	static var windows: Array<Window> = []; | ||||||
|  | 	static var resizeCallbacks: Array<Array<Int->Int->Void>> = []; | ||||||
|  |  | ||||||
|  | 	var num: Int; | ||||||
|  | 	var canvas: js.html.CanvasElement; | ||||||
|  | 	var defaultWidth: Int; | ||||||
|  | 	var defaultHeight: Int; | ||||||
|  |  | ||||||
|  | 	@:noCompletion | ||||||
|  | 	@:noDoc | ||||||
|  | 	public function new(num: Int, defaultWidth: Int, defaultHeight: Int, canvas: js.html.CanvasElement) { | ||||||
|  | 		this.num = num; | ||||||
|  | 		this.canvas = canvas; | ||||||
|  | 		this.defaultWidth = defaultWidth; | ||||||
|  | 		this.defaultHeight = defaultHeight; | ||||||
|  | 		windows.push(this); | ||||||
|  | 		resizeCallbacks[num] = []; | ||||||
|  | 		windows.push(this); | ||||||
|  | 		final observer: MutationObserver = new MutationObserver(function(mutations: Array<js.html.MutationRecord>, observer: MutationObserver) { | ||||||
|  | 			var isResize = false; | ||||||
|  | 			for (mutation in mutations) { | ||||||
|  | 				if (mutation.attributeName == "width" || mutation.attributeName == "height") { | ||||||
|  | 					isResize = true; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if (isResize) { | ||||||
|  | 				this.resize(canvas.width, canvas.height); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 		observer.observe(canvas, {attributes: true}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function create(win: WindowOptions = null, frame: FramebufferOptions = null): Window { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function destroy(window: Window): Void {} | ||||||
|  |  | ||||||
|  | 	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; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function resize(width: Int, height: Int): Void { | ||||||
|  | 		for (callback in resizeCallbacks[num]) { | ||||||
|  | 			callback(width, height); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function move(x: Int, y: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function changeWindowFeatures(features: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function changeFramebuffer(frame: FramebufferOptions): Void {} | ||||||
|  |  | ||||||
|  | 	public var x(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_x(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_x(value: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var y(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_y(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_y(value: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var width(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return canvas.width == 0 ? defaultWidth : canvas.width; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_width(value: Int): Int { | ||||||
|  | 		return 800; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, set): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return canvas.height == 0 ? defaultHeight : canvas.height; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_height(value: Int): Int { | ||||||
|  | 		return 600; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var mode(get, set): WindowMode; | ||||||
|  |  | ||||||
|  | 	function get_mode(): WindowMode { | ||||||
|  | 		return isFullscreen() ? Fullscreen : Windowed; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_mode(mode: WindowMode): WindowMode { | ||||||
|  | 		if (mode == Fullscreen || mode == ExclusiveFullscreen) { | ||||||
|  | 			if (!isFullscreen()) { | ||||||
|  | 				requestFullscreen(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			if (isFullscreen()) { | ||||||
|  | 				exitFullscreen(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return mode; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function isFullscreen(): Bool { | ||||||
|  | 		return Syntax.code("document.fullscreenElement === this.canvas || | ||||||
|  | 			document.mozFullScreenElement === this.canvas || | ||||||
|  | 			document.webkitFullscreenElement === this.canvas || | ||||||
|  | 			document.msFullscreenElement === this.canvas "); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function requestFullscreen(): Void { | ||||||
|  | 		untyped if (canvas.requestFullscreen) { | ||||||
|  | 			var c: Dynamic = canvas; | ||||||
|  | 			c.requestFullscreen({navigationUI: "hide"}); | ||||||
|  | 		} | ||||||
|  | 		else if (canvas.msRequestFullscreen) { | ||||||
|  | 			canvas.msRequestFullscreen(); | ||||||
|  | 		} | ||||||
|  | 		else if (canvas.mozRequestFullScreen) { | ||||||
|  | 			canvas.mozRequestFullScreen(); | ||||||
|  | 		} | ||||||
|  | 		else if (canvas.webkitRequestFullscreen) { | ||||||
|  | 			canvas.webkitRequestFullscreen(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function exitFullscreen(): Void { | ||||||
|  | 		untyped if (document.exitFullscreen) { | ||||||
|  | 			document.exitFullscreen(); | ||||||
|  | 		} | ||||||
|  | 		else if (document.msExitFullscreen) { | ||||||
|  | 			document.msExitFullscreen(); | ||||||
|  | 		} | ||||||
|  | 		else if (document.mozCancelFullScreen) { | ||||||
|  | 			document.mozCancelFullScreen(); | ||||||
|  | 		} | ||||||
|  | 		else if (document.webkitExitFullscreen) { | ||||||
|  | 			document.webkitExitFullscreen(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var visible(get, set): Bool; | ||||||
|  |  | ||||||
|  | 	function get_visible(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_visible(value: Bool): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var title(get, set): String; | ||||||
|  |  | ||||||
|  | 	function get_title(): String { | ||||||
|  | 		return "Kha"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_title(value: String): String { | ||||||
|  | 		return "Kha"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function notifyOnResize(callback: Int->Int->Void): Void { | ||||||
|  | 		resizeCallbacks[num].push(callback); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var vSynced(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	function get_vSynced(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										187
									
								
								Kha/Backends/HTML5/kha/arrays/ByteArray.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								Kha/Backends/HTML5/kha/arrays/ByteArray.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,187 @@ | |||||||
|  | package kha.arrays; | ||||||
|  |  | ||||||
|  | import js.lib.DataView; | ||||||
|  | import kha.FastFloat; | ||||||
|  |  | ||||||
|  | @:forward | ||||||
|  | abstract ByteArray(DataView) to DataView { | ||||||
|  | 	static final LITTLE_ENDIAN: Bool = js.Syntax.code("new Uint8Array(new Uint32Array([0x12345678]).buffer)[0] === 0x78"); | ||||||
|  |  | ||||||
|  | 	public var buffer(get, never): ByteBuffer; | ||||||
|  |  | ||||||
|  | 	inline function get_buffer(): ByteBuffer { | ||||||
|  | 		return cast this.buffer; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function new(buffer: ByteBuffer, ?byteOffset: Int, ?byteLength: Int) { | ||||||
|  | 		this = new DataView(buffer, byteOffset, byteLength); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static public function make(byteLength: Int): ByteArray { | ||||||
|  | 		return new ByteArray(ByteBuffer.create(byteLength)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt8(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt8(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint8(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint8(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt16(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt16(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint16(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint16(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt32(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt32(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint32(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint32(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat32(byteOffset: Int): FastFloat { | ||||||
|  | 		return this.getFloat32(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat64(byteOffset: Int): Float { | ||||||
|  | 		return this.getFloat64(byteOffset, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt8(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt8(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint8(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint8(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt16(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt16(byteOffset, value, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint16(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint16(byteOffset, value, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt32(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt32(byteOffset, value, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint32(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint32(byteOffset, value, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat32(byteOffset: Int, value: FastFloat): Void { | ||||||
|  | 		this.setFloat32(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat64(byteOffset: Int, value: Float): Void { | ||||||
|  | 		this.setFloat64(byteOffset, value, LITTLE_ENDIAN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt16LE(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt16(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint16LE(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint16(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt32LE(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt32(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint32LE(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint32(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat32LE(byteOffset: Int): FastFloat { | ||||||
|  | 		return this.getFloat32(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat64LE(byteOffset: Int): Float { | ||||||
|  | 		return this.getFloat64(byteOffset, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt16LE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt16(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint16LE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint16(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt32LE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt32(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint32LE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint32(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat32LE(byteOffset: Int, value: FastFloat): Void { | ||||||
|  | 		this.setFloat32(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat64LE(byteOffset: Int, value: Float): Void { | ||||||
|  | 		this.setFloat64(byteOffset, value, true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt16BE(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt16(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint16BE(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint16(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getInt32BE(byteOffset: Int): Int { | ||||||
|  | 		return this.getInt32(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getUint32BE(byteOffset: Int): Int { | ||||||
|  | 		return this.getUint32(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat32BE(byteOffset: Int): FastFloat { | ||||||
|  | 		return this.getFloat32(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function getFloat64BE(byteOffset: Int): Float { | ||||||
|  | 		return this.getFloat64(byteOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt16BE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt16(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint16BE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint16(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setInt32BE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setInt32(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setUint32BE(byteOffset: Int, value: Int): Void { | ||||||
|  | 		this.setUint32(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat32BE(byteOffset: Int, value: FastFloat): Void { | ||||||
|  | 		this.setFloat32(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function setFloat64BE(byteOffset: Int, value: Float): Void { | ||||||
|  | 		this.setFloat64(byteOffset, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public inline function subarray(start: Int, ?end: Int): ByteArray { | ||||||
|  | 		return new ByteArray(buffer, start, end != null ? end - start : null); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								Kha/Backends/HTML5/kha/arrays/ByteBuffer.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Kha/Backends/HTML5/kha/arrays/ByteBuffer.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | package kha.arrays; | ||||||
|  |  | ||||||
|  | import js.lib.ArrayBuffer; | ||||||
|  |  | ||||||
|  | @:forward | ||||||
|  | abstract ByteBuffer(ArrayBuffer) from ArrayBuffer to ArrayBuffer { | ||||||
|  | 	public static function create(length: Int): ByteBuffer { | ||||||
|  | 		return new ByteBuffer(length); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function new(length: Int) { | ||||||
|  | 		this = new ArrayBuffer(length); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								Kha/Backends/HTML5/kha/audio1/Audio.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Kha/Backends/HTML5/kha/audio1/Audio.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | package kha.audio1; | ||||||
|  |  | ||||||
|  | typedef Audio = kha.audio2.Audio1; | ||||||
							
								
								
									
										107
									
								
								Kha/Backends/HTML5/kha/audio2/Audio.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								Kha/Backends/HTML5/kha/audio2/Audio.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,107 @@ | |||||||
|  | package kha.audio2; | ||||||
|  |  | ||||||
|  | import js.Syntax; | ||||||
|  | import js.Browser; | ||||||
|  | import js.html.URL; | ||||||
|  | import js.html.audio.AudioContext; | ||||||
|  | import js.html.audio.AudioProcessingEvent; | ||||||
|  | import js.html.audio.ScriptProcessorNode; | ||||||
|  | import kha.internal.IntBox; | ||||||
|  | import kha.js.AEAudioChannel; | ||||||
|  | import kha.Sound; | ||||||
|  |  | ||||||
|  | class Audio { | ||||||
|  | 	public static var disableGcInteractions = false; | ||||||
|  | 	static var intBox: IntBox = new IntBox(0); | ||||||
|  | 	static var buffer: Buffer; | ||||||
|  | 	@:noCompletion public static var _context: AudioContext; | ||||||
|  | 	static var processingNode: ScriptProcessorNode; | ||||||
|  |  | ||||||
|  | 	static function initContext(): Void { | ||||||
|  | 		try { | ||||||
|  | 			_context = new AudioContext(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		catch (e:Dynamic) {} | ||||||
|  | 		try { | ||||||
|  | 			Syntax.code("this._context = new webkitAudioContext();"); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		catch (e:Dynamic) {} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@:noCompletion | ||||||
|  | 	public static function _init(): Bool { | ||||||
|  | 		initContext(); | ||||||
|  | 		if (_context == null) | ||||||
|  | 			return false; | ||||||
|  |  | ||||||
|  | 		Audio.samplesPerSecond = Math.round(_context.sampleRate); | ||||||
|  | 		var bufferSize = 1024 * 2; | ||||||
|  | 		buffer = new Buffer(bufferSize * 4, 2, Std.int(_context.sampleRate)); | ||||||
|  |  | ||||||
|  | 		processingNode = _context.createScriptProcessor(bufferSize, 0, 2); | ||||||
|  | 		processingNode.onaudioprocess = function(e: AudioProcessingEvent) { | ||||||
|  | 			var output1 = e.outputBuffer.getChannelData(0); | ||||||
|  | 			var output2 = e.outputBuffer.getChannelData(1); | ||||||
|  | 			if (audioCallback != null) { | ||||||
|  | 				intBox.value = e.outputBuffer.length * 2; | ||||||
|  | 				audioCallback(intBox, buffer); | ||||||
|  | 				for (i in 0...e.outputBuffer.length) { | ||||||
|  | 					output1[i] = buffer.data.get(buffer.readLocation); | ||||||
|  | 					buffer.readLocation += 1; | ||||||
|  | 					output2[i] = buffer.data.get(buffer.readLocation); | ||||||
|  | 					buffer.readLocation += 1; | ||||||
|  | 					if (buffer.readLocation >= buffer.size) { | ||||||
|  | 						buffer.readLocation = 0; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				for (i in 0...e.outputBuffer.length) { | ||||||
|  | 					output1[i] = 0; | ||||||
|  | 					output2[i] = 0; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		processingNode.connect(_context.destination); | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var samplesPerSecond: Int; | ||||||
|  |  | ||||||
|  | 	public static var audioCallback: kha.internal.IntBox->Buffer->Void; | ||||||
|  |  | ||||||
|  | 	static var virtualChannels: Array<VirtualStreamChannel> = []; | ||||||
|  |  | ||||||
|  | 	public static function wakeChannels() { | ||||||
|  | 		SystemImpl.mobileAudioPlaying = true; | ||||||
|  | 		for (channel in virtualChannels) { | ||||||
|  | 			channel.wake(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function stream(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel { | ||||||
|  | 		// var source = _context.createMediaStreamSource(cast sound.compressedData.getData()); | ||||||
|  | 		// source.connect(_context.destination); | ||||||
|  | 		var element = Browser.document.createAudioElement(); | ||||||
|  | 		#if kha_debug_html5 | ||||||
|  | 		var blob = new js.html.Blob([sound.compressedData.getData()], {type: "audio/ogg"}); | ||||||
|  | 		#else | ||||||
|  | 		var blob = new js.html.Blob([sound.compressedData.getData()], {type: "audio/mp4"}); | ||||||
|  | 		#end | ||||||
|  | 		element.src = URL.createObjectURL(blob); | ||||||
|  | 		element.loop = loop; | ||||||
|  | 		var channel = new AEAudioChannel(element, loop); | ||||||
|  |  | ||||||
|  | 		if (SystemImpl.mobileAudioPlaying) { | ||||||
|  | 			channel.play(); | ||||||
|  | 			return channel; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			var virtualChannel = new VirtualStreamChannel(channel, loop); | ||||||
|  | 			virtualChannels.push(virtualChannel); | ||||||
|  | 			return virtualChannel; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										126
									
								
								Kha/Backends/HTML5/kha/audio2/VirtualStreamChannel.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								Kha/Backends/HTML5/kha/audio2/VirtualStreamChannel.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,126 @@ | |||||||
|  | package kha.audio2; | ||||||
|  |  | ||||||
|  | import kha.js.AEAudioChannel; | ||||||
|  | import kha.audio1.AudioChannel; | ||||||
|  |  | ||||||
|  | enum abstract PlayMode(Int) { | ||||||
|  | 	var Stopped; | ||||||
|  | 	var Paused; | ||||||
|  | 	var Playing; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class VirtualStreamChannel implements kha.audio1.AudioChannel { | ||||||
|  | 	var aeChannel: AEAudioChannel; | ||||||
|  | 	var mode = PlayMode.Playing; | ||||||
|  | 	var lastTickTime: Float; | ||||||
|  | 	var lastPosition: Float; | ||||||
|  | 	var looping: Bool; | ||||||
|  |  | ||||||
|  | 	public function new(aeChannel: AEAudioChannel, looping: Bool) { | ||||||
|  | 		this.aeChannel = aeChannel; | ||||||
|  | 		this.looping = looping; | ||||||
|  | 		lastTickTime = Scheduler.realTime(); | ||||||
|  | 		lastPosition = 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function wake(): Void { | ||||||
|  | 		updatePosition(); | ||||||
|  | 		aeChannel.position = lastPosition; | ||||||
|  | 		aeChannel.play(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function updatePosition(): Void { | ||||||
|  | 		var now = Scheduler.realTime(); | ||||||
|  | 		switch (mode) { | ||||||
|  | 			case Stopped: | ||||||
|  | 				lastPosition = 0; | ||||||
|  | 			case Paused: | ||||||
|  | 			// nothing | ||||||
|  | 			case Playing: | ||||||
|  | 				lastPosition += now - lastTickTime; | ||||||
|  | 				while (lastPosition > length) { | ||||||
|  | 					lastPosition -= length; | ||||||
|  | 				} | ||||||
|  | 		} | ||||||
|  | 		lastTickTime = now; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function play(): Void { | ||||||
|  | 		if (SystemImpl.mobileAudioPlaying) { | ||||||
|  | 			aeChannel.play(); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			updatePosition(); | ||||||
|  | 			mode = Playing; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function pause(): Void { | ||||||
|  | 		if (SystemImpl.mobileAudioPlaying) { | ||||||
|  | 			aeChannel.pause(); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			updatePosition(); | ||||||
|  | 			mode = Paused; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function stop(): Void { | ||||||
|  | 		if (SystemImpl.mobileAudioPlaying) { | ||||||
|  | 			aeChannel.stop(); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			updatePosition(); | ||||||
|  | 			mode = Stopped; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var length(get, never): Float; // Seconds | ||||||
|  |  | ||||||
|  | 	function get_length(): Float { | ||||||
|  | 		return aeChannel.length; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var position(get, set): Float; // Seconds | ||||||
|  |  | ||||||
|  | 	function get_position(): Float { | ||||||
|  | 		if (SystemImpl.mobileAudioPlaying) { | ||||||
|  | 			return aeChannel.position; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			updatePosition(); | ||||||
|  | 			return lastPosition; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_position(value: Float): Float { | ||||||
|  | 		if (SystemImpl.mobileAudioPlaying) { | ||||||
|  | 			return aeChannel.position = value; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			updatePosition(); | ||||||
|  | 			return lastPosition = value; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var volume(get, set): Float; | ||||||
|  |  | ||||||
|  | 	function get_volume(): Float { | ||||||
|  | 		return aeChannel.volume; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_volume(value: Float): Float { | ||||||
|  | 		return aeChannel.volume = value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var finished(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	function get_finished(): Bool { | ||||||
|  | 		if (SystemImpl.mobileAudioPlaying) { | ||||||
|  | 			return aeChannel.finished; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			return mode == Stopped || (!looping && position >= length); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								Kha/Backends/HTML5/kha/capture/AudioCapture.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								Kha/Backends/HTML5/kha/capture/AudioCapture.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | |||||||
|  | package kha.capture; | ||||||
|  |  | ||||||
|  | import js.html.audio.AudioProcessingEvent; | ||||||
|  | import kha.audio2.Buffer; | ||||||
|  |  | ||||||
|  | class AudioCapture { | ||||||
|  | 	static var input: js.html.audio.MediaStreamAudioSourceNode; | ||||||
|  | 	static var processingNode: js.html.audio.ScriptProcessorNode; | ||||||
|  | 	static var buffer: Buffer; | ||||||
|  |  | ||||||
|  | 	public static var audioCallback: Int->Buffer->Void; | ||||||
|  |  | ||||||
|  | 	public static function init(initialized: Void->Void, error: Void->Void): Void { | ||||||
|  | 		if (kha.audio2.Audio._context == null) { | ||||||
|  | 			error(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var getUserMedia = untyped __js__("navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia"); | ||||||
|  | 		getUserMedia.call(js.Browser.navigator, {audio: true}, function(stream: Dynamic) { | ||||||
|  | 			input = kha.audio2.Audio._context.createMediaStreamSource(stream); | ||||||
|  |  | ||||||
|  | 			var bufferSize = 1024 * 2; | ||||||
|  | 			buffer = new Buffer(bufferSize * 4, 2, Std.int(kha.audio2.Audio._context.sampleRate)); | ||||||
|  |  | ||||||
|  | 			processingNode = kha.audio2.Audio._context.createScriptProcessor(bufferSize, 1, 0); | ||||||
|  | 			processingNode.onaudioprocess = function(e: AudioProcessingEvent) { | ||||||
|  | 				if (audioCallback != null) { | ||||||
|  | 					var input1 = e.inputBuffer.getChannelData(0); | ||||||
|  | 					var input2 = e.inputBuffer.getChannelData(0); | ||||||
|  | 					for (i in 0...e.inputBuffer.length) { | ||||||
|  | 						buffer.data.set(buffer.writeLocation, input1[i]); | ||||||
|  | 						buffer.writeLocation += 1; | ||||||
|  | 						buffer.data.set(buffer.writeLocation, input2[i]); | ||||||
|  | 						buffer.writeLocation += 1; | ||||||
|  | 						if (buffer.writeLocation >= buffer.size) { | ||||||
|  | 							buffer.writeLocation = 0; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					audioCallback(e.inputBuffer.length * 2, buffer); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			input.connect(processingNode); | ||||||
|  | 			// input.connect(kha.audio2.Audio._context.destination); | ||||||
|  | 			initialized(); | ||||||
|  | 		}, function() { | ||||||
|  | 			error(); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								Kha/Backends/HTML5/kha/capture/VideoCapture.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Kha/Backends/HTML5/kha/capture/VideoCapture.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | package kha.capture; | ||||||
|  |  | ||||||
|  | import js.Browser; | ||||||
|  |  | ||||||
|  | class VideoCapture { | ||||||
|  | 	public static function init(initialized: kha.Video->Void, error: Void->Void): Void { | ||||||
|  | 		var getUserMedia = untyped __js__("navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia"); | ||||||
|  | 		getUserMedia.call(js.Browser.navigator, {audio: true, video: true}, function(stream: Dynamic) { | ||||||
|  | 			var element: js.html.VideoElement = cast Browser.document.createElement("video"); | ||||||
|  | 			element.srcObject = stream; | ||||||
|  | 			element.onloadedmetadata = function(e) { | ||||||
|  | 				initialized(kha.js.Video.fromElement(element)); | ||||||
|  | 			} | ||||||
|  | 		}, function() { | ||||||
|  | 			error(); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										199
									
								
								Kha/Backends/HTML5/kha/graphics4/CubeMap.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								Kha/Backends/HTML5/kha/graphics4/CubeMap.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,199 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import js.html.webgl.GL; | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import kha.js.graphics4.Graphics; | ||||||
|  |  | ||||||
|  | class CubeMap implements Canvas implements Resource { | ||||||
|  | 	var myWidth: Int; | ||||||
|  | 	var myHeight: Int; | ||||||
|  | 	var format: TextureFormat; | ||||||
|  | 	var renderTarget: Bool; | ||||||
|  | 	var depthStencilFormat: DepthStencilFormat; | ||||||
|  | 	var graphics4: kha.graphics4.Graphics; | ||||||
|  |  | ||||||
|  | 	public var frameBuffer: Dynamic = null; | ||||||
|  | 	public var texture: Dynamic = null; | ||||||
|  | 	public var depthTexture: Dynamic = null; | ||||||
|  | 	public var isDepthAttachment: Bool = false; | ||||||
|  |  | ||||||
|  | 	// WebGL2 constants | ||||||
|  | 	static inline var GL_RGBA16F = 0x881A; | ||||||
|  | 	static inline var GL_RGBA32F = 0x8814; | ||||||
|  | 	static inline var GL_R16F = 0x822D; | ||||||
|  | 	static inline var GL_R32F = 0x822E; | ||||||
|  | 	static inline var GL_DEPTH_COMPONENT24 = 0x81A6; | ||||||
|  | 	static inline var GL_DEPTH24_STENCIL8 = 0x88F0; | ||||||
|  | 	static inline var GL_DEPTH32F_STENCIL8 = 0x8CAD; | ||||||
|  |  | ||||||
|  | 	function new(size: Int, format: TextureFormat, renderTarget: Bool, depthStencilFormat: DepthStencilFormat) { | ||||||
|  | 		myWidth = size; | ||||||
|  | 		myHeight = size; | ||||||
|  | 		this.format = format; | ||||||
|  | 		this.renderTarget = renderTarget; | ||||||
|  | 		this.depthStencilFormat = depthStencilFormat; | ||||||
|  | 		if (renderTarget) | ||||||
|  | 			createTexture(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function createRenderTarget(size: Int, format: TextureFormat = null, depthStencil: DepthStencilFormat = null): CubeMap { | ||||||
|  | 		if (format == null) | ||||||
|  | 			format = TextureFormat.RGBA32; | ||||||
|  | 		if (depthStencil == null) | ||||||
|  | 			depthStencil = NoDepthAndStencil; | ||||||
|  | 		return new CubeMap(size, format, true, depthStencil); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function createTexture() { | ||||||
|  | 		if (SystemImpl.gl == null) | ||||||
|  | 			return; | ||||||
|  |  | ||||||
|  | 		texture = SystemImpl.gl.createTexture(); | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, texture); | ||||||
|  |  | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MAG_FILTER, GL.LINEAR); | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MIN_FILTER, GL.LINEAR); | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); | ||||||
|  | 		SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); | ||||||
|  |  | ||||||
|  | 		if (renderTarget) { | ||||||
|  | 			frameBuffer = SystemImpl.gl.createFramebuffer(); | ||||||
|  | 			SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  |  | ||||||
|  | 			switch (format) { | ||||||
|  | 				case DEPTH16: | ||||||
|  | 					for (i in 0...6) | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, SystemImpl.gl2 ? GL.DEPTH_COMPONENT16 : GL.DEPTH_COMPONENT, myWidth, | ||||||
|  | 							myHeight, 0, GL.DEPTH_COMPONENT, GL.UNSIGNED_SHORT, null); | ||||||
|  | 				case RGBA128: | ||||||
|  | 					for (i in 0...6) | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, SystemImpl.gl2 ? GL_RGBA32F : GL.RGBA, myWidth, myHeight, 0, GL.RGBA, | ||||||
|  | 							GL.FLOAT, null); | ||||||
|  | 				case RGBA64: | ||||||
|  | 					for (i in 0...6) | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, SystemImpl.gl2 ? GL_RGBA16F : GL.RGBA, myWidth, myHeight, 0, GL.RGBA, | ||||||
|  | 							SystemImpl.halfFloat.HALF_FLOAT_OES, null); | ||||||
|  | 				case RGBA32: | ||||||
|  | 					for (i in 0...6) | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL.RGBA, myWidth, myHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null); | ||||||
|  | 				case A32: | ||||||
|  | 					for (i in 0...6) | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, SystemImpl.gl2 ? GL_R32F : GL.ALPHA, myWidth, myHeight, 0, GL.ALPHA, | ||||||
|  | 							GL.FLOAT, null); | ||||||
|  | 				case A16: | ||||||
|  | 					for (i in 0...6) | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, SystemImpl.gl2 ? GL_R16F : GL.ALPHA, myWidth, myHeight, 0, GL.ALPHA, | ||||||
|  | 							SystemImpl.halfFloat.HALF_FLOAT_OES, null); | ||||||
|  | 				default: | ||||||
|  | 					for (i in 0...6) | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL.RGBA, myWidth, myHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (format == DEPTH16) { | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MAG_FILTER, GL.NEAREST); | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MIN_FILTER, GL.NEAREST); | ||||||
|  | 				isDepthAttachment = true; | ||||||
|  | 				// Some WebGL implementations throw incomplete framebuffer error, create color attachment | ||||||
|  | 				if (!SystemImpl.gl2) { | ||||||
|  | 					var colortex = SystemImpl.gl.createTexture(); | ||||||
|  | 					SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, colortex); | ||||||
|  | 					for (i in 0...6) { | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL.RGBA, myWidth, myHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null); | ||||||
|  | 						SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, colortex, 0); | ||||||
|  | 					} | ||||||
|  | 					SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, texture); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			initDepthStencilBuffer(depthStencilFormat); | ||||||
|  | 			SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, null); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function initDepthStencilBuffer(depthStencilFormat: DepthStencilFormat) { | ||||||
|  | 		switch (depthStencilFormat) { | ||||||
|  | 			case NoDepthAndStencil: | ||||||
|  | 			case DepthOnly, Depth16: | ||||||
|  | 				{ | ||||||
|  | 					depthTexture = SystemImpl.gl.createTexture(); | ||||||
|  | 					SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, depthTexture); | ||||||
|  | 					if (depthStencilFormat == DepthOnly) | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP, 0, SystemImpl.gl2 ? GL_DEPTH_COMPONENT24 : GL.DEPTH_COMPONENT, myWidth, myHeight, 0, | ||||||
|  | 							GL.DEPTH_COMPONENT, GL.UNSIGNED_INT, null); | ||||||
|  | 					else | ||||||
|  | 						SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP, 0, SystemImpl.gl2 ? GL.DEPTH_COMPONENT16 : GL.DEPTH_COMPONENT, myWidth, myHeight, 0, | ||||||
|  | 							GL.DEPTH_COMPONENT, GL.UNSIGNED_SHORT, null); | ||||||
|  | 					SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MAG_FILTER, GL.NEAREST); | ||||||
|  | 					SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MIN_FILTER, GL.NEAREST); | ||||||
|  | 					SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); | ||||||
|  | 					SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); | ||||||
|  | 					SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  | 					SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_CUBE_MAP, depthTexture, 0); | ||||||
|  | 				} | ||||||
|  | 			case DepthAutoStencilAuto, Depth24Stencil8, Depth32Stencil8: | ||||||
|  | 				depthTexture = SystemImpl.gl.createTexture(); | ||||||
|  | 				SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, depthTexture); | ||||||
|  | 				SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP, 0, SystemImpl.gl2 ? GL_DEPTH24_STENCIL8 : GL.DEPTH_STENCIL, myWidth, myHeight, 0, | ||||||
|  | 					GL.DEPTH_STENCIL, SystemImpl.depthTexture.UNSIGNED_INT_24_8_WEBGL, null); | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MAG_FILTER, GL.NEAREST); | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MIN_FILTER, GL.NEAREST); | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); | ||||||
|  | 				SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer); | ||||||
|  | 				SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_STENCIL_ATTACHMENT, GL.TEXTURE_CUBE_MAP, depthTexture, 0); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function set(stage: Int): Void { | ||||||
|  | 		SystemImpl.gl.activeTexture(GL.TEXTURE0 + stage); | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, texture); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setDepth(stage: Int): Void { | ||||||
|  | 		SystemImpl.gl.activeTexture(GL.TEXTURE0 + stage); | ||||||
|  | 		SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, depthTexture); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unload(): Void {} | ||||||
|  |  | ||||||
|  | 	public function lock(level: Int = 0): Bytes { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(): Void {} | ||||||
|  |  | ||||||
|  | 	public var width(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return myWidth; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return myHeight; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	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 Graphics(this); | ||||||
|  | 		} | ||||||
|  | 		return graphics4; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								Kha/Backends/HTML5/kha/graphics4/FragmentShader.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								Kha/Backends/HTML5/kha/graphics4/FragmentShader.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import js.html.webgl.GL; | ||||||
|  |  | ||||||
|  | class FragmentShader { | ||||||
|  | 	public var sources: Array<String>; | ||||||
|  | 	public var type: Dynamic; | ||||||
|  | 	public var shader: Dynamic; | ||||||
|  | 	public var files: Array<String>; | ||||||
|  |  | ||||||
|  | 	public function new(sources: Array<Blob>, files: Array<String>) { | ||||||
|  | 		this.sources = []; | ||||||
|  | 		for (source in sources) { | ||||||
|  | 			this.sources.push(source.toString()); | ||||||
|  | 		} | ||||||
|  | 		this.type = GL.FRAGMENT_SHADER; | ||||||
|  | 		this.shader = null; | ||||||
|  | 		this.files = files; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromSource(source: String): FragmentShader { | ||||||
|  | 		var shader = new FragmentShader([], ["runtime-string"]); | ||||||
|  | 		shader.sources.push(source); | ||||||
|  | 		return shader; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		SystemImpl.gl.deleteShader(shader); | ||||||
|  | 		shader = null; | ||||||
|  | 		sources = null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								Kha/Backends/HTML5/kha/graphics4/IndexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								Kha/Backends/HTML5/kha/graphics4/IndexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import js.html.webgl.GL; | ||||||
|  | import kha.arrays.Uint32Array; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  |  | ||||||
|  | class IndexBuffer { | ||||||
|  | 	public var _data: Uint32Array; | ||||||
|  |  | ||||||
|  | 	var buffer: Dynamic; | ||||||
|  | 	var mySize: Int; | ||||||
|  | 	var usage: Usage; | ||||||
|  | 	var lockStart: Int = 0; | ||||||
|  | 	var lockEnd: Int = 0; | ||||||
|  |  | ||||||
|  | 	public function new(indexCount: Int, usage: Usage, canRead: Bool = false) { | ||||||
|  | 		this.usage = usage; | ||||||
|  | 		mySize = indexCount; | ||||||
|  | 		buffer = SystemImpl.gl.createBuffer(); | ||||||
|  | 		_data = new Uint32Array(indexCount); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		_data = null; | ||||||
|  | 		SystemImpl.gl.deleteBuffer(buffer); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function lock(?start: Int, ?count: Int): Uint32Array { | ||||||
|  | 		lockStart = start != null ? start : 0; | ||||||
|  | 		lockEnd = count != null ? start + count : mySize; | ||||||
|  | 		return _data.subarray(lockStart, lockEnd); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(?count: Int): Void { | ||||||
|  | 		if (count != null) | ||||||
|  | 			lockEnd = lockStart + count; | ||||||
|  | 		SystemImpl.gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, buffer); | ||||||
|  | 		var data = _data.subarray(lockStart, lockEnd); | ||||||
|  | 		var glData: Dynamic = SystemImpl.elementIndexUint == null ? new js.lib.Uint16Array(data.buffer) : data; | ||||||
|  | 		SystemImpl.gl.bufferData(GL.ELEMENT_ARRAY_BUFFER, glData, usage == Usage.DynamicUsage ? GL.DYNAMIC_DRAW : GL.STATIC_DRAW); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function set(): Void { | ||||||
|  | 		SystemImpl.gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, buffer); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function count(): Int { | ||||||
|  | 		return mySize; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										133
									
								
								Kha/Backends/HTML5/kha/graphics4/PipelineState.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								Kha/Backends/HTML5/kha/graphics4/PipelineState.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,133 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import js.html.webgl.GL; | ||||||
|  | import kha.graphics4.VertexData; | ||||||
|  |  | ||||||
|  | class PipelineState extends PipelineStateBase { | ||||||
|  | 	var program: Dynamic = null; | ||||||
|  | 	var textures: Array<String>; | ||||||
|  | 	var textureValues: Array<Dynamic>; | ||||||
|  |  | ||||||
|  | 	public function new() { | ||||||
|  | 		super(); | ||||||
|  | 		textures = new Array<String>(); | ||||||
|  | 		textureValues = new Array<Dynamic>(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		if (program != null) { | ||||||
|  | 			SystemImpl.gl.deleteProgram(program); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function compile(): Void { | ||||||
|  | 		if (program != null) { | ||||||
|  | 			SystemImpl.gl.deleteProgram(program); | ||||||
|  | 		} | ||||||
|  | 		program = SystemImpl.gl.createProgram(); | ||||||
|  | 		compileShader(vertexShader); | ||||||
|  | 		compileShader(fragmentShader); | ||||||
|  | 		SystemImpl.gl.attachShader(program, vertexShader.shader); | ||||||
|  | 		SystemImpl.gl.attachShader(program, fragmentShader.shader); | ||||||
|  |  | ||||||
|  | 		var index = 0; | ||||||
|  | 		for (structure in inputLayout) { | ||||||
|  | 			for (element in structure.elements) { | ||||||
|  | 				SystemImpl.gl.bindAttribLocation(program, index, element.name); | ||||||
|  | 				if (element.data == VertexData.Float32_4X4) { | ||||||
|  | 					index += 4; | ||||||
|  | 				} | ||||||
|  | 				else { | ||||||
|  | 					++index; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		SystemImpl.gl.linkProgram(program); | ||||||
|  | 		if (!SystemImpl.gl.getProgramParameter(program, GL.LINK_STATUS)) { | ||||||
|  | 			var message = "Could not link the shader program:\n" + SystemImpl.gl.getProgramInfoLog(program); | ||||||
|  | 			trace("Error: " + message); | ||||||
|  | 			throw message; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function set(): Void { | ||||||
|  | 		SystemImpl.gl.useProgram(program); | ||||||
|  | 		for (index in 0...textureValues.length) | ||||||
|  | 			SystemImpl.gl.uniform1i(textureValues[index], index); | ||||||
|  | 		SystemImpl.gl.colorMask(colorWriteMaskRed, colorWriteMaskGreen, colorWriteMaskBlue, colorWriteMaskAlpha); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function compileShader(shader: Dynamic): Void { | ||||||
|  | 		if (shader.shader != null) | ||||||
|  | 			return; | ||||||
|  | 		var s = SystemImpl.gl.createShader(shader.type); | ||||||
|  | 		var highp = SystemImpl.gl.getShaderPrecisionFormat(GL.FRAGMENT_SHADER, GL.HIGH_FLOAT); | ||||||
|  | 		var highpSupported = highp.precision != 0; | ||||||
|  | 		var files: Array<String> = shader.files; | ||||||
|  | 		for (i in 0...files.length) { | ||||||
|  | 			if (SystemImpl.gl2) { | ||||||
|  | 				if (files[i].indexOf("-webgl2") >= 0 || files[i].indexOf("runtime-string") >= 0) { | ||||||
|  | 					SystemImpl.gl.shaderSource(s, shader.sources[i]); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				if (!highpSupported && (files[i].indexOf("-relaxed") >= 0 || files[i].indexOf("runtime-string") >= 0)) { | ||||||
|  | 					SystemImpl.gl.shaderSource(s, shader.sources[i]); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 				if (highpSupported && (files[i].indexOf("-relaxed") < 0 || files[i].indexOf("runtime-string") >= 0)) { | ||||||
|  | 					SystemImpl.gl.shaderSource(s, shader.sources[i]); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		SystemImpl.gl.compileShader(s); | ||||||
|  | 		if (!SystemImpl.gl.getShaderParameter(s, GL.COMPILE_STATUS)) { | ||||||
|  | 			var message = "Could not compile shader:\n" + SystemImpl.gl.getShaderInfoLog(s); | ||||||
|  | 			trace("Error: " + message); | ||||||
|  | 			throw message; | ||||||
|  | 		} | ||||||
|  | 		shader.shader = s; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function getConstantLocation(name: String): kha.graphics4.ConstantLocation { | ||||||
|  | 		var location = SystemImpl.gl.getUniformLocation(program, name); | ||||||
|  | 		if (location == null) { | ||||||
|  | 			trace("Warning: Uniform " + name + " not found."); | ||||||
|  | 		} | ||||||
|  | 		var type = GL.FLOAT; | ||||||
|  | 		var count: Int = SystemImpl.gl.getProgramParameter(program, GL.ACTIVE_UNIFORMS); | ||||||
|  | 		for (i in 0...count) { | ||||||
|  | 			var info = SystemImpl.gl.getActiveUniform(program, i); | ||||||
|  | 			if (info.name == name || info.name == name + "[0]") { | ||||||
|  | 				type = info.type; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return new kha.js.graphics4.ConstantLocation(location, type); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function getTextureUnit(name: String): kha.graphics4.TextureUnit { | ||||||
|  | 		var index = findTexture(name); | ||||||
|  | 		if (index < 0) { | ||||||
|  | 			var location = SystemImpl.gl.getUniformLocation(program, name); | ||||||
|  | 			if (location == null) { | ||||||
|  | 				trace("Warning: Sampler " + name + " not found."); | ||||||
|  | 			} | ||||||
|  | 			index = textures.length; | ||||||
|  | 			textureValues.push(location); | ||||||
|  | 			textures.push(name); | ||||||
|  | 		} | ||||||
|  | 		return new kha.js.graphics4.TextureUnit(index); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function findTexture(name: String): Int { | ||||||
|  | 		for (index in 0...textures.length) { | ||||||
|  | 			if (textures[index] == name) | ||||||
|  | 				return index; | ||||||
|  | 		} | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										206
									
								
								Kha/Backends/HTML5/kha/graphics4/VertexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								Kha/Backends/HTML5/kha/graphics4/VertexBuffer.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,206 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import kha.arrays.Float32Array; | ||||||
|  | import js.html.webgl.GL; | ||||||
|  | import kha.arrays.ByteArray; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  | import kha.graphics4.VertexStructure; | ||||||
|  |  | ||||||
|  | class VertexBuffer { | ||||||
|  | 	public var _data: ByteArray; | ||||||
|  |  | ||||||
|  | 	var buffer: Dynamic; | ||||||
|  | 	var mySize: Int; | ||||||
|  | 	var myStride: Int; | ||||||
|  | 	var sizes: Array<Int>; | ||||||
|  | 	var offsets: Array<Int>; | ||||||
|  | 	var types: Array<Int>; | ||||||
|  | 	var instanceDataStepRate: Int; | ||||||
|  | 	var lockStart: Int = 0; | ||||||
|  | 	var lockEnd: Int = 0; | ||||||
|  |  | ||||||
|  | 	public function new(vertexCount: Int, structure: VertexStructure, usage: Usage, instanceDataStepRate: Int = 0, canRead: Bool = false) { | ||||||
|  | 		this.instanceDataStepRate = instanceDataStepRate; | ||||||
|  | 		mySize = vertexCount; | ||||||
|  | 		myStride = 0; | ||||||
|  | 		for (element in structure.elements) { | ||||||
|  | 			myStride += VertexStructure.dataByteSize(element.data); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		buffer = SystemImpl.gl.createBuffer(); | ||||||
|  | 		_data = ByteArray.make(vertexCount * myStride); | ||||||
|  |  | ||||||
|  | 		sizes = new Array<Int>(); | ||||||
|  | 		offsets = new Array<Int>(); | ||||||
|  | 		types = new Array<Int>(); | ||||||
|  | 		sizes[structure.elements.length - 1] = 0; | ||||||
|  | 		offsets[structure.elements.length - 1] = 0; | ||||||
|  | 		types[structure.elements.length - 1] = 0; | ||||||
|  |  | ||||||
|  | 		var offset = 0; | ||||||
|  | 		var index = 0; | ||||||
|  | 		for (element in structure.elements) { | ||||||
|  | 			var size; | ||||||
|  | 			var type; | ||||||
|  | 			switch (element.data) { | ||||||
|  | 				case Float32_1X: | ||||||
|  | 					size = 1; | ||||||
|  | 					type = GL.FLOAT; | ||||||
|  | 				case Float32_2X: | ||||||
|  | 					size = 2; | ||||||
|  | 					type = GL.FLOAT; | ||||||
|  | 				case Float32_3X: | ||||||
|  | 					size = 3; | ||||||
|  | 					type = GL.FLOAT; | ||||||
|  | 				case Float32_4X: | ||||||
|  | 					size = 4; | ||||||
|  | 					type = GL.FLOAT; | ||||||
|  | 				case Float32_4X4: | ||||||
|  | 					size = 4 * 4; | ||||||
|  | 					type = GL.FLOAT; | ||||||
|  | 				case Int8_1X, Int8_1X_Normalized: | ||||||
|  | 					size = 1; | ||||||
|  | 					type = GL.BYTE; | ||||||
|  | 				case Int8_2X, Int8_2X_Normalized: | ||||||
|  | 					size = 2; | ||||||
|  | 					type = GL.BYTE; | ||||||
|  | 				case Int8_4X, Int8_4X_Normalized: | ||||||
|  | 					size = 4; | ||||||
|  | 					type = GL.BYTE; | ||||||
|  | 				case UInt8_1X, UInt8_1X_Normalized: | ||||||
|  | 					size = 1; | ||||||
|  | 					type = GL.UNSIGNED_BYTE; | ||||||
|  | 				case UInt8_2X, UInt8_2X_Normalized: | ||||||
|  | 					size = 2; | ||||||
|  | 					type = GL.UNSIGNED_BYTE; | ||||||
|  | 				case UInt8_4X, UInt8_4X_Normalized: | ||||||
|  | 					size = 4; | ||||||
|  | 					type = GL.UNSIGNED_BYTE; | ||||||
|  | 				case Int16_1X, Int16_1X_Normalized: | ||||||
|  | 					size = 1; | ||||||
|  | 					type = GL.SHORT; | ||||||
|  | 				case Int16_2X, Int16_2X_Normalized: | ||||||
|  | 					size = 2; | ||||||
|  | 					type = GL.SHORT; | ||||||
|  | 				case Int16_4X, Int16_4X_Normalized: | ||||||
|  | 					size = 4; | ||||||
|  | 					type = GL.SHORT; | ||||||
|  | 				case UInt16_1X, UInt16_1X_Normalized: | ||||||
|  | 					size = 1; | ||||||
|  | 					type = GL.UNSIGNED_SHORT; | ||||||
|  | 				case UInt16_2X, UInt16_2X_Normalized: | ||||||
|  | 					size = 2; | ||||||
|  | 					type = GL.UNSIGNED_SHORT; | ||||||
|  | 				case UInt16_4X, UInt16_4X_Normalized: | ||||||
|  | 					size = 4; | ||||||
|  | 					type = GL.UNSIGNED_SHORT; | ||||||
|  | 				case Int32_1X: | ||||||
|  | 					size = 1; | ||||||
|  | 					type = GL.INT; | ||||||
|  | 				case Int32_2X: | ||||||
|  | 					size = 2; | ||||||
|  | 					type = GL.INT; | ||||||
|  | 				case Int32_3X: | ||||||
|  | 					size = 3; | ||||||
|  | 					type = GL.INT; | ||||||
|  | 				case Int32_4X: | ||||||
|  | 					size = 4; | ||||||
|  | 					type = GL.INT; | ||||||
|  | 				case UInt32_1X: | ||||||
|  | 					size = 1; | ||||||
|  | 					type = GL.UNSIGNED_INT; | ||||||
|  | 				case UInt32_2X: | ||||||
|  | 					size = 2; | ||||||
|  | 					type = GL.UNSIGNED_INT; | ||||||
|  | 				case UInt32_3X: | ||||||
|  | 					size = 3; | ||||||
|  | 					type = GL.UNSIGNED_INT; | ||||||
|  | 				case UInt32_4X: | ||||||
|  | 					size = 4; | ||||||
|  | 					type = GL.UNSIGNED_INT; | ||||||
|  | 			} | ||||||
|  | 			sizes[index] = size; | ||||||
|  | 			offsets[index] = offset; | ||||||
|  | 			types[index] = type; | ||||||
|  | 			offset += VertexStructure.dataByteSize(element.data); | ||||||
|  | 			++index; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		SystemImpl.gl.bindBuffer(GL.ARRAY_BUFFER, buffer); | ||||||
|  | 		SystemImpl.gl.bufferData(GL.ARRAY_BUFFER, _data.subarray(0 * stride(), mySize * stride()), | ||||||
|  | 			usage == Usage.DynamicUsage ? GL.DYNAMIC_DRAW : GL.STATIC_DRAW); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		_data = null; | ||||||
|  | 		SystemImpl.gl.deleteBuffer(buffer); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function lock(?start: Int, ?count: Int): Float32Array { | ||||||
|  | 		lockStart = start != null ? start : 0; | ||||||
|  | 		lockEnd = count != null ? start + count : mySize; | ||||||
|  | 		return _data.subarray(lockStart * stride(), lockEnd * stride()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(?count: Int): Void { | ||||||
|  | 		if (count != null) | ||||||
|  | 			lockEnd = lockStart + count; | ||||||
|  | 		SystemImpl.gl.bindBuffer(GL.ARRAY_BUFFER, buffer); | ||||||
|  | 		if (SystemImpl.safari) { | ||||||
|  | 			SystemImpl.gl.bufferData(GL.ARRAY_BUFFER, _data.subarray(0 * stride(), lockEnd * stride()), GL.DYNAMIC_DRAW); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.gl.bufferSubData(GL.ARRAY_BUFFER, lockStart * stride(), _data.subarray(lockStart * stride(), lockEnd * stride())); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function stride(): Int { | ||||||
|  | 		return myStride; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function count(): Int { | ||||||
|  | 		return mySize; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function set(offset: Int): Int { | ||||||
|  | 		var ext: Dynamic = SystemImpl.gl2 ? true : SystemImpl.gl.getExtension("ANGLE_instanced_arrays"); | ||||||
|  | 		SystemImpl.gl.bindBuffer(GL.ARRAY_BUFFER, buffer); | ||||||
|  | 		var attributesOffset = 0; | ||||||
|  | 		for (i in 0...sizes.length) { | ||||||
|  | 			if (sizes[i] > 4) { | ||||||
|  | 				var size = sizes[i]; | ||||||
|  | 				var addonOffset = 0; | ||||||
|  | 				while (size > 0) { | ||||||
|  | 					SystemImpl.gl.enableVertexAttribArray(offset + attributesOffset); | ||||||
|  | 					SystemImpl.gl.vertexAttribPointer(offset + attributesOffset, 4, GL.FLOAT, false, myStride, offsets[i] + addonOffset); | ||||||
|  | 					if (ext) { | ||||||
|  | 						if (SystemImpl.gl2) { | ||||||
|  | 							untyped SystemImpl.gl.vertexAttribDivisor(offset + attributesOffset, instanceDataStepRate); | ||||||
|  | 						} | ||||||
|  | 						else { | ||||||
|  | 							ext.vertexAttribDivisorANGLE(offset + attributesOffset, instanceDataStepRate); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					size -= 4; | ||||||
|  | 					addonOffset += 4 * 4; | ||||||
|  | 					++attributesOffset; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				var normalized = types[i] == GL.FLOAT ? false : true; | ||||||
|  | 				SystemImpl.gl.enableVertexAttribArray(offset + attributesOffset); | ||||||
|  | 				SystemImpl.gl.vertexAttribPointer(offset + attributesOffset, sizes[i], types[i], normalized, myStride, offsets[i]); | ||||||
|  | 				if (ext) { | ||||||
|  | 					if (SystemImpl.gl2) { | ||||||
|  | 						untyped SystemImpl.gl.vertexAttribDivisor(offset + attributesOffset, instanceDataStepRate); | ||||||
|  | 					} | ||||||
|  | 					else { | ||||||
|  | 						ext.vertexAttribDivisorANGLE(offset + attributesOffset, instanceDataStepRate); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				++attributesOffset; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return attributesOffset; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								Kha/Backends/HTML5/kha/graphics4/VertexShader.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								Kha/Backends/HTML5/kha/graphics4/VertexShader.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | |||||||
|  | package kha.graphics4; | ||||||
|  |  | ||||||
|  | import js.html.webgl.GL; | ||||||
|  |  | ||||||
|  | class VertexShader { | ||||||
|  | 	public var sources: Array<String>; | ||||||
|  | 	public var type: Dynamic; | ||||||
|  | 	public var shader: Dynamic; | ||||||
|  | 	public var files: Array<String>; | ||||||
|  |  | ||||||
|  | 	public function new(sources: Array<Blob>, files: Array<String>) { | ||||||
|  | 		this.sources = []; | ||||||
|  | 		for (source in sources) { | ||||||
|  | 			this.sources.push(source.toString()); | ||||||
|  | 		} | ||||||
|  | 		this.type = GL.VERTEX_SHADER; | ||||||
|  | 		this.shader = null; | ||||||
|  | 		this.files = files; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromSource(source: String): VertexShader { | ||||||
|  | 		var shader = new VertexShader([], ["runtime-string"]); | ||||||
|  | 		shader.sources.push(source); | ||||||
|  | 		return shader; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function delete(): Void { | ||||||
|  | 		SystemImpl.gl.deleteShader(shader); | ||||||
|  | 		shader = null; | ||||||
|  | 		sources = null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										76
									
								
								Kha/Backends/HTML5/kha/input/MouseImpl.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								Kha/Backends/HTML5/kha/input/MouseImpl.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | |||||||
|  | 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.khanvas.style.cursor = "none"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function showSystemCursor(): Void { | ||||||
|  | 		SystemImpl.khanvas.style.cursor = "default"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function setSystemCursor(cursor: MouseCursor): Void { | ||||||
|  | 		SystemImpl.khanvas.style.cursor = switch (cursor) { | ||||||
|  | 			case Default: "default"; | ||||||
|  | 			case Pointer: "pointer"; | ||||||
|  | 			case Text: "text"; | ||||||
|  | 			case EastWestResize: "ew-resize"; | ||||||
|  | 			case NorthSouthResize: "ns-resize"; | ||||||
|  | 			case NorthEastResize: "ne-resize"; | ||||||
|  | 			case SouthEastResize: "se-resize"; | ||||||
|  | 			case NorthWestResize: "nw-resize"; | ||||||
|  | 			case SouthWestResize: "sw-resize"; | ||||||
|  | 			case Grab: "grab"; | ||||||
|  | 			case Grabbing: "grabbing"; | ||||||
|  | 			case NotAllowed: "not-allowed"; | ||||||
|  | 			case Wait: "wait"; | ||||||
|  | 			case Crosshair: "crosshair"; | ||||||
|  | 			case Custom(image): | ||||||
|  | 				var canvas = js.Browser.document.createCanvasElement(); | ||||||
|  | 				canvas.width = image.width; | ||||||
|  | 				canvas.height = image.height; | ||||||
|  | 				if (Std.isOfType(image, WebGLImage)) { | ||||||
|  | 					canvas.getContext2d().drawImage(cast(image, WebGLImage).image, 0, 0); | ||||||
|  | 				} | ||||||
|  | 				else { | ||||||
|  | 					canvas.getContext2d().drawImage(cast(image, CanvasImage).image, 0, 0); | ||||||
|  | 				} | ||||||
|  | 				var dataURL = canvas.toDataURL("image/png"); | ||||||
|  | 				dataURL = StringTools.replace(dataURL, "/^data:image\\/(png|jpg);base64,/", ""); | ||||||
|  |  | ||||||
|  | 				'url(\'$dataURL\'),auto'; | ||||||
|  | 			default: "default"; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										37
									
								
								Kha/Backends/HTML5/kha/input/Sensor.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Kha/Backends/HTML5/kha/input/Sensor.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | |||||||
|  | package kha.input; | ||||||
|  |  | ||||||
|  | import kha.SystemImpl; | ||||||
|  |  | ||||||
|  | class Sensor { | ||||||
|  | 	static var isInited: Bool = false; | ||||||
|  | 	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 { | ||||||
|  | 		if (!isInited) { | ||||||
|  | 			SystemImpl.initSensor(); | ||||||
|  | 			isInited = true; | ||||||
|  | 		} | ||||||
|  | 		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); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								Kha/Backends/HTML5/kha/js/AEAudioChannel.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								Kha/Backends/HTML5/kha/js/AEAudioChannel.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | package kha.js; | ||||||
|  |  | ||||||
|  | import js.html.AudioElement; | ||||||
|  | import kha.audio1.AudioChannel; | ||||||
|  |  | ||||||
|  | class AEAudioChannel implements kha.audio1.AudioChannel { | ||||||
|  | 	var element: AudioElement; | ||||||
|  | 	var stopped = false; | ||||||
|  | 	var looping: Bool; | ||||||
|  |  | ||||||
|  | 	public function new(element: AudioElement, looping: Bool) { | ||||||
|  | 		this.element = element; | ||||||
|  | 		this.looping = looping; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function play(): Void { | ||||||
|  | 		stopped = false; | ||||||
|  | 		element.play(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function pause(): Void { | ||||||
|  | 		try { | ||||||
|  | 			element.pause(); | ||||||
|  | 		} | ||||||
|  | 		catch (e:Dynamic) { | ||||||
|  | 			trace(e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function stop(): Void { | ||||||
|  | 		try { | ||||||
|  | 			element.pause(); | ||||||
|  | 			element.currentTime = 0; | ||||||
|  | 			stopped = true; | ||||||
|  | 		} | ||||||
|  | 		catch (e:Dynamic) { | ||||||
|  | 			trace(e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var length(get, never): Float; // Seconds | ||||||
|  |  | ||||||
|  | 	function get_length(): Float { | ||||||
|  | 		if (Math.isFinite(element.duration)) { | ||||||
|  | 			return element.duration; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			return Math.POSITIVE_INFINITY; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var position(get, set): Float; // Seconds | ||||||
|  |  | ||||||
|  | 	function get_position(): Float { | ||||||
|  | 		return element.currentTime; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_position(value: Float): Float { | ||||||
|  | 		return element.currentTime = value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var volume(get, set): Float; | ||||||
|  |  | ||||||
|  | 	function get_volume(): Float { | ||||||
|  | 		return element.volume; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_volume(value: Float): Float { | ||||||
|  | 		return element.volume = value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var finished(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	function get_finished(): Bool { | ||||||
|  | 		return stopped || (!looping && position >= length); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								Kha/Backends/HTML5/kha/js/AudioElementAudio.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Kha/Backends/HTML5/kha/js/AudioElementAudio.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | package kha.js; | ||||||
|  |  | ||||||
|  | @:keep | ||||||
|  | class AudioElementAudio { | ||||||
|  | 	public static function play(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel { | ||||||
|  | 		return stream(sound, loop); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function stream(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel { | ||||||
|  | 		sound.element.loop = loop; | ||||||
|  | 		var channel = new AEAudioChannel(sound.element, loop); | ||||||
|  | 		channel.play(); | ||||||
|  | 		return cast channel; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										264
									
								
								Kha/Backends/HTML5/kha/js/CanvasGraphics.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								Kha/Backends/HTML5/kha/js/CanvasGraphics.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,264 @@ | |||||||
|  | package kha.js; | ||||||
|  |  | ||||||
|  | import kha.Color; | ||||||
|  | import kha.graphics2.Graphics; | ||||||
|  | import kha.graphics2.ImageScaleQuality; | ||||||
|  | import kha.math.FastMatrix3; | ||||||
|  | import js.html.CanvasRenderingContext2D; | ||||||
|  |  | ||||||
|  | class CanvasGraphics extends Graphics { | ||||||
|  | 	var canvas: CanvasRenderingContext2D; | ||||||
|  | 	var webfont: kha.js.Font; | ||||||
|  | 	var myColor: Color; | ||||||
|  | 	var scaleQuality: ImageScaleQuality; | ||||||
|  | 	var clipping: Bool = false; | ||||||
|  |  | ||||||
|  | 	static var instance: CanvasGraphics; | ||||||
|  |  | ||||||
|  | 	public function new(canvas: CanvasRenderingContext2D) { | ||||||
|  | 		super(); | ||||||
|  | 		this.canvas = canvas; | ||||||
|  | 		instance = this; | ||||||
|  | 		myColor = Color.fromBytes(0, 0, 0); | ||||||
|  | 		// webfont = new Font("Arial", new FontStyle(false, false, false), 12); | ||||||
|  | 		// canvas.globalCompositeOperation = "normal"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function stringWidth(font: kha.Font, text: String): Float { | ||||||
|  | 		if (instance == null) | ||||||
|  | 			return 5 * text.length; | ||||||
|  | 		else { | ||||||
|  | 			instance.font = font; | ||||||
|  | 			return instance.canvas.measureText(text).width; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function begin(clear: Bool = true, clearColor: Color = null): Void { | ||||||
|  | 		if (clear) | ||||||
|  | 			this.clear(clearColor); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function clear(color: Color = null): Void { | ||||||
|  | 		if (color == null) | ||||||
|  | 			color = 0x00000000; | ||||||
|  | 		canvas.strokeStyle = "rgba(" + color.Rb + "," + color.Gb + "," + color.Bb + "," + color.A + ")"; | ||||||
|  | 		canvas.fillStyle = "rgba(" + color.Rb + "," + color.Gb + "," + color.Bb + "," + color.A + ")"; | ||||||
|  | 		if (color.A == 0) // if color is transparent, clear the screen. Note: in Canvas, transparent colors will overlay, not overwrite. | ||||||
|  | 			canvas.clearRect(0, 0, canvas.canvas.width, canvas.canvas.height); | ||||||
|  | 		else | ||||||
|  | 			canvas.fillRect(0, 0, canvas.canvas.width, canvas.canvas.height); | ||||||
|  | 		this.color = myColor; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function end(): Void {} | ||||||
|  |  | ||||||
|  | 	/*override public function translate(x: Float, y: Float) { | ||||||
|  | 		tx = x; | ||||||
|  | 		ty = y; | ||||||
|  | 	}*/ | ||||||
|  | 	override public function drawImage(img: kha.Image, x: Float, y: Float) { | ||||||
|  | 		canvas.globalAlpha = opacity; | ||||||
|  | 		canvas.drawImage(cast(img, CanvasImage).image, x, y); | ||||||
|  | 		canvas.globalAlpha = 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function drawScaledSubImage(image: kha.Image, sx: Float, sy: Float, sw: Float, sh: Float, dx: Float, dy: Float, dw: Float, dh: Float) { | ||||||
|  | 		canvas.globalAlpha = opacity; | ||||||
|  | 		try { | ||||||
|  | 			if (dw < 0 || dh < 0) { | ||||||
|  | 				canvas.save(); | ||||||
|  | 				canvas.translate(dx, dy); | ||||||
|  | 				var x = 0.0; | ||||||
|  | 				var y = 0.0; | ||||||
|  | 				if (dw < 0) { | ||||||
|  | 					canvas.scale(-1, 1); | ||||||
|  | 					x = -dw; | ||||||
|  | 				} | ||||||
|  | 				if (dh < 0) { | ||||||
|  | 					canvas.scale(1, -1); | ||||||
|  | 					y = -dh; | ||||||
|  | 				} | ||||||
|  | 				canvas.drawImage(cast(image, CanvasImage).image, sx, sy, sw, sh, x, y, dw, dh); | ||||||
|  | 				canvas.restore(); | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				canvas.drawImage(cast(image, CanvasImage).image, sx, sy, sw, sh, dx, dy, dw, dh); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		catch (ex:Dynamic) {} | ||||||
|  | 		canvas.globalAlpha = 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function set_color(color: Color): Color { | ||||||
|  | 		myColor = color; | ||||||
|  | 		canvas.strokeStyle = "rgba(" + color.Rb + "," + color.Gb + "," + color.Bb + "," + color.A + ")"; | ||||||
|  | 		canvas.fillStyle = "rgba(" + color.Rb + "," + color.Gb + "," + color.Bb + "," + color.A + ")"; | ||||||
|  | 		return color; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_color(): Color { | ||||||
|  | 		return myColor; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_imageScaleQuality(): ImageScaleQuality { | ||||||
|  | 		return scaleQuality; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function set_imageScaleQuality(value: ImageScaleQuality): ImageScaleQuality { | ||||||
|  | 		if (value == ImageScaleQuality.Low) { | ||||||
|  | 			untyped canvas.mozImageSmoothingEnabled = false; | ||||||
|  | 			untyped canvas.webkitImageSmoothingEnabled = false; | ||||||
|  | 			untyped canvas.msImageSmoothingEnabled = false; | ||||||
|  | 			canvas.imageSmoothingEnabled = false; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			untyped canvas.mozImageSmoothingEnabled = true; | ||||||
|  | 			untyped canvas.webkitImageSmoothingEnabled = true; | ||||||
|  | 			untyped canvas.msImageSmoothingEnabled = true; | ||||||
|  | 			canvas.imageSmoothingEnabled = true; | ||||||
|  | 		} | ||||||
|  | 		return scaleQuality = value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function drawRect(x: Float, y: Float, width: Float, height: Float, strength: Float = 1.0) { | ||||||
|  | 		canvas.beginPath(); | ||||||
|  | 		var oldStrength = canvas.lineWidth; | ||||||
|  | 		canvas.lineWidth = Math.round(strength); | ||||||
|  | 		canvas.rect(x, y, width, height); | ||||||
|  | 		canvas.stroke(); | ||||||
|  | 		canvas.lineWidth = oldStrength; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function fillRect(x: Float, y: Float, width: Float, height: Float) { | ||||||
|  | 		canvas.globalAlpha = opacity * myColor.A; | ||||||
|  | 		canvas.fillRect(x, y, width, height); | ||||||
|  | 		canvas.globalAlpha = opacity; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function drawArc(cx: Float, cy: Float, radius: Float, sAngle: Float, eAngle: Float, strength: Float = 1.0, ccw: Bool = false) { | ||||||
|  | 		_drawArc(cx, cy, radius, sAngle, eAngle, strength, ccw); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function drawCircle(cx: Float, cy: Float, radius: Float, strength: Float = 1.0) { | ||||||
|  | 		_drawArc(cx, cy, radius, 0, 2 * Math.PI, strength, false); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	inline function _drawArc(cx: Float, cy: Float, radius: Float, sAngle: Float, eAngle: Float, strength: Float, ccw: Bool) { | ||||||
|  | 		canvas.beginPath(); | ||||||
|  | 		var oldStrength = canvas.lineWidth; | ||||||
|  | 		canvas.lineWidth = Math.round(strength); | ||||||
|  | 		canvas.arc(cx, cy, radius, sAngle, eAngle, ccw); | ||||||
|  | 		canvas.stroke(); | ||||||
|  | 		canvas.lineWidth = oldStrength; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function fillArc(cx: Float, cy: Float, radius: Float, sAngle: Float, eAngle: Float, ccw: Bool = false) { | ||||||
|  | 		canvas.beginPath(); | ||||||
|  | 		canvas.arc(cx, cy, radius, sAngle, eAngle, ccw); | ||||||
|  | 		canvas.fill(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function fillCircle(cx: Float, cy: Float, radius: Float) { | ||||||
|  | 		canvas.beginPath(); | ||||||
|  | 		canvas.arc(cx, cy, radius, 0, 2 * Math.PI, false); | ||||||
|  | 		canvas.fill(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var bakedQuadCache = new kha.Kravur.AlignedQuad(); | ||||||
|  |  | ||||||
|  | 	override public function drawString(text: String, x: Float, y: Float) { | ||||||
|  | 		// canvas.fillText(text, tx + x, ty + y + webfont.getHeight()); | ||||||
|  | 		// canvas.drawImage(cast(webfont.getTexture(), Image).image, 0, 0, 50, 50, tx + x, ty + y, 50, 50); | ||||||
|  |  | ||||||
|  | 		var image = webfont.getImage(fontSize, myColor); | ||||||
|  | 		if (image.width > 0) { | ||||||
|  | 			// the image created in getImage() is not imediately useable | ||||||
|  | 			var xpos = x; | ||||||
|  | 			var ypos = y; | ||||||
|  | 			for (i in 0...text.length) { | ||||||
|  | 				var q = webfont.kravur._get(fontSize).getBakedQuad(bakedQuadCache, kha.graphics2.Graphics.fontGlyphs.indexOf(text.charCodeAt(i)), xpos, ypos); | ||||||
|  |  | ||||||
|  | 				if (q != null) { | ||||||
|  | 					if (q.s1 - q.s0 > 0 && q.t1 - q.t0 > 0 && q.x1 - q.x0 > 0 && q.y1 - q.y0 > 0) | ||||||
|  | 						canvas.drawImage(image, q.s0 * image.width, q.t0 * image.height, (q.s1 - q.s0) * image.width, (q.t1 - q.t0) * image.height, q.x0, | ||||||
|  | 							q.y0, q.x1 - q.x0, q.y1 - q.y0); | ||||||
|  | 					xpos += q.xadvance; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function drawCharacters(text: Array<Int>, start: Int, length: Int, x: Float, y: Float): Void { | ||||||
|  | 		var image = webfont.getImage(fontSize, myColor); | ||||||
|  | 		if (image.width > 0) { | ||||||
|  | 			// the image created in getImage() is not imediately useable | ||||||
|  | 			var xpos = x; | ||||||
|  | 			var ypos = y; | ||||||
|  | 			for (i in start...start + length) { | ||||||
|  | 				var q = webfont.kravur._get(fontSize).getBakedQuad(bakedQuadCache, kha.graphics2.Graphics.fontGlyphs.indexOf(text[i]), xpos, ypos); | ||||||
|  |  | ||||||
|  | 				if (q != null) { | ||||||
|  | 					if (q.s1 - q.s0 > 0 && q.t1 - q.t0 > 0 && q.x1 - q.x0 > 0 && q.y1 - q.y0 > 0) | ||||||
|  | 						canvas.drawImage(image, q.s0 * image.width, q.t0 * image.height, (q.s1 - q.s0) * image.width, (q.t1 - q.t0) * image.height, q.x0, | ||||||
|  | 							q.y0, q.x1 - q.x0, q.y1 - q.y0); | ||||||
|  | 					xpos += q.xadvance; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function set_font(font: kha.Font): kha.Font { | ||||||
|  | 		webfont = cast(font, kha.js.Font); | ||||||
|  | 		// canvas.font = webfont.size + "px " + webfont.name; | ||||||
|  | 		return cast webfont; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_font(): kha.Font { | ||||||
|  | 		return cast webfont; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function drawLine(x1: Float, y1: Float, x2: Float, y2: Float, strength: Float = 1.0) { | ||||||
|  | 		canvas.beginPath(); | ||||||
|  | 		var oldWith = canvas.lineWidth; | ||||||
|  | 		canvas.lineWidth = Math.round(strength); | ||||||
|  | 		canvas.moveTo(x1, y1); | ||||||
|  | 		canvas.lineTo(x2, y2); | ||||||
|  | 		canvas.moveTo(0, 0); | ||||||
|  | 		canvas.stroke(); | ||||||
|  | 		canvas.lineWidth = oldWith; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function fillTriangle(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float) { | ||||||
|  | 		canvas.beginPath(); | ||||||
|  | 		canvas.moveTo(x1, y1); | ||||||
|  | 		canvas.lineTo(x2, y2); | ||||||
|  | 		canvas.lineTo(x3, y3); | ||||||
|  | 		canvas.closePath(); | ||||||
|  | 		canvas.fill(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function scissor(x: Int, y: Int, width: Int, height: Int): Void { | ||||||
|  | 		if (!clipping) { | ||||||
|  | 			canvas.save(); | ||||||
|  | 			clipping = true; | ||||||
|  | 		} | ||||||
|  | 		canvas.beginPath(); | ||||||
|  | 		canvas.rect(x, y, width, height); | ||||||
|  | 		canvas.clip(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function disableScissor(): Void { | ||||||
|  | 		if (clipping) { | ||||||
|  | 			canvas.restore(); | ||||||
|  | 			clipping = false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function drawVideo(video: kha.Video, x: Float, y: Float, width: Float, height: Float): Void { | ||||||
|  | 		canvas.drawImage(cast(video, Video).element, x, y, width, height); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function setTransformation(transformation: FastMatrix3): Void { | ||||||
|  | 		canvas.setTransform(transformation._00, transformation._01, transformation._10, transformation._11, transformation._20, transformation._21); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								Kha/Backends/HTML5/kha/js/Font.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								Kha/Backends/HTML5/kha/js/Font.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | package kha.js; | ||||||
|  |  | ||||||
|  | import js.Syntax; | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import js.Browser; | ||||||
|  | import js.html.ImageElement; | ||||||
|  | import kha.Color; | ||||||
|  | import kha.Kravur; | ||||||
|  |  | ||||||
|  | @:keepInit | ||||||
|  | class Font implements Resource { | ||||||
|  | 	public var kravur: Kravur; | ||||||
|  |  | ||||||
|  | 	var images: Map<Int, Map<Int, ImageElement>> = new Map(); | ||||||
|  |  | ||||||
|  | 	public function new(blob: Blob) { | ||||||
|  | 		this.kravur = Syntax.code("new kha_js_Font.Kravur(blob);"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromBytes(bytes: Bytes): Font { | ||||||
|  | 		return new Font(Blob.fromBytes(bytes)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function height(fontSize: Int): Float { | ||||||
|  | 		return kravur._get(fontSize).getHeight(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function width(fontSize: Int, str: String): Float { | ||||||
|  | 		return kravur._get(fontSize).stringWidth(str); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function widthOfCharacters(fontSize: Int, characters: Array<Int>, start: Int, length: Int): Float { | ||||||
|  | 		return kravur._get(fontSize).charactersWidth(characters, start, length); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function baseline(fontSize: Int): Float { | ||||||
|  | 		return kravur._get(fontSize).getBaselinePosition(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function getImage(fontSize: Int, color: Color): ImageElement { | ||||||
|  | 		var glyphs = kha.graphics2.Graphics.fontGlyphs; | ||||||
|  | 		var imageIndex = fontSize * 10000 + glyphs.length; | ||||||
|  | 		if (!images.exists(imageIndex)) { | ||||||
|  | 			images[imageIndex] = new Map(); | ||||||
|  | 		} | ||||||
|  | 		if (!images[imageIndex].exists(color.value)) { | ||||||
|  | 			var kravur = this.kravur._get(fontSize); | ||||||
|  | 			var canvas = Browser.document.createCanvasElement(); | ||||||
|  | 			canvas.width = kravur.width; | ||||||
|  | 			canvas.height = kravur.height; | ||||||
|  | 			var ctx = canvas.getContext("2d"); | ||||||
|  | 			ctx.fillStyle = "black"; | ||||||
|  | 			ctx.fillRect(0, 0, kravur.width, kravur.height); | ||||||
|  |  | ||||||
|  | 			var imageData = ctx.getImageData(0, 0, kravur.width, kravur.height); | ||||||
|  | 			var bytes = cast(kravur.getTexture(), CanvasImage).bytes; | ||||||
|  | 			for (i in 0...bytes.length) { | ||||||
|  | 				imageData.data[i * 4 + 0] = color.Rb; | ||||||
|  | 				imageData.data[i * 4 + 1] = color.Gb; | ||||||
|  | 				imageData.data[i * 4 + 2] = color.Bb; | ||||||
|  | 				imageData.data[i * 4 + 3] = bytes.get(i); | ||||||
|  | 			} | ||||||
|  | 			ctx.putImageData(imageData, 0, 0); | ||||||
|  |  | ||||||
|  | 			var img = Browser.document.createImageElement(); | ||||||
|  | 			img.src = canvas.toDataURL("image/png"); | ||||||
|  | 			images[imageIndex][color.value] = img; | ||||||
|  | 			return img; | ||||||
|  | 		} | ||||||
|  | 		return images[imageIndex][color.value]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unload(): Void { | ||||||
|  | 		kravur = null; | ||||||
|  | 		images = null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								Kha/Backends/HTML5/kha/js/MobileWebAudio.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								Kha/Backends/HTML5/kha/js/MobileWebAudio.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | |||||||
|  | package kha.js; | ||||||
|  |  | ||||||
|  | import js.Syntax; | ||||||
|  | import js.html.audio.AudioContext; | ||||||
|  |  | ||||||
|  | @:keep | ||||||
|  | class MobileWebAudio { | ||||||
|  | 	@:noCompletion public static var _context: AudioContext; | ||||||
|  |  | ||||||
|  | 	@:noCompletion public static function _init(): Void { | ||||||
|  | 		try { | ||||||
|  | 			_context = new AudioContext(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		catch (e:Dynamic) {} | ||||||
|  | 		try { | ||||||
|  | 			Syntax.code("this._context = new webkitAudioContext();"); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		catch (e:Dynamic) {} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function play(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel { | ||||||
|  | 		var channel = new MobileWebAudioChannel(cast sound, loop); | ||||||
|  | 		channel.play(); | ||||||
|  | 		return channel; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function stream(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel { | ||||||
|  | 		return play(sound, loop); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										105
									
								
								Kha/Backends/HTML5/kha/js/MobileWebAudioChannel.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								Kha/Backends/HTML5/kha/js/MobileWebAudioChannel.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | |||||||
|  | package kha.js; | ||||||
|  |  | ||||||
|  | import js.html.audio.AudioBuffer; | ||||||
|  | import js.html.audio.AudioBufferSourceNode; | ||||||
|  | import js.html.audio.GainNode; | ||||||
|  |  | ||||||
|  | class MobileWebAudioChannel implements kha.audio1.AudioChannel { | ||||||
|  | 	var buffer: AudioBuffer; | ||||||
|  | 	var loop: Bool; | ||||||
|  | 	var source: AudioBufferSourceNode; | ||||||
|  | 	var gain: GainNode; | ||||||
|  | 	var startTime: Float; | ||||||
|  | 	var pauseTime: Float; | ||||||
|  | 	var paused: Bool = false; | ||||||
|  | 	var stopped: Bool = false; | ||||||
|  |  | ||||||
|  | 	public function new(sound: MobileWebAudioSound, loop: Bool) { | ||||||
|  | 		this.buffer = sound._buffer; | ||||||
|  | 		this.loop = loop; | ||||||
|  | 		createSource(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function createSource(): Void { | ||||||
|  | 		source = MobileWebAudio._context.createBufferSource(); | ||||||
|  | 		source.loop = loop; | ||||||
|  | 		source.buffer = buffer; | ||||||
|  | 		source.onended = function() { | ||||||
|  | 			stopped = true; | ||||||
|  | 		} | ||||||
|  | 		gain = MobileWebAudio._context.createGain(); | ||||||
|  | 		source.connect(gain); | ||||||
|  | 		gain.connect(MobileWebAudio._context.destination); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function play(): Void { | ||||||
|  | 		if (paused || stopped) { | ||||||
|  | 			createSource(); | ||||||
|  | 		} | ||||||
|  | 		stopped = false; | ||||||
|  | 		if (paused) { | ||||||
|  | 			paused = false; | ||||||
|  | 			startTime = MobileWebAudio._context.currentTime - pauseTime; | ||||||
|  | 			source.start(0, pauseTime); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			startTime = MobileWebAudio._context.currentTime; | ||||||
|  | 			source.start(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function pause(): Void { | ||||||
|  | 		final wasStopped = paused || stopped; | ||||||
|  | 		pauseTime = MobileWebAudio._context.currentTime - startTime; | ||||||
|  | 		paused = true; | ||||||
|  | 		if (wasStopped) | ||||||
|  | 			return; | ||||||
|  | 		source.stop(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function stop(): Void { | ||||||
|  | 		final wasStopped = paused || stopped; | ||||||
|  | 		paused = false; | ||||||
|  | 		stopped = true; | ||||||
|  | 		if (wasStopped) | ||||||
|  | 			return; | ||||||
|  | 		source.stop(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var length(get, never): Float; // Seconds | ||||||
|  |  | ||||||
|  | 	function get_length(): Float { | ||||||
|  | 		return source.buffer.duration; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var position(get, set): Float; // Seconds | ||||||
|  |  | ||||||
|  | 	function get_position(): Float { | ||||||
|  | 		if (stopped) | ||||||
|  | 			return length; | ||||||
|  | 		if (paused) | ||||||
|  | 			return pauseTime; | ||||||
|  | 		else | ||||||
|  | 			return MobileWebAudio._context.currentTime - startTime; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_position(value: Float): Float { | ||||||
|  | 		return value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var volume(get, set): Float; | ||||||
|  |  | ||||||
|  | 	function get_volume(): Float { | ||||||
|  | 		return gain.gain.value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function set_volume(value: Float): Float { | ||||||
|  | 		return gain.gain.value = value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var finished(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	function get_finished(): Bool { | ||||||
|  | 		return stopped; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										37
									
								
								Kha/Backends/HTML5/kha/js/MobileWebAudioSound.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Kha/Backends/HTML5/kha/js/MobileWebAudioSound.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | |||||||
|  | package kha.js; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import js.html.XMLHttpRequest; | ||||||
|  |  | ||||||
|  | class MobileWebAudioSound extends kha.Sound { | ||||||
|  | 	public var _buffer: Dynamic; | ||||||
|  |  | ||||||
|  | 	public function new(filename: String, done: kha.Sound->Void, failed: AssetError->Void) { | ||||||
|  | 		super(); | ||||||
|  | 		var request = untyped new XMLHttpRequest(); | ||||||
|  | 		request.open("GET", filename, true); | ||||||
|  | 		request.responseType = "arraybuffer"; | ||||||
|  |  | ||||||
|  | 		request.onerror = function() { | ||||||
|  | 			failed({url: filename}); | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		request.onload = function() { | ||||||
|  | 			compressedData = Bytes.ofData(request.response); | ||||||
|  | 			uncompressedData = null; | ||||||
|  | 			MobileWebAudio._context.decodeAudioData(compressedData.getData(), function(buffer) { | ||||||
|  | 				length = buffer.duration; | ||||||
|  | 				channels = buffer.numberOfChannels; | ||||||
|  | 				_buffer = buffer; | ||||||
|  | 				done(this); | ||||||
|  | 			}, function() { | ||||||
|  | 				failed({url: filename, error: "Audio format not supported"}); | ||||||
|  | 			}); | ||||||
|  | 		}; | ||||||
|  | 		request.send(null); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function uncompress(done: Void->Void): Void { | ||||||
|  | 		done(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										132
									
								
								Kha/Backends/HTML5/kha/js/Sound.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								Kha/Backends/HTML5/kha/js/Sound.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,132 @@ | |||||||
|  | package kha.js; | ||||||
|  |  | ||||||
|  | import js.Browser; | ||||||
|  | import js.html.AudioElement; | ||||||
|  | import js.html.ErrorEvent; | ||||||
|  | import js.html.Event; | ||||||
|  | import js.html.MediaError; | ||||||
|  |  | ||||||
|  | using StringTools; | ||||||
|  |  | ||||||
|  | /*class SoundChannel extends kha.SoundChannel { | ||||||
|  | 	private var element: Dynamic; | ||||||
|  |  | ||||||
|  | 	public function new(element: Dynamic) { | ||||||
|  | 		super(); | ||||||
|  | 		this.element = element; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function play(): Void { | ||||||
|  | 		super.play(); | ||||||
|  | 		element.play(); | ||||||
|  | 	}  | ||||||
|  |  | ||||||
|  | 	override public function pause(): Void { | ||||||
|  | 		try { | ||||||
|  | 			element.pause(); | ||||||
|  | 		} | ||||||
|  | 		catch (e: Dynamic) { | ||||||
|  | 			trace(e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function stop(): Void { | ||||||
|  | 		try { | ||||||
|  | 			element.pause(); | ||||||
|  | 			element.currentTime = 0; | ||||||
|  | 			super.stop(); | ||||||
|  | 		} | ||||||
|  | 		catch (e: Dynamic) { | ||||||
|  | 			trace(e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function getCurrentPos(): Int { | ||||||
|  | 		return Math.ceil(element.currentTime * 1000);  // Miliseconds | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function getLength(): Int { | ||||||
|  | 		if (Math.isFinite(element.duration)) { | ||||||
|  | 			return Math.floor(element.duration * 1000); // Miliseconds | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | }*/ | ||||||
|  | class Sound extends kha.Sound { | ||||||
|  | 	var filenames: Array<String>; | ||||||
|  |  | ||||||
|  | 	static var loading: Array<Sound> = new Array(); | ||||||
|  |  | ||||||
|  | 	var done: kha.Sound->Void; | ||||||
|  | 	var failed: AssetError->Void; | ||||||
|  |  | ||||||
|  | 	public var element: AudioElement; | ||||||
|  |  | ||||||
|  | 	public function new(filenames: Array<String>, done: kha.Sound->Void, failed: AssetError->Void) { | ||||||
|  | 		super(); | ||||||
|  |  | ||||||
|  | 		this.done = done; | ||||||
|  | 		this.failed = failed; | ||||||
|  | 		loading.push(this); // prevent gc from removing this | ||||||
|  |  | ||||||
|  | 		element = Browser.document.createAudioElement(); | ||||||
|  |  | ||||||
|  | 		this.filenames = []; | ||||||
|  | 		for (filename in filenames) { | ||||||
|  | 			if (element.canPlayType("audio/ogg") != "" && filename.endsWith(".ogg")) | ||||||
|  | 				this.filenames.push(filename); | ||||||
|  | 			if (element.canPlayType("audio/mp4") != "" && filename.endsWith(".mp4")) | ||||||
|  | 				this.filenames.push(filename); | ||||||
|  | 			if (element.canPlayType("audio/wav") != "" && filename.endsWith(".wav")) | ||||||
|  | 				this.filenames.push(filename); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		element.addEventListener("error", errorListener, false); | ||||||
|  | 		element.addEventListener("canplay", canPlayThroughListener, false); | ||||||
|  |  | ||||||
|  | 		element.src = this.filenames[0]; | ||||||
|  | 		element.preload = "auto"; | ||||||
|  | 		element.load(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// override public function play(): kha.SoundChannel { | ||||||
|  | 	//	try { | ||||||
|  | 	//		element.play(); | ||||||
|  | 	//	} | ||||||
|  | 	//	catch (e: Dynamic) { | ||||||
|  | 	//		trace(e); | ||||||
|  | 	//	} | ||||||
|  | 	//	return new SoundChannel(element); | ||||||
|  | 	// } | ||||||
|  | 	function errorListener(eventInfo: ErrorEvent): Void { | ||||||
|  | 		if (element.error.code == MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) { | ||||||
|  | 			for (i in 0...filenames.length - 1) { | ||||||
|  | 				if (element.src == filenames[i]) { | ||||||
|  | 					// try loading with next extension: | ||||||
|  | 					element.src = filenames[i + 1]; | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		failed({url: element.src}); | ||||||
|  | 		finishAsset(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function canPlayThroughListener(eventInfo: Event): Void { | ||||||
|  | 		finishAsset(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function finishAsset() { | ||||||
|  | 		element.removeEventListener("error", errorListener, false); | ||||||
|  | 		element.removeEventListener("canplaythrough", canPlayThroughListener, false); | ||||||
|  | 		done(this); | ||||||
|  | 		loading.remove(this); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function uncompress(done: Void->Void): Void { | ||||||
|  | 		done(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										147
									
								
								Kha/Backends/HTML5/kha/js/Video.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								Kha/Backends/HTML5/kha/js/Video.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,147 @@ | |||||||
|  | package kha.js; | ||||||
|  |  | ||||||
|  | import js.Browser; | ||||||
|  | import js.html.ErrorEvent; | ||||||
|  | import js.html.Event; | ||||||
|  | import js.html.MediaError; | ||||||
|  | import js.html.VideoElement; | ||||||
|  |  | ||||||
|  | using StringTools; | ||||||
|  |  | ||||||
|  | class Video extends kha.Video { | ||||||
|  | 	public var element: VideoElement; | ||||||
|  | 	public var texture: Image; | ||||||
|  |  | ||||||
|  | 	var filenames: Array<String>; | ||||||
|  | 	var done: kha.Video->Void; | ||||||
|  |  | ||||||
|  | 	function new() { | ||||||
|  | 		super(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromElement(element: js.html.VideoElement): Video { | ||||||
|  | 		var video = new Video(); | ||||||
|  | 		video.element = element; | ||||||
|  | 		if (SystemImpl.gl != null) | ||||||
|  | 			video.texture = Image.fromVideo(video); | ||||||
|  | 		return video; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromFile(filenames: Array<String>, done: kha.Video->Void): Void { | ||||||
|  | 		var video = new Video(); | ||||||
|  |  | ||||||
|  | 		video.done = done; | ||||||
|  |  | ||||||
|  | 		video.element = cast Browser.document.createElement("video"); | ||||||
|  |  | ||||||
|  | 		video.filenames = []; | ||||||
|  | 		for (filename in filenames) { | ||||||
|  | 			if (video.element.canPlayType("video/webm") != "" && filename.endsWith(".webm")) | ||||||
|  | 				video.filenames.push(filename); | ||||||
|  | 			#if !kha_debug_html5 | ||||||
|  | 			if (video.element.canPlayType("video/mp4") != "" && filename.endsWith(".mp4")) | ||||||
|  | 				video.filenames.push(filename); | ||||||
|  | 			#end | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		video.element.addEventListener("error", video.errorListener, false); | ||||||
|  | 		video.element.addEventListener("canplaythrough", video.canPlayThroughListener, false); | ||||||
|  |  | ||||||
|  | 		video.element.preload = "auto"; | ||||||
|  | 		video.element.src = video.filenames[0]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function width(): Int { | ||||||
|  | 		return element.videoWidth; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function height(): Int { | ||||||
|  | 		return element.videoHeight; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function play(loop: Bool = false): Void { | ||||||
|  | 		try { | ||||||
|  | 			element.loop = loop; | ||||||
|  | 			element.play(); | ||||||
|  | 		} | ||||||
|  | 		catch (e:Dynamic) { | ||||||
|  | 			trace(e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function pause(): Void { | ||||||
|  | 		try { | ||||||
|  | 			element.pause(); | ||||||
|  | 		} | ||||||
|  | 		catch (e:Dynamic) { | ||||||
|  | 			trace(e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function stop(): Void { | ||||||
|  | 		try { | ||||||
|  | 			element.pause(); | ||||||
|  | 			element.currentTime = 0; | ||||||
|  | 		} | ||||||
|  | 		catch (e:Dynamic) { | ||||||
|  | 			trace(e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function getCurrentPos(): Int { | ||||||
|  | 		return Math.ceil(element.currentTime * 1000); // Miliseconds | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get_position(): Int { | ||||||
|  | 		return Math.ceil(element.currentTime * 1000); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function set_position(value: Int): Int { | ||||||
|  | 		element.currentTime = value / 1000; | ||||||
|  | 		return value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function getVolume(): Float { | ||||||
|  | 		return element.volume; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function setVolume(volume: Float): Void { | ||||||
|  | 		element.volume = volume; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function getLength(): Int { | ||||||
|  | 		if (Math.isFinite(element.duration)) { | ||||||
|  | 			return Math.floor(element.duration * 1000); // Miliseconds | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function errorListener(eventInfo: ErrorEvent): Void { | ||||||
|  | 		if (element.error.code == MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) { | ||||||
|  | 			for (i in 0...filenames.length - 1) { | ||||||
|  | 				if (element.src == filenames[i]) { | ||||||
|  | 					// try loading with next extension: | ||||||
|  | 					element.src = filenames[i + 1]; | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		trace("Error loading " + element.src); | ||||||
|  | 		finishAsset(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function canPlayThroughListener(eventInfo: Event): Void { | ||||||
|  | 		finishAsset(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function finishAsset() { | ||||||
|  | 		element.removeEventListener("error", errorListener, false); | ||||||
|  | 		element.removeEventListener("canplaythrough", canPlayThroughListener, false); | ||||||
|  | 		if (SystemImpl.gl != null) | ||||||
|  | 			texture = Image.fromVideo(this); | ||||||
|  | 		done(this); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										114
									
								
								Kha/Backends/HTML5/kha/js/WebAudioSound.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								Kha/Backends/HTML5/kha/js/WebAudioSound.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,114 @@ | |||||||
|  | package kha.js; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import js.Browser; | ||||||
|  | import js.html.XMLHttpRequest; | ||||||
|  | import kha.audio2.Audio; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | 	class WebAudioChannel extends kha.SoundChannel { | ||||||
|  | 	private var buffer: Dynamic; | ||||||
|  | 	private var startTime: Float; | ||||||
|  | 	private var offset: Float; | ||||||
|  | 	private var source: Dynamic; | ||||||
|  |  | ||||||
|  | 	public function new(buffer: Dynamic) { | ||||||
|  | 		super(); | ||||||
|  | 		this.offset = 0; | ||||||
|  | 		this.buffer = buffer; | ||||||
|  | 		this.startTime = Audio._context.currentTime;  | ||||||
|  | 		this.source = Audio._context.createBufferSource(); | ||||||
|  | 		this.source.buffer = this.buffer; | ||||||
|  | 		this.source.connect(Audio._context.destination); | ||||||
|  | 		this.source.start(0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function play(): Void { | ||||||
|  | 		if (source != null) return; | ||||||
|  | 		super.play(); | ||||||
|  | 		startTime = Audio._context.currentTime - offset; | ||||||
|  | 		source.start(0, offset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function pause(): Void { | ||||||
|  | 		source.stop(); | ||||||
|  | 		offset = Audio._context.currentTime - startTime; | ||||||
|  | 		startTime = -1; | ||||||
|  | 		source = null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function stop(): Void { | ||||||
|  | 		source.stop(); | ||||||
|  | 		source = null; | ||||||
|  | 		offset = 0; | ||||||
|  | 		startTime = -1; | ||||||
|  | 		super.stop(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function getCurrentPos(): Int { | ||||||
|  | 		if (startTime < 0) return Math.ceil(offset * 1000); | ||||||
|  | 		else return Math.ceil((Audio._context.currentTime - startTime) * 1000); //Miliseconds | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function getLength(): Int { | ||||||
|  | 		return Math.floor(buffer.duration * 1000); //Miliseconds | ||||||
|  | 	} | ||||||
|  | 	} | ||||||
|  |  */ | ||||||
|  | class WebAudioSound extends kha.Sound { | ||||||
|  | 	public function new(filename: String, done: kha.Sound->Void, failed: AssetError->Void) { | ||||||
|  | 		super(); | ||||||
|  | 		var request = untyped new XMLHttpRequest(); | ||||||
|  | 		request.open("GET", filename, true); | ||||||
|  | 		request.responseType = "arraybuffer"; | ||||||
|  |  | ||||||
|  | 		request.onerror = function() { | ||||||
|  | 			failed({url: filename}); | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		request.onload = function() { | ||||||
|  | 			compressedData = Bytes.ofData(request.response); | ||||||
|  | 			uncompressedData = null; | ||||||
|  | 			done(this); | ||||||
|  | 		}; | ||||||
|  | 		request.send(null); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function superUncompress(done: Void->Void): Void { | ||||||
|  | 		super.uncompress(done); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function uncompress(done: Void->Void): Void { | ||||||
|  | 		Audio._context.decodeAudioData(compressedData.getData(), function(buffer: js.html.audio.AudioBuffer) { | ||||||
|  | 			final ch0 = buffer.getChannelData(0); | ||||||
|  | 			final ch1 = buffer.numberOfChannels == 1 ? ch0 : buffer.getChannelData(1); | ||||||
|  | 			final len = ch0.length; | ||||||
|  | 			uncompressedData = new kha.arrays.Float32Array(len * 2); | ||||||
|  | 			length = buffer.duration; | ||||||
|  | 			channels = buffer.numberOfChannels; | ||||||
|  | 			sampleRate = Math.round(buffer.sampleRate); | ||||||
|  | 			var idx = 0; | ||||||
|  | 			var i = 0; | ||||||
|  | 			final lidx = len * 2; | ||||||
|  | 			function uncompressInner() { | ||||||
|  | 				var chk_len = idx + 11025; | ||||||
|  | 				var next_chk = chk_len > lidx ? lidx : chk_len; | ||||||
|  | 				while (idx < next_chk) { | ||||||
|  | 					uncompressedData[idx] = ch0[i]; | ||||||
|  | 					uncompressedData[idx + 1] = ch1[i]; | ||||||
|  | 					idx += 2; | ||||||
|  | 					++i; | ||||||
|  | 				} | ||||||
|  | 				if (idx < lidx) | ||||||
|  | 					js.Browser.window.setTimeout(uncompressInner, 0); | ||||||
|  | 				else { | ||||||
|  | 					compressedData = null; | ||||||
|  | 					done(); | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
|  | 			uncompressInner(); | ||||||
|  | 		}, function() { | ||||||
|  | 			superUncompress(done); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								Kha/Backends/HTML5/kha/js/graphics4/ConstantLocation.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Kha/Backends/HTML5/kha/js/graphics4/ConstantLocation.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | package kha.js.graphics4; | ||||||
|  |  | ||||||
|  | class ConstantLocation implements kha.graphics4.ConstantLocation { | ||||||
|  | 	public var value: Dynamic; | ||||||
|  | 	public var type: Int; | ||||||
|  |  | ||||||
|  | 	public function new(value: Dynamic, type: Int) { | ||||||
|  | 		this.value = value; | ||||||
|  | 		this.type = type; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										738
									
								
								Kha/Backends/HTML5/kha/js/graphics4/Graphics.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										738
									
								
								Kha/Backends/HTML5/kha/js/graphics4/Graphics.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,738 @@ | |||||||
|  | package kha.js.graphics4; | ||||||
|  |  | ||||||
|  | import js.html.webgl.GL2; | ||||||
|  | import kha.graphics4.StencilValue; | ||||||
|  | import kha.arrays.Float32Array; | ||||||
|  | import kha.arrays.Int32Array; | ||||||
|  | import js.html.webgl.GL; | ||||||
|  | import kha.graphics4.BlendingFactor; | ||||||
|  | import kha.graphics4.BlendingOperation; | ||||||
|  | import kha.graphics4.CompareMode; | ||||||
|  | import kha.graphics4.CubeMap; | ||||||
|  | import kha.graphics4.CullMode; | ||||||
|  | import kha.graphics4.IndexBuffer; | ||||||
|  | import kha.graphics4.MipMapFilter; | ||||||
|  | import kha.graphics4.PipelineState; | ||||||
|  | import kha.graphics4.StencilAction; | ||||||
|  | import kha.graphics4.TextureAddressing; | ||||||
|  | import kha.graphics4.TextureFilter; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  | import kha.graphics4.VertexBuffer; | ||||||
|  | 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.WebGLImage; | ||||||
|  |  | ||||||
|  | class Graphics implements kha.graphics4.Graphics { | ||||||
|  | 	var currentPipeline: PipelineState = null; | ||||||
|  | 	var depthTest: Bool = false; | ||||||
|  | 	var depthMask: Bool = false; | ||||||
|  | 	var colorMaskRed: Bool = true; | ||||||
|  | 	var colorMaskGreen: Bool = true; | ||||||
|  | 	var colorMaskBlue: Bool = true; | ||||||
|  | 	var colorMaskAlpha: Bool = true; | ||||||
|  | 	var indicesCount: Int; | ||||||
|  | 	var renderTarget: Canvas; | ||||||
|  | 	var renderTargetFrameBuffer: Dynamic; | ||||||
|  | 	var renderTargetMSAA: Dynamic; | ||||||
|  | 	var renderTargetTexture: Dynamic; | ||||||
|  | 	var isCubeMap: Bool = false; | ||||||
|  | 	var isDepthAttachment: Bool = false; | ||||||
|  | 	var instancedExtension: Dynamic; | ||||||
|  | 	var blendMinMaxExtension: Dynamic; | ||||||
|  |  | ||||||
|  | 	static var current: Graphics = null; | ||||||
|  | 	static var useVertexAttributes: Int = 0; | ||||||
|  |  | ||||||
|  | 	public function new(renderTarget: Canvas = null) { | ||||||
|  | 		this.renderTarget = renderTarget; | ||||||
|  | 		init(); | ||||||
|  | 		if (SystemImpl.gl2) { | ||||||
|  | 			instancedExtension = true; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			instancedExtension = SystemImpl.gl.getExtension("ANGLE_instanced_arrays"); | ||||||
|  | 			blendMinMaxExtension = SystemImpl.gl.getExtension("EXT_blend_minmax"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function init() { | ||||||
|  | 		if (renderTarget == null) | ||||||
|  | 			return; | ||||||
|  | 		isCubeMap = Std.isOfType(renderTarget, CubeMap); | ||||||
|  | 		if (isCubeMap) { | ||||||
|  | 			var cubeMap: CubeMap = cast(renderTarget, CubeMap); | ||||||
|  | 			renderTargetFrameBuffer = cubeMap.frameBuffer; | ||||||
|  | 			renderTargetTexture = cubeMap.texture; | ||||||
|  | 			isDepthAttachment = cubeMap.isDepthAttachment; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			var image: WebGLImage = cast(renderTarget, WebGLImage); | ||||||
|  | 			renderTargetFrameBuffer = image.frameBuffer; | ||||||
|  | 			renderTargetMSAA = image.MSAAFrameBuffer; | ||||||
|  | 			renderTargetTexture = image.texture; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function begin(additionalRenderTargets: Array<Canvas> = null): Void { | ||||||
|  | 		if (current == null) { | ||||||
|  | 			current = this; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			throw "End before you begin"; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		SystemImpl.gl.enable(GL.BLEND); | ||||||
|  | 		SystemImpl.gl.blendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA); | ||||||
|  | 		if (renderTarget == null) { | ||||||
|  | 			SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null); | ||||||
|  | 			SystemImpl.gl.viewport(0, 0, System.windowWidth(), System.windowHeight()); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, renderTargetFrameBuffer); | ||||||
|  | 			// if (isCubeMap) SystemImpl.gl.framebufferTexture(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_CUBE_MAP, renderTargetTexture, 0); // Layered | ||||||
|  | 			SystemImpl.gl.viewport(0, 0, renderTarget.width, renderTarget.height); | ||||||
|  | 			if (additionalRenderTargets != null) { | ||||||
|  | 				SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, SystemImpl.drawBuffers.COLOR_ATTACHMENT0_WEBGL, GL.TEXTURE_2D, renderTargetTexture, 0); | ||||||
|  | 				for (i in 0...additionalRenderTargets.length) { | ||||||
|  | 					SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, SystemImpl.drawBuffers.COLOR_ATTACHMENT0_WEBGL + i + 1, GL.TEXTURE_2D, | ||||||
|  | 						cast(additionalRenderTargets[i], WebGLImage).texture, 0); | ||||||
|  | 				} | ||||||
|  | 				var attachments = [SystemImpl.drawBuffers.COLOR_ATTACHMENT0_WEBGL]; | ||||||
|  | 				for (i in 0...additionalRenderTargets.length) { | ||||||
|  | 					attachments.push(SystemImpl.drawBuffers.COLOR_ATTACHMENT0_WEBGL + i + 1); | ||||||
|  | 				} | ||||||
|  | 				SystemImpl.gl2 ? untyped SystemImpl.gl.drawBuffers(attachments) : SystemImpl.drawBuffers.drawBuffersWEBGL(attachments); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function beginFace(face: Int): Void { | ||||||
|  | 		if (current == null) { | ||||||
|  | 			current = this; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			throw "End before you begin"; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		SystemImpl.gl.enable(GL.BLEND); | ||||||
|  | 		SystemImpl.gl.blendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA); | ||||||
|  | 		SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, renderTargetFrameBuffer); | ||||||
|  | 		SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, isDepthAttachment ? GL.DEPTH_ATTACHMENT : GL.COLOR_ATTACHMENT0, | ||||||
|  | 			GL.TEXTURE_CUBE_MAP_POSITIVE_X + face, renderTargetTexture, 0); | ||||||
|  | 		SystemImpl.gl.viewport(0, 0, renderTarget.width, renderTarget.height); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function beginEye(eye: Int): Void { | ||||||
|  | 		if (current == null) { | ||||||
|  | 			current = this; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			throw "End before you begin"; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		SystemImpl.gl.enable(GL.BLEND); | ||||||
|  | 		SystemImpl.gl.blendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA); | ||||||
|  | 		SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null); | ||||||
|  | 		if (eye == 0) { | ||||||
|  | 			SystemImpl.gl.viewport(0, 0, Std.int(System.windowWidth() * 0.5), System.windowHeight()); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.gl.viewport(Std.int(System.windowWidth() * 0.5), 0, Std.int(System.windowWidth() * 0.5), System.windowHeight()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function end(): Void { | ||||||
|  | 		if (current == this) { | ||||||
|  | 			current = null; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			throw "Begin before you end"; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (renderTargetMSAA != null) { | ||||||
|  | 			untyped SystemImpl.gl.bindFramebuffer(SystemImpl.gl.READ_FRAMEBUFFER, renderTargetFrameBuffer); | ||||||
|  | 			untyped SystemImpl.gl.bindFramebuffer(SystemImpl.gl.DRAW_FRAMEBUFFER, renderTargetMSAA); | ||||||
|  | 			untyped SystemImpl.gl.blitFramebuffer(0, 0, renderTarget.width, renderTarget.height, 0, 0, renderTarget.width, renderTarget.height, | ||||||
|  | 				GL.COLOR_BUFFER_BIT, GL.NEAREST); | ||||||
|  | 		} | ||||||
|  | 		#if (debug || kha_debug_html5) | ||||||
|  | 		var error = SystemImpl.gl.getError(); | ||||||
|  | 		switch (error) { | ||||||
|  | 			case GL.NO_ERROR: | ||||||
|  |  | ||||||
|  | 			case GL.INVALID_ENUM: | ||||||
|  | 				trace("WebGL error: Invalid enum"); | ||||||
|  | 			case GL.INVALID_VALUE: | ||||||
|  | 				trace("WebGL error: Invalid value"); | ||||||
|  | 			case GL.INVALID_OPERATION: | ||||||
|  | 				trace("WebGL error: Invalid operation"); | ||||||
|  | 			case GL.INVALID_FRAMEBUFFER_OPERATION: | ||||||
|  | 				trace("WebGL error: Invalid framebuffer operation"); | ||||||
|  | 			case GL.OUT_OF_MEMORY: | ||||||
|  | 				trace("WebGL error: Out of memory"); | ||||||
|  | 			case GL.CONTEXT_LOST_WEBGL: | ||||||
|  | 				trace("WebGL error: Context lost"); | ||||||
|  | 			default: | ||||||
|  | 				trace("Unknown WebGL error"); | ||||||
|  | 		} | ||||||
|  | 		#end | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function flush(): Void {} | ||||||
|  |  | ||||||
|  | 	public function vsynced(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function refreshRate(): Int { | ||||||
|  | 		return 60; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function clear(?color: Color, ?depth: Float, ?stencil: Int): Void { | ||||||
|  | 		var clearMask: Int = 0; | ||||||
|  | 		if (color != null) { | ||||||
|  | 			clearMask |= GL.COLOR_BUFFER_BIT; | ||||||
|  | 			SystemImpl.gl.colorMask(true, true, true, true); | ||||||
|  | 			SystemImpl.gl.clearColor(color.R, color.G, color.B, color.A); | ||||||
|  | 		} | ||||||
|  | 		if (depth != null) { | ||||||
|  | 			clearMask |= GL.DEPTH_BUFFER_BIT; | ||||||
|  | 			SystemImpl.gl.enable(GL.DEPTH_TEST); | ||||||
|  | 			SystemImpl.gl.depthMask(true); | ||||||
|  | 			SystemImpl.gl.clearDepth(depth); | ||||||
|  | 		} | ||||||
|  | 		if (stencil != null) { | ||||||
|  | 			clearMask |= GL.STENCIL_BUFFER_BIT; | ||||||
|  | 			SystemImpl.gl.enable(GL.STENCIL_TEST); | ||||||
|  | 			SystemImpl.gl.stencilMask(0xff); | ||||||
|  | 			SystemImpl.gl.clearStencil(stencil); | ||||||
|  | 		} | ||||||
|  | 		SystemImpl.gl.clear(clearMask); | ||||||
|  | 		SystemImpl.gl.colorMask(colorMaskRed, colorMaskGreen, colorMaskBlue, colorMaskAlpha); | ||||||
|  | 		if (depthTest) { | ||||||
|  | 			SystemImpl.gl.enable(GL.DEPTH_TEST); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.gl.disable(GL.DEPTH_TEST); | ||||||
|  | 		} | ||||||
|  | 		SystemImpl.gl.depthMask(depthMask); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function viewport(x: Int, y: Int, width: Int, height: Int): Void { | ||||||
|  | 		if (renderTarget == null) { | ||||||
|  | 			SystemImpl.gl.viewport(x, System.windowHeight(0) - y - height, width, height); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.gl.viewport(x, y, width, height); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function scissor(x: Int, y: Int, width: Int, height: Int): Void { | ||||||
|  | 		SystemImpl.gl.enable(GL.SCISSOR_TEST); | ||||||
|  | 		if (renderTarget == null) { | ||||||
|  | 			SystemImpl.gl.scissor(x, System.windowHeight(0) - y - height, width, height); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.gl.scissor(x, y, width, height); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function disableScissor(): Void { | ||||||
|  | 		SystemImpl.gl.disable(GL.SCISSOR_TEST); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setDepthMode(write: Bool, mode: CompareMode): Void { | ||||||
|  | 		switch (mode) { | ||||||
|  | 			case Always: | ||||||
|  | 				write ? SystemImpl.gl.enable(GL.DEPTH_TEST) : SystemImpl.gl.disable(GL.DEPTH_TEST); | ||||||
|  | 				depthTest = write; | ||||||
|  | 				SystemImpl.gl.depthFunc(GL.ALWAYS); | ||||||
|  | 			case Never: | ||||||
|  | 				SystemImpl.gl.enable(GL.DEPTH_TEST); | ||||||
|  | 				depthTest = true; | ||||||
|  | 				SystemImpl.gl.depthFunc(GL.NEVER); | ||||||
|  | 			case Equal: | ||||||
|  | 				SystemImpl.gl.enable(GL.DEPTH_TEST); | ||||||
|  | 				depthTest = true; | ||||||
|  | 				SystemImpl.gl.depthFunc(GL.EQUAL); | ||||||
|  | 			case NotEqual: | ||||||
|  | 				SystemImpl.gl.enable(GL.DEPTH_TEST); | ||||||
|  | 				depthTest = true; | ||||||
|  | 				SystemImpl.gl.depthFunc(GL.NOTEQUAL); | ||||||
|  | 			case Less: | ||||||
|  | 				SystemImpl.gl.enable(GL.DEPTH_TEST); | ||||||
|  | 				depthTest = true; | ||||||
|  | 				SystemImpl.gl.depthFunc(GL.LESS); | ||||||
|  | 			case LessEqual: | ||||||
|  | 				SystemImpl.gl.enable(GL.DEPTH_TEST); | ||||||
|  | 				depthTest = true; | ||||||
|  | 				SystemImpl.gl.depthFunc(GL.LEQUAL); | ||||||
|  | 			case Greater: | ||||||
|  | 				SystemImpl.gl.enable(GL.DEPTH_TEST); | ||||||
|  | 				depthTest = true; | ||||||
|  | 				SystemImpl.gl.depthFunc(GL.GREATER); | ||||||
|  | 			case GreaterEqual: | ||||||
|  | 				SystemImpl.gl.enable(GL.DEPTH_TEST); | ||||||
|  | 				depthTest = true; | ||||||
|  | 				SystemImpl.gl.depthFunc(GL.GEQUAL); | ||||||
|  | 		} | ||||||
|  | 		SystemImpl.gl.depthMask(write); | ||||||
|  | 		depthMask = write; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static function getBlendFunc(factor: BlendingFactor): Int { | ||||||
|  | 		switch (factor) { | ||||||
|  | 			case BlendZero, Undefined: | ||||||
|  | 				return GL.ZERO; | ||||||
|  | 			case BlendOne: | ||||||
|  | 				return GL.ONE; | ||||||
|  | 			case SourceAlpha: | ||||||
|  | 				return GL.SRC_ALPHA; | ||||||
|  | 			case DestinationAlpha: | ||||||
|  | 				return GL.DST_ALPHA; | ||||||
|  | 			case InverseSourceAlpha: | ||||||
|  | 				return GL.ONE_MINUS_SRC_ALPHA; | ||||||
|  | 			case InverseDestinationAlpha: | ||||||
|  | 				return GL.ONE_MINUS_DST_ALPHA; | ||||||
|  | 			case SourceColor: | ||||||
|  | 				return GL.SRC_COLOR; | ||||||
|  | 			case DestinationColor: | ||||||
|  | 				return GL.DST_COLOR; | ||||||
|  | 			case InverseSourceColor: | ||||||
|  | 				return GL.ONE_MINUS_SRC_COLOR; | ||||||
|  | 			case InverseDestinationColor: | ||||||
|  | 				return GL.ONE_MINUS_DST_COLOR; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static function getBlendOp(op: BlendingOperation): Int { | ||||||
|  | 		switch (op) { | ||||||
|  | 			case Add: | ||||||
|  | 				return GL.FUNC_ADD; | ||||||
|  | 			case Subtract: | ||||||
|  | 				return GL.FUNC_SUBTRACT; | ||||||
|  | 			case ReverseSubtract: | ||||||
|  | 				return GL.FUNC_REVERSE_SUBTRACT; | ||||||
|  | 			case Min: | ||||||
|  | 				return 0x8007; | ||||||
|  | 			case Max: | ||||||
|  | 				return 0x8008; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setBlendingMode(source: BlendingFactor, destination: BlendingFactor, operation: BlendingOperation, alphaSource: BlendingFactor, | ||||||
|  | 			alphaDestination: BlendingFactor, alphaOperation: BlendingOperation): Void { | ||||||
|  | 		if (source == BlendOne && destination == BlendZero) { | ||||||
|  | 			SystemImpl.gl.disable(GL.BLEND); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.gl.enable(GL.BLEND); | ||||||
|  | 			SystemImpl.gl.blendFuncSeparate(getBlendFunc(source), getBlendFunc(destination), getBlendFunc(alphaSource), getBlendFunc(alphaDestination)); | ||||||
|  | 			SystemImpl.gl.blendEquationSeparate(getBlendOp(operation), getBlendOp(alphaOperation)); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function createVertexBuffer(vertexCount: Int, structure: VertexStructure, usage: Usage, canRead: Bool = false): kha.graphics4.VertexBuffer { | ||||||
|  | 		return new VertexBuffer(vertexCount, structure, usage); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVertexBuffer(vertexBuffer: kha.graphics4.VertexBuffer): Void { | ||||||
|  | 		for (i in 0...useVertexAttributes) { | ||||||
|  | 			SystemImpl.gl.disableVertexAttribArray(i); | ||||||
|  | 		} | ||||||
|  | 		useVertexAttributes = vertexBuffer.set(0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVertexBuffers(vertexBuffers: Array<kha.graphics4.VertexBuffer>): Void { | ||||||
|  | 		for (i in 0...useVertexAttributes) { | ||||||
|  | 			SystemImpl.gl.disableVertexAttribArray(i); | ||||||
|  | 		} | ||||||
|  | 		var offset: Int = 0; | ||||||
|  | 		for (vertexBuffer in vertexBuffers) { | ||||||
|  | 			offset += vertexBuffer.set(offset); | ||||||
|  | 		} | ||||||
|  | 		useVertexAttributes = offset; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function createIndexBuffer(indexCount: Int, usage: Usage, canRead: Bool = false): kha.graphics4.IndexBuffer { | ||||||
|  | 		return new IndexBuffer(indexCount, usage); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setIndexBuffer(indexBuffer: kha.graphics4.IndexBuffer): Void { | ||||||
|  | 		indicesCount = indexBuffer.count(); | ||||||
|  | 		indexBuffer.set(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// public function maxTextureSize(): Int { | ||||||
|  | 	//	return Sys.gl == null ? 8192 : Sys.gl.getParameter(Sys.gl.MAX_TEXTURE_SIZE); | ||||||
|  | 	// } | ||||||
|  | 	// public function supportsNonPow2Textures(): Bool { | ||||||
|  | 	//	return false; | ||||||
|  | 	// } | ||||||
|  |  | ||||||
|  | 	public function setTexture(stage: kha.graphics4.TextureUnit, texture: kha.Image): Void { | ||||||
|  | 		if (texture == null) { | ||||||
|  | 			SystemImpl.gl.activeTexture(GL.TEXTURE0 + (cast stage : TextureUnit).value); | ||||||
|  | 			SystemImpl.gl.bindTexture(GL.TEXTURE_2D, null); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			cast(texture, WebGLImage).set((cast stage : TextureUnit).value); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setTextureDepth(stage: kha.graphics4.TextureUnit, texture: kha.Image): Void { | ||||||
|  | 		cast(texture, WebGLImage).setDepth((cast stage : TextureUnit).value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setTextureArray(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void { | ||||||
|  | 		// not implemented yet. | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVideoTexture(unit: kha.graphics4.TextureUnit, texture: kha.Video): Void { | ||||||
|  | 		if (texture == null) { | ||||||
|  | 			SystemImpl.gl.activeTexture(GL.TEXTURE0 + (cast unit : TextureUnit).value); | ||||||
|  | 			SystemImpl.gl.bindTexture(GL.TEXTURE_2D, null); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			cast((cast texture : kha.js.Video).texture, WebGLImage).set((cast unit : TextureUnit).value); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setImageTexture(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {} | ||||||
|  |  | ||||||
|  | 	public function setTextureParameters(texunit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing, | ||||||
|  | 			minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void { | ||||||
|  | 		SystemImpl.gl.activeTexture(GL.TEXTURE0 + (cast texunit : TextureUnit).value); | ||||||
|  |  | ||||||
|  | 		switch (uAddressing) { | ||||||
|  | 			case Clamp: | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); | ||||||
|  | 			case Repeat: | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.REPEAT); | ||||||
|  | 			case Mirror: | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.MIRRORED_REPEAT); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		switch (vAddressing) { | ||||||
|  | 			case Clamp: | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); | ||||||
|  | 			case Repeat: | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.REPEAT); | ||||||
|  | 			case Mirror: | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.MIRRORED_REPEAT); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		switch (minificationFilter) { | ||||||
|  | 			case PointFilter: | ||||||
|  | 				switch (mipmapFilter) { | ||||||
|  | 					case NoMipFilter: | ||||||
|  | 						SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST); | ||||||
|  | 					case PointMipFilter: | ||||||
|  | 						SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST_MIPMAP_NEAREST); | ||||||
|  | 					case LinearMipFilter: | ||||||
|  | 						SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST_MIPMAP_LINEAR); | ||||||
|  | 				} | ||||||
|  | 			case LinearFilter, AnisotropicFilter: | ||||||
|  | 				switch (mipmapFilter) { | ||||||
|  | 					case NoMipFilter: | ||||||
|  | 						SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); | ||||||
|  | 					case PointMipFilter: | ||||||
|  | 						SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR_MIPMAP_NEAREST); | ||||||
|  | 					case LinearMipFilter: | ||||||
|  | 						SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR_MIPMAP_LINEAR); | ||||||
|  | 				} | ||||||
|  | 				if (minificationFilter == AnisotropicFilter) { | ||||||
|  | 					SystemImpl.gl.texParameteri(GL.TEXTURE_2D, SystemImpl.anisotropicFilter.TEXTURE_MAX_ANISOTROPY_EXT, 4); | ||||||
|  | 				} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		switch (magnificationFilter) { | ||||||
|  | 			case PointFilter: | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.NEAREST); | ||||||
|  | 			case LinearFilter, AnisotropicFilter: | ||||||
|  | 				SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setTexture3DParameters(texunit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing, | ||||||
|  | 		wAddressing: TextureAddressing, minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void {} | ||||||
|  |  | ||||||
|  | 	public function setTextureCompareMode(texunit: kha.graphics4.TextureUnit, enabled: Bool) { | ||||||
|  | 		if (enabled) { | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL2.TEXTURE_COMPARE_MODE, GL2.COMPARE_REF_TO_TEXTURE); | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL2.TEXTURE_COMPARE_FUNC, GL.LEQUAL); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_2D, GL2.TEXTURE_COMPARE_MODE, GL.NONE); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setCubeMapCompareMode(texunit: kha.graphics4.TextureUnit, enabled: Bool) { | ||||||
|  | 		if (enabled) { | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL2.TEXTURE_COMPARE_MODE, GL2.COMPARE_REF_TO_TEXTURE); | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL2.TEXTURE_COMPARE_FUNC, GL.LEQUAL); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL2.TEXTURE_COMPARE_MODE, GL.NONE); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setCubeMap(stage: kha.graphics4.TextureUnit, cubeMap: kha.graphics4.CubeMap): Void { | ||||||
|  | 		if (cubeMap == null) { | ||||||
|  | 			SystemImpl.gl.activeTexture(GL.TEXTURE0 + (cast stage : TextureUnit).value); | ||||||
|  | 			SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, null); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			cubeMap.set((cast stage : TextureUnit).value); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setCubeMapDepth(stage: kha.graphics4.TextureUnit, cubeMap: kha.graphics4.CubeMap): Void { | ||||||
|  | 		cubeMap.setDepth((cast stage : TextureUnit).value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function maxBoundTextures(): Int { | ||||||
|  | 		return SystemImpl.gl.getParameter(GL.MAX_TEXTURE_IMAGE_UNITS); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setCullMode(mode: CullMode): Void { | ||||||
|  | 		switch (mode) { | ||||||
|  | 			case None: | ||||||
|  | 				SystemImpl.gl.disable(GL.CULL_FACE); | ||||||
|  | 			case Clockwise: | ||||||
|  | 				SystemImpl.gl.enable(GL.CULL_FACE); | ||||||
|  | 				SystemImpl.gl.cullFace(GL.BACK); | ||||||
|  | 			case CounterClockwise: | ||||||
|  | 				SystemImpl.gl.enable(GL.CULL_FACE); | ||||||
|  | 				SystemImpl.gl.cullFace(GL.FRONT); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setPipeline(pipe: PipelineState): Void { | ||||||
|  | 		setCullMode(pipe.cullMode); | ||||||
|  | 		setDepthMode(pipe.depthWrite, pipe.depthMode); | ||||||
|  | 		if (pipe.stencilFrontMode == Always && pipe.stencilBackMode == Always && pipe.stencilFrontBothPass == Keep && pipe.stencilBackBothPass == Keep | ||||||
|  | 			&& pipe.stencilFrontDepthFail == Keep && pipe.stencilBackDepthFail == Keep && pipe.stencilFrontFail == Keep && pipe.stencilBackFail == Keep) { | ||||||
|  | 			SystemImpl.gl.disable(GL.STENCIL_TEST); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.gl.enable(GL.STENCIL_TEST); | ||||||
|  | 			setStencilParameters(true, pipe.stencilFrontMode, pipe.stencilFrontBothPass, pipe.stencilFrontDepthFail, pipe.stencilFrontFail, | ||||||
|  | 				pipe.stencilReferenceValue, pipe.stencilReadMask, pipe.stencilWriteMask); | ||||||
|  | 			setStencilParameters(false, pipe.stencilBackMode, pipe.stencilBackBothPass, pipe.stencilBackDepthFail, pipe.stencilBackFail, | ||||||
|  | 				pipe.stencilReferenceValue, pipe.stencilReadMask, pipe.stencilWriteMask); | ||||||
|  | 		} | ||||||
|  | 		setBlendingMode(pipe.blendSource, pipe.blendDestination, pipe.blendOperation, pipe.alphaBlendSource, pipe.alphaBlendDestination, | ||||||
|  | 			pipe.alphaBlendOperation); | ||||||
|  | 		currentPipeline = pipe; | ||||||
|  | 		pipe.set(); | ||||||
|  | 		colorMaskRed = pipe.colorWriteMaskRed; | ||||||
|  | 		colorMaskGreen = pipe.colorWriteMaskGreen; | ||||||
|  | 		colorMaskBlue = pipe.colorWriteMaskBlue; | ||||||
|  | 		colorMaskAlpha = pipe.colorWriteMaskAlpha; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setStencilReferenceValue(value: Int): Void { | ||||||
|  | 		SystemImpl.gl.stencilFuncSeparate(GL.FRONT, convertCompareMode(currentPipeline.stencilFrontMode), value, currentPipeline.stencilReadMask); | ||||||
|  | 		SystemImpl.gl.stencilFuncSeparate(GL.BACK, convertCompareMode(currentPipeline.stencilBackMode), value, currentPipeline.stencilReadMask); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setBool(location: kha.graphics4.ConstantLocation, value: Bool): Void { | ||||||
|  | 		SystemImpl.gl.uniform1i((cast location : ConstantLocation).value, value ? 1 : 0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setInt(location: kha.graphics4.ConstantLocation, value: Int): Void { | ||||||
|  | 		SystemImpl.gl.uniform1i((cast location : ConstantLocation).value, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setInt2(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int): Void { | ||||||
|  | 		SystemImpl.gl.uniform2i((cast location : ConstantLocation).value, value1, value2); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setInt3(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int, value3: Int): Void { | ||||||
|  | 		SystemImpl.gl.uniform3i((cast location : ConstantLocation).value, value1, value2, value3); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setInt4(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int, value3: Int, value4: Int): Void { | ||||||
|  | 		SystemImpl.gl.uniform4i((cast location : ConstantLocation).value, value1, value2, value3, value4); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setInts(location: kha.graphics4.ConstantLocation, values: Int32Array): Void { | ||||||
|  | 		var webglLocation = (cast location : ConstantLocation); | ||||||
|  | 		var rawValues = new js.lib.Int32Array(values.buffer, values.byteOffset, values.length); | ||||||
|  | 		switch (webglLocation.type) { | ||||||
|  | 			case GL.INT_VEC2: | ||||||
|  | 				SystemImpl.gl.uniform2iv(webglLocation.value, rawValues); | ||||||
|  | 			case GL.INT_VEC3: | ||||||
|  | 				SystemImpl.gl.uniform3iv(webglLocation.value, rawValues); | ||||||
|  | 			case GL.INT_VEC4: | ||||||
|  | 				SystemImpl.gl.uniform4iv(webglLocation.value, rawValues); | ||||||
|  | 			default: | ||||||
|  | 				SystemImpl.gl.uniform1iv(webglLocation.value, rawValues); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setFloat(location: kha.graphics4.ConstantLocation, value: FastFloat): Void { | ||||||
|  | 		SystemImpl.gl.uniform1f((cast location : ConstantLocation).value, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setFloat2(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat): Void { | ||||||
|  | 		SystemImpl.gl.uniform2f((cast location : ConstantLocation).value, value1, value2); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setFloat3(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat): Void { | ||||||
|  | 		SystemImpl.gl.uniform3f((cast location : ConstantLocation).value, value1, value2, value3); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setFloat4(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat, value4: FastFloat): Void { | ||||||
|  | 		SystemImpl.gl.uniform4f((cast location : ConstantLocation).value, value1, value2, value3, value4); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setFloats(location: kha.graphics4.ConstantLocation, values: Float32Array): Void { | ||||||
|  | 		var webglLocation = (cast location : ConstantLocation); | ||||||
|  | 		var rawValues = new js.lib.Float32Array(values.buffer, values.byteOffset, values.length); | ||||||
|  | 		switch (webglLocation.type) { | ||||||
|  | 			case GL.FLOAT_VEC2: | ||||||
|  | 				SystemImpl.gl.uniform2fv(webglLocation.value, rawValues); | ||||||
|  | 			case GL.FLOAT_VEC3: | ||||||
|  | 				SystemImpl.gl.uniform3fv(webglLocation.value, rawValues); | ||||||
|  | 			case GL.FLOAT_VEC4: | ||||||
|  | 				SystemImpl.gl.uniform4fv(webglLocation.value, rawValues); | ||||||
|  | 			case GL.FLOAT_MAT4: | ||||||
|  | 				SystemImpl.gl.uniformMatrix4fv(webglLocation.value, false, rawValues); | ||||||
|  | 			default: | ||||||
|  | 				SystemImpl.gl.uniform1fv(webglLocation.value, rawValues); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVector2(location: kha.graphics4.ConstantLocation, value: FastVector2): Void { | ||||||
|  | 		SystemImpl.gl.uniform2f((cast location : ConstantLocation).value, value.x, value.y); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVector3(location: kha.graphics4.ConstantLocation, value: FastVector3): Void { | ||||||
|  | 		SystemImpl.gl.uniform3f((cast location : ConstantLocation).value, value.x, value.y, value.z); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setVector4(location: kha.graphics4.ConstantLocation, value: FastVector4): Void { | ||||||
|  | 		SystemImpl.gl.uniform4f((cast location : ConstantLocation).value, value.x, value.y, value.z, value.w); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static var matrixCache = new js.lib.Float32Array(16); | ||||||
|  | 	public inline function setMatrix(location: kha.graphics4.ConstantLocation, matrix: FastMatrix4): Void { | ||||||
|  | 		matrixCache[0] = matrix._00; | ||||||
|  | 		matrixCache[1] = matrix._01; | ||||||
|  | 		matrixCache[2] = matrix._02; | ||||||
|  | 		matrixCache[3] = matrix._03; | ||||||
|  | 		matrixCache[4] = matrix._10; | ||||||
|  | 		matrixCache[5] = matrix._11; | ||||||
|  | 		matrixCache[6] = matrix._12; | ||||||
|  | 		matrixCache[7] = matrix._13; | ||||||
|  | 		matrixCache[8] = matrix._20; | ||||||
|  | 		matrixCache[9] = matrix._21; | ||||||
|  | 		matrixCache[10] = matrix._22; | ||||||
|  | 		matrixCache[11] = matrix._23; | ||||||
|  | 		matrixCache[12] = matrix._30; | ||||||
|  | 		matrixCache[13] = matrix._31; | ||||||
|  | 		matrixCache[14] = matrix._32; | ||||||
|  | 		matrixCache[15] = matrix._33; | ||||||
|  | 		SystemImpl.gl.uniformMatrix4fv((cast location : ConstantLocation).value, false, matrixCache); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static var matrix3Cache = new js.lib.Float32Array(9); | ||||||
|  | 	public inline function setMatrix3(location: kha.graphics4.ConstantLocation, matrix: FastMatrix3): Void { | ||||||
|  | 		matrix3Cache[0] = matrix._00; | ||||||
|  | 		matrix3Cache[1] = matrix._01; | ||||||
|  | 		matrix3Cache[2] = matrix._02; | ||||||
|  | 		matrix3Cache[3] = matrix._10; | ||||||
|  | 		matrix3Cache[4] = matrix._11; | ||||||
|  | 		matrix3Cache[5] = matrix._12; | ||||||
|  | 		matrix3Cache[6] = matrix._20; | ||||||
|  | 		matrix3Cache[7] = matrix._21; | ||||||
|  | 		matrix3Cache[8] = matrix._22; | ||||||
|  | 		SystemImpl.gl.uniformMatrix3fv((cast location : ConstantLocation).value, false, matrix3Cache); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function drawIndexedVertices(start: Int = 0, count: Int = -1): Void { | ||||||
|  | 		var type = SystemImpl.elementIndexUint == null ? GL.UNSIGNED_SHORT : GL.UNSIGNED_INT; | ||||||
|  | 		var size = type == GL.UNSIGNED_SHORT ? 2 : 4; | ||||||
|  | 		SystemImpl.gl.drawElements(GL.TRIANGLES, count == -1 ? indicesCount : count, type, start * size); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function convertStencilAction(action: StencilAction) { | ||||||
|  | 		switch (action) { | ||||||
|  | 			case StencilAction.Decrement: | ||||||
|  | 				return GL.DECR; | ||||||
|  | 			case StencilAction.DecrementWrap: | ||||||
|  | 				return GL.DECR_WRAP; | ||||||
|  | 			case StencilAction.Increment: | ||||||
|  | 				return GL.INCR; | ||||||
|  | 			case StencilAction.IncrementWrap: | ||||||
|  | 				return GL.INCR_WRAP; | ||||||
|  | 			case StencilAction.Invert: | ||||||
|  | 				return GL.INVERT; | ||||||
|  | 			case StencilAction.Keep: | ||||||
|  | 				return GL.KEEP; | ||||||
|  | 			case StencilAction.Replace: | ||||||
|  | 				return GL.REPLACE; | ||||||
|  | 			case StencilAction.Zero: | ||||||
|  | 				return GL.ZERO; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function convertCompareMode(compareMode: CompareMode) { | ||||||
|  | 		switch (compareMode) { | ||||||
|  | 			case Always: | ||||||
|  | 				return GL.ALWAYS; | ||||||
|  | 			case Equal: | ||||||
|  | 				return GL.EQUAL; | ||||||
|  | 			case Greater: | ||||||
|  | 				return GL.GREATER; | ||||||
|  | 			case GreaterEqual: | ||||||
|  | 				return GL.GEQUAL; | ||||||
|  | 			case Less: | ||||||
|  | 				return GL.LESS; | ||||||
|  | 			case LessEqual: | ||||||
|  | 				return GL.LEQUAL; | ||||||
|  | 			case Never: | ||||||
|  | 				return GL.NEVER; | ||||||
|  | 			case NotEqual: | ||||||
|  | 				return GL.NOTEQUAL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function setStencilParameters(front: Bool, compareMode: CompareMode, bothPass: StencilAction, depthFail: StencilAction, stencilFail: StencilAction, | ||||||
|  | 			referenceValue: StencilValue, readMask: Int = 0xff, writeMask: Int = 0xff): Void { | ||||||
|  | 		var stencilFunc = convertCompareMode(compareMode); | ||||||
|  | 		SystemImpl.gl.stencilMaskSeparate(front ? GL.FRONT : GL.BACK, writeMask); | ||||||
|  | 		SystemImpl.gl.stencilOpSeparate(front ? GL.FRONT : GL.BACK, convertStencilAction(stencilFail), convertStencilAction(depthFail), | ||||||
|  | 			convertStencilAction(bothPass)); | ||||||
|  | 		switch (referenceValue) { | ||||||
|  | 			case Static(value): | ||||||
|  | 				SystemImpl.gl.stencilFuncSeparate(front ? GL.FRONT : GL.BACK, stencilFunc, value, readMask); | ||||||
|  | 			case Dynamic: | ||||||
|  | 				SystemImpl.gl.stencilFuncSeparate(front ? GL.FRONT : GL.BACK, stencilFunc, 0, readMask); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function drawIndexedVerticesInstanced(instanceCount: Int, start: Int = 0, count: Int = -1) { | ||||||
|  | 		if (instancedRenderingAvailable()) { | ||||||
|  | 			var type = SystemImpl.elementIndexUint == null ? GL.UNSIGNED_SHORT : GL.UNSIGNED_INT; | ||||||
|  | 			var typeSize = SystemImpl.elementIndexUint == null ? 2 : 4; | ||||||
|  | 			if (SystemImpl.gl2) { | ||||||
|  | 				untyped SystemImpl.gl.drawElementsInstanced(GL.TRIANGLES, count == -1 ? indicesCount : count, type, start * typeSize, instanceCount); | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				instancedExtension.drawElementsInstancedANGLE(GL.TRIANGLES, count == -1 ? indicesCount : count, type, start * typeSize, instanceCount); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function instancedRenderingAvailable(): Bool { | ||||||
|  | 		return instancedExtension; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								Kha/Backends/HTML5/kha/js/graphics4/Graphics2.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Kha/Backends/HTML5/kha/js/graphics4/Graphics2.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | package kha.js.graphics4; | ||||||
|  |  | ||||||
|  | import js.html.webgl.GL; | ||||||
|  | import kha.Color; | ||||||
|  |  | ||||||
|  | class Graphics2 extends kha.graphics4.Graphics2 { | ||||||
|  | 	public function new(canvas: Canvas) { | ||||||
|  | 		super(canvas); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function drawVideoInternal(video: kha.Video, x: Float, y: Float, width: Float, height: Float): Void { | ||||||
|  | 		var v = cast(video, Video); | ||||||
|  | 		drawScaledSubImage(v.texture, 0, 0, v.texture.width, v.texture.height, x, y, width, height); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override public function begin(clear: Bool = true, clearColor: Color = null): Void { | ||||||
|  | 		SystemImpl.gl.colorMask(true, true, true, true); | ||||||
|  |  | ||||||
|  | 		// Disable depth test so that everything is just overpainted as determined by the order of function calls2 | ||||||
|  | 		SystemImpl.gl.disable(GL.DEPTH_TEST); | ||||||
|  | 		SystemImpl.gl.depthFunc(GL.ALWAYS); | ||||||
|  |  | ||||||
|  | 		super.begin(clear, clearColor); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								Kha/Backends/HTML5/kha/js/graphics4/TextureUnit.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Kha/Backends/HTML5/kha/js/graphics4/TextureUnit.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | package kha.js.graphics4; | ||||||
|  |  | ||||||
|  | class TextureUnit implements kha.graphics4.TextureUnit { | ||||||
|  | 	public var value: Int; | ||||||
|  |  | ||||||
|  | 	public function new(value: Int) { | ||||||
|  | 		this.value = value; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										249
									
								
								Kha/Backends/HTML5/kha/js/vr/VrInterface.hx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										249
									
								
								Kha/Backends/HTML5/kha/js/vr/VrInterface.hx
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,249 @@ | |||||||
|  | package kha.js.vr; | ||||||
|  |  | ||||||
|  | import js.Syntax; | ||||||
|  | import js.lib.Float32Array; | ||||||
|  | import kha.vr.Pose; | ||||||
|  | import kha.vr.PoseState; | ||||||
|  | import kha.vr.SensorState; | ||||||
|  | import kha.vr.TimeWarpParms; | ||||||
|  | import kha.math.FastMatrix4; | ||||||
|  | import kha.math.Vector3; | ||||||
|  | import kha.math.Quaternion; | ||||||
|  | import kha.SystemImpl; | ||||||
|  |  | ||||||
|  | class VrInterface extends kha.vr.VrInterface { | ||||||
|  | 	var vrEnabled: Bool = false; | ||||||
|  |  | ||||||
|  | 	var vrDisplay: Dynamic; | ||||||
|  | 	var frameData: Dynamic; | ||||||
|  |  | ||||||
|  | 	var leftProjectionMatrix: FastMatrix4 = FastMatrix4.identity(); | ||||||
|  | 	var rightProjectionMatrix: FastMatrix4 = FastMatrix4.identity(); | ||||||
|  | 	var leftViewMatrix: FastMatrix4 = FastMatrix4.identity(); | ||||||
|  | 	var rightViewMatrix: FastMatrix4 = FastMatrix4.identity(); | ||||||
|  |  | ||||||
|  | 	var width: Int = 0; | ||||||
|  | 	var height: Int = 0; | ||||||
|  | 	var vrWidth: Int = 0; | ||||||
|  | 	var vrHeight: Int = 0; | ||||||
|  |  | ||||||
|  | 	public function new() { | ||||||
|  | 		super(); | ||||||
|  | 		#if kha_webvr | ||||||
|  | 		var displayEnabled: Bool = Syntax.code("navigator.getVRDisplays"); | ||||||
|  | 		#else | ||||||
|  | 		var displayEnabled = false; | ||||||
|  | 		#end | ||||||
|  | 		if (displayEnabled) { | ||||||
|  | 			vrEnabled = true; | ||||||
|  | 			getVRDisplays(); | ||||||
|  | 			trace("Display enabled."); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function getVRDisplays() { | ||||||
|  | 		var vrDisplayInstance = Syntax.code("navigator.getVRDisplays()"); | ||||||
|  | 		vrDisplayInstance.then(function(displays) { | ||||||
|  | 			if (displays.length > 0) { | ||||||
|  | 				frameData = Syntax.code("new VRFrameData()"); | ||||||
|  | 				vrDisplay = Syntax.code("displays[0]"); | ||||||
|  | 				vrDisplay.depthNear = 0.1; | ||||||
|  | 				vrDisplay.depthFar = 1024.0; | ||||||
|  |  | ||||||
|  | 				var leftEye = vrDisplay.getEyeParameters("left"); | ||||||
|  | 				var rightEye = vrDisplay.getEyeParameters("right"); | ||||||
|  | 				width = SystemImpl.khanvas.width; | ||||||
|  | 				height = SystemImpl.khanvas.height; | ||||||
|  | 				vrWidth = Std.int(Math.max(leftEye.renderWidth, rightEye.renderWidth) * 2); | ||||||
|  | 				vrHeight = Std.int(Math.max(leftEye.renderHeight, rightEye.renderHeight)); | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				trace("There are no VR displays connected."); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public override function onVRRequestPresent() { | ||||||
|  | 		try { | ||||||
|  | 			vrDisplay.requestPresent([{source: SystemImpl.khanvas}]).then(function() { | ||||||
|  | 				onResize(); | ||||||
|  | 				vrDisplay.requestAnimationFrame(onAnimationFrame); | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 		catch (err:Dynamic) { | ||||||
|  | 			trace("Failed to requestPresent."); | ||||||
|  | 			trace(err); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public override function onVRExitPresent() { | ||||||
|  | 		try { | ||||||
|  | 			vrDisplay.exitPresent([{source: SystemImpl.khanvas}]).then(function() { | ||||||
|  | 				onResize(); | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 		catch (err:Dynamic) { | ||||||
|  | 			trace("Failed to exitPresent."); | ||||||
|  | 			trace(err); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public override function onResetPose() { | ||||||
|  | 		try { | ||||||
|  | 			vrDisplay.resetPose(); | ||||||
|  | 		} | ||||||
|  | 		catch (err:Dynamic) { | ||||||
|  | 			trace("Failed to resetPose"); | ||||||
|  | 			trace(err); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function onAnimationFrame(timestamp: Float): Void { | ||||||
|  | 		if (vrDisplay != null && vrDisplay.isPresenting) { | ||||||
|  | 			vrDisplay.requestAnimationFrame(onAnimationFrame); | ||||||
|  |  | ||||||
|  | 			vrDisplay.getFrameData(frameData); | ||||||
|  |  | ||||||
|  | 			leftProjectionMatrix = createMatrixFromArray(untyped frameData.leftProjectionMatrix); | ||||||
|  | 			leftViewMatrix = createMatrixFromArray(untyped frameData.leftViewMatrix); | ||||||
|  |  | ||||||
|  | 			rightProjectionMatrix = createMatrixFromArray(untyped frameData.rightProjectionMatrix); | ||||||
|  | 			rightViewMatrix = createMatrixFromArray(untyped frameData.rightViewMatrix); | ||||||
|  |  | ||||||
|  | 			// Submit the newly rendered layer to be presented by the VRDisplay | ||||||
|  | 			vrDisplay.submitFrame(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function onResize() { | ||||||
|  | 		if (vrDisplay != null && vrDisplay.isPresenting) { | ||||||
|  | 			SystemImpl.khanvas.width = vrWidth; | ||||||
|  | 			SystemImpl.khanvas.height = vrHeight; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			SystemImpl.khanvas.width = width; | ||||||
|  | 			SystemImpl.khanvas.height = height; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public override function GetSensorState(): SensorState { | ||||||
|  | 		return GetPredictedSensorState(0.0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public override function GetPredictedSensorState(time: Float): SensorState { | ||||||
|  | 		var result: SensorState = new SensorState(); | ||||||
|  |  | ||||||
|  | 		result.Predicted = new PoseState(); | ||||||
|  | 		result.Recorded = result.Predicted; | ||||||
|  |  | ||||||
|  | 		result.Predicted.AngularAcceleration = new Vector3(); | ||||||
|  | 		result.Predicted.AngularVelocity = new Vector3(); | ||||||
|  | 		result.Predicted.LinearAcceleration = new Vector3(); | ||||||
|  | 		result.Predicted.LinearVelocity = new Vector3(); | ||||||
|  | 		result.Predicted.TimeInSeconds = time; | ||||||
|  | 		result.Predicted.Pose = new Pose(); | ||||||
|  | 		result.Predicted.Pose.Orientation = new Quaternion(); | ||||||
|  | 		result.Predicted.Pose.Position = new Vector3(); | ||||||
|  |  | ||||||
|  | 		var mPose = frameData.pose; // predicted pose of the vrDisplay | ||||||
|  | 		if (mPose != null) { | ||||||
|  | 			result.Predicted.AngularVelocity = createVectorFromArray(untyped mPose.angularVelocity); | ||||||
|  | 			result.Predicted.AngularAcceleration = createVectorFromArray(untyped mPose.angularAcceleration); | ||||||
|  | 			result.Predicted.LinearVelocity = createVectorFromArray(untyped mPose.linearVelocity); | ||||||
|  | 			result.Predicted.LinearAcceleration = createVectorFromArray(untyped mPose.linearAcceleration); | ||||||
|  | 			result.Predicted.Pose.Orientation = createQuaternion(untyped mPose.orientation); | ||||||
|  | 			result.Predicted.Pose.Position = createVectorFromArray(untyped mPose.position); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return result; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Sends a black image to the warp swap thread | ||||||
|  | 	public override function WarpSwapBlack(): Void { | ||||||
|  | 		// TODO: Implement | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Sends the Oculus loading symbol to the warp swap thread | ||||||
|  | 	public override function WarpSwapLoadingIcon(): Void { | ||||||
|  | 		// TODO: Implement | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Sends the set of images to the warp swap thread | ||||||
|  | 	public override function WarpSwap(parms: TimeWarpParms): Void { | ||||||
|  | 		// TODO: Implement | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public override function IsPresenting(): Bool { | ||||||
|  | 		if (vrDisplay != null) | ||||||
|  | 			return vrDisplay.isPresenting; | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public override function IsVrEnabled(): Bool { | ||||||
|  | 		return vrEnabled; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public override function GetTimeInSeconds(): Float { | ||||||
|  | 		return Scheduler.time(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public override function GetProjectionMatrix(eye: Int): FastMatrix4 { | ||||||
|  | 		if (eye == 0) { | ||||||
|  | 			return leftProjectionMatrix; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			return rightProjectionMatrix; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public override function GetViewMatrix(eye: Int): FastMatrix4 { | ||||||
|  | 		if (eye == 0) { | ||||||
|  | 			return leftViewMatrix; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			return rightViewMatrix; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function createMatrixFromArray(array: Float32Array): FastMatrix4 { | ||||||
|  | 		var matrix: FastMatrix4 = FastMatrix4.identity(); | ||||||
|  | 		matrix._00 = array[0]; | ||||||
|  | 		matrix._01 = array[1]; | ||||||
|  | 		matrix._02 = array[2]; | ||||||
|  | 		matrix._03 = array[3]; | ||||||
|  | 		matrix._10 = array[4]; | ||||||
|  | 		matrix._11 = array[5]; | ||||||
|  | 		matrix._12 = array[6]; | ||||||
|  | 		matrix._13 = array[7]; | ||||||
|  | 		matrix._20 = array[8]; | ||||||
|  | 		matrix._21 = array[9]; | ||||||
|  | 		matrix._22 = array[10]; | ||||||
|  | 		matrix._23 = array[11]; | ||||||
|  | 		matrix._30 = array[12]; | ||||||
|  | 		matrix._31 = array[13]; | ||||||
|  | 		matrix._32 = array[14]; | ||||||
|  | 		matrix._33 = array[15]; | ||||||
|  | 		return matrix; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function createVectorFromArray(array: Float32Array): Vector3 { | ||||||
|  | 		var vector: Vector3 = new Vector3(0, 0, 0); | ||||||
|  | 		if (array != null) { | ||||||
|  | 			vector.x = array[0]; | ||||||
|  | 			vector.y = array[1]; | ||||||
|  | 			vector.z = array[2]; | ||||||
|  | 		} | ||||||
|  | 		return vector; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function createQuaternion(array: Float32Array): Quaternion { | ||||||
|  | 		var quaternion: Quaternion = new Quaternion(0, 0, 0, 0); | ||||||
|  | 		if (array != null) { | ||||||
|  | 			quaternion.x = array[0]; | ||||||
|  | 			quaternion.y = array[1]; | ||||||
|  | 			quaternion.z = array[2]; | ||||||
|  | 			quaternion.w = array[3]; | ||||||
|  | 		} | ||||||
|  | 		return quaternion; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										68
									
								
								Kha/Backends/HTML5/kha/netsync/Network.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								Kha/Backends/HTML5/kha/netsync/Network.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | |||||||
|  | package kha.netsync; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import js.html.BinaryType; | ||||||
|  | import js.html.WebSocket; | ||||||
|  |  | ||||||
|  | class Network { | ||||||
|  | 	var socket: WebSocket; | ||||||
|  | 	var open: Bool = false; | ||||||
|  |  | ||||||
|  | 	public function new(url: String, port: Int, errorCallback: Void->Void, closeCallback: Void->Void) { | ||||||
|  | 		socket = new WebSocket("ws://" + url + ":" + port); | ||||||
|  | 		socket.onerror = function(error) { | ||||||
|  | 			trace("Network error."); | ||||||
|  | 			errorCallback(); | ||||||
|  | 		} | ||||||
|  | 		socket.binaryType = BinaryType.ARRAYBUFFER; | ||||||
|  | 		socket.onopen = function() { | ||||||
|  | 			open = true; | ||||||
|  | 		}; | ||||||
|  | 		socket.onclose = function(event) { | ||||||
|  | 			trace("Network connection closed. " + webSocketCloseReason(event.code) + " (" + event.reason + ")."); | ||||||
|  | 			closeCallback(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static function webSocketCloseReason(code: Int): String { | ||||||
|  | 		switch (code) { | ||||||
|  | 			case 1000: | ||||||
|  | 				return "Normal Closure"; | ||||||
|  | 			case 1001: | ||||||
|  | 				return "Going Away"; | ||||||
|  | 			case 1002: | ||||||
|  | 				return "Protocol error"; | ||||||
|  | 			case 1003: | ||||||
|  | 				return "Unsupported Data"; | ||||||
|  | 			case 1005: | ||||||
|  | 				return "No Status Rcvd"; | ||||||
|  | 			case 1006: | ||||||
|  | 				return "Abnormal Closure"; | ||||||
|  | 			case 1007: | ||||||
|  | 				return "Invalid frame"; | ||||||
|  | 			case 1008: | ||||||
|  | 				return "Policy Violation"; | ||||||
|  | 			case 1009: | ||||||
|  | 				return "Message Too Big"; | ||||||
|  | 			case 1010: | ||||||
|  | 				return "Mandatory Ext."; | ||||||
|  | 			case 1011: | ||||||
|  | 				return "Internal Server Error"; | ||||||
|  | 			case 1015: | ||||||
|  | 				return "TLS handshake"; | ||||||
|  | 			default: | ||||||
|  | 				return ""; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function send(bytes: Bytes, mandatory: Bool): Void { | ||||||
|  | 		if (open) | ||||||
|  | 			socket.send(bytes.getData()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function listen(listener: Bytes->Void): Void { | ||||||
|  | 		socket.onmessage = function(message) { | ||||||
|  | 			listener(Bytes.ofData(message.data)); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								Kha/Backends/HTML5/kha/network/Http.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								Kha/Backends/HTML5/kha/network/Http.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | |||||||
|  | package kha.network; | ||||||
|  |  | ||||||
|  | import js.html.XMLHttpRequest; | ||||||
|  |  | ||||||
|  | class Http { | ||||||
|  | 	static function methodToString(method: HttpMethod): String { | ||||||
|  | 		switch (method) { | ||||||
|  | 			case Get: | ||||||
|  | 				return "GET"; | ||||||
|  | 			case Post: | ||||||
|  | 				return "POST"; | ||||||
|  | 			case Put: | ||||||
|  | 				return "PUT"; | ||||||
|  | 			case Delete: | ||||||
|  | 				return "DELETE"; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	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 { | ||||||
|  | 		var req = new XMLHttpRequest(""); | ||||||
|  | 		var completeUrl = (secure ? "https://" : "http://") + url + ":" + port + "/" + path; | ||||||
|  | 		req.open(methodToString(method), completeUrl, true); | ||||||
|  | 		if (headers != null) { | ||||||
|  | 			for (key in headers.keys()) { | ||||||
|  | 				req.setRequestHeader(key, headers[key]); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		req.onreadystatechange = function() { | ||||||
|  | 			if (req.readyState != 4) | ||||||
|  | 				return; | ||||||
|  | 			if (req.status != 200) { | ||||||
|  | 				callback(1, req.status, null); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			callback(0, req.status, req.responseText); | ||||||
|  | 		} | ||||||
|  | 		req.send(data); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								Kha/Backends/Java/java/lang/Runnable.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								Kha/Backends/Java/java/lang/Runnable.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | package java.lang; | ||||||
|  |  | ||||||
|  | extern interface Runnable { | ||||||
|  | 	function run(): Void; | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								Kha/Backends/Java/kha/Blob.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Kha/Backends/Java/kha/Blob.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | typedef Blob = kha.internal.BytesBlob; | ||||||
							
								
								
									
										75
									
								
								Kha/Backends/Java/kha/Display.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								Kha/Backends/Java/kha/Display.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | class Display { | ||||||
|  | 	static var instance: Display = new Display(); | ||||||
|  |  | ||||||
|  | 	function new() {} | ||||||
|  |  | ||||||
|  | 	public static function init(): Void {} | ||||||
|  |  | ||||||
|  | 	public static var primary(get, never): Display; | ||||||
|  |  | ||||||
|  | 	static function get_primary(): Display { | ||||||
|  | 		return instance; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static var all(get, never): Array<Display>; | ||||||
|  |  | ||||||
|  | 	static function get_all(): Array<Display> { | ||||||
|  | 		return [primary]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var available(get, never): Bool; | ||||||
|  |  | ||||||
|  | 	function get_available(): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var name(get, never): String; | ||||||
|  |  | ||||||
|  | 	function get_name(): String { | ||||||
|  | 		return "Display"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var x(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_x(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var y(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_y(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var width(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return 1920; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return 1080; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var frequency(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_frequency(): Int { | ||||||
|  | 		return 60; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var pixelsPerInch(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_pixelsPerInch(): Int { | ||||||
|  | 		return 96; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var modes(get, never): Array<DisplayMode>; | ||||||
|  |  | ||||||
|  | 	function get_modes(): Array<DisplayMode> { | ||||||
|  | 		return []; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								Kha/Backends/Java/kha/Font.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Kha/Backends/Java/kha/Font.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | typedef Font = kha.java.Font; | ||||||
							
								
								
									
										162
									
								
								Kha/Backends/Java/kha/Image.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								Kha/Backends/Java/kha/Image.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,162 @@ | |||||||
|  | package kha; | ||||||
|  |  | ||||||
|  | import haxe.io.Bytes; | ||||||
|  | import kha.graphics4.TextureFormat; | ||||||
|  | import kha.graphics4.Usage; | ||||||
|  | import kha.java.Painter; | ||||||
|  |  | ||||||
|  | @:classCode(' | ||||||
|  | 	public java.awt.image.BufferedImage image; | ||||||
|  | ') | ||||||
|  | class Image implements Canvas implements Resource { | ||||||
|  | 	var painter: Painter; | ||||||
|  | 	var graphics1: kha.graphics1.Graphics; | ||||||
|  |  | ||||||
|  | 	public function new(filename: String) {} | ||||||
|  |  | ||||||
|  | 	@:functionCode(' | ||||||
|  | 		image.image = new java.awt.image.BufferedImage(width, height, format == 0 ? 10 : 6); | ||||||
|  | 	') | ||||||
|  | 	static function create2(image: Image, width: Int, height: Int, format: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public static function create(width: Int, height: Int, format: TextureFormat = null, usage: Usage = null): Image { | ||||||
|  | 		var img = new Image(null); | ||||||
|  | 		create2(img, width, height, format == TextureFormat.L8 ? 0 : 1); | ||||||
|  | 		return img; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function create3D(width: Int, height: Int, depth: Int, format: TextureFormat = null, usage: Usage = null): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function createRenderTarget(width: Int, height: Int, format: TextureFormat = null, depthStencil: Bool = false, | ||||||
|  | 			antiAliasingSamples: Int = 1): Image { | ||||||
|  | 		var img = new Image(null); | ||||||
|  | 		create2(img, width, height, format == TextureFormat.L8 ? 0 : 1); | ||||||
|  | 		return img; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromBytes(bytes: Bytes, width: Int, height: Int, format: TextureFormat = null, usage: Usage = null): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function fromBytes3D(bytes: Bytes, width: Int, height: Int, depth: Int, format: TextureFormat = null, usage: Usage = null): Image { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	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; | ||||||
|  |  | ||||||
|  | 	@:functionCode(' | ||||||
|  | 		painter.graphics = image.createGraphics(); | ||||||
|  | 	') | ||||||
|  | 	function initPainter(painter: Painter): Void {} | ||||||
|  |  | ||||||
|  | 	function get_g2(): kha.graphics2.Graphics { | ||||||
|  | 		if (painter == null) { | ||||||
|  | 			painter = new Painter(); | ||||||
|  | 			initPainter(painter); | ||||||
|  | 		} | ||||||
|  | 		return painter; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var g4(get, never): kha.graphics4.Graphics; | ||||||
|  |  | ||||||
|  | 	function get_g4(): kha.graphics4.Graphics { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var width(get, never): Int; | ||||||
|  |  | ||||||
|  | 	@:functionCode(' | ||||||
|  | 		return image.getWidth(null); | ||||||
|  | 	') | ||||||
|  | 	function get_width(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var height(get, never): Int; | ||||||
|  |  | ||||||
|  | 	@:functionCode(' | ||||||
|  | 		return image.getHeight(null); | ||||||
|  | 	') | ||||||
|  | 	function get_height(): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var depth(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_depth(): Int { | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var format(get, never): TextureFormat; | ||||||
|  |  | ||||||
|  | 	@:functionCode(' | ||||||
|  | 		return image.getType(); | ||||||
|  | 	') | ||||||
|  | 	function get_format(): TextureFormat { | ||||||
|  | 		return TextureFormat.RGBA32; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var realWidth(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_realWidth(): Int { | ||||||
|  | 		return width; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var realHeight(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_realHeight(): Int { | ||||||
|  | 		return height; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public var stride(get, never): Int; | ||||||
|  |  | ||||||
|  | 	function get_stride(): Int { | ||||||
|  | 		return realWidth * 4; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@:functionCode(' | ||||||
|  | 		if (x >= 0 && x < get_width() && y >= 0 && y < get_height()) { | ||||||
|  | 			int argb = image.getRGB(x, y); | ||||||
|  | 			return argb >> 24 != 0; | ||||||
|  | 		} | ||||||
|  | 		else return false; | ||||||
|  | 	') | ||||||
|  | 	public function isOpaque(x: Int, y: Int): Bool { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function at(x: Int, y: Int): Int { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unload(): Void {} | ||||||
|  |  | ||||||
|  | 	public function lock(level: Int = 0): Bytes { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function unlock(): Void {} | ||||||
|  |  | ||||||
|  | 	public function getPixels(): Bytes { | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public function generateMipmaps(levels: Int): Void {} | ||||||
|  |  | ||||||
|  | 	public function setMipmaps(mipmaps: Array<Image>): Void {} | ||||||
|  |  | ||||||
|  | 	public function setDepthStencilFrom(image: Image): Void {} | ||||||
|  |  | ||||||
|  | 	public function clear(x: Int, y: Int, z: Int, width: Int, height: Int, depth: Int, color: Color): Void {} | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user