├── .editorconfig ├── .gitignore ├── .gitmodules ├── .npmignore ├── .nvmrc ├── LiCENSE ├── README.md ├── deploy.sh ├── images ├── bouncing-ball.png ├── clock-example.png └── mario.png ├── package.json ├── samples ├── alert-and-confirm-example.js ├── bouncing-ball-example.js ├── circle-example.js ├── clip-example.js ├── clock-example.js ├── clock-example2.js ├── cubic-bezier-curve-example.js ├── document-example.js ├── draw-image-example.js ├── draw-image-example2.js ├── file-drop-example.js ├── filled-rect-example.js ├── focus-example.js ├── fullscreen.js ├── get-image-data-example.js ├── keypress-example.js ├── keyup-example.js ├── line-example.js ├── lineOffsetExample.js ├── looping-panorama-example.js ├── mooninites.png ├── mouse-move-example.js ├── polygon-example.js ├── put-image-data-example.js ├── simple-bounce.js ├── simple-game.js ├── solar-system.js ├── spark.js ├── trailing-bouncing-ball-example.js ├── window-resize.js └── yamcha.jpg ├── src ├── engine │ ├── index.ts │ └── sdl │ │ ├── app │ │ ├── application-context.ts │ │ └── application-frame-manager.ts │ │ ├── canvas │ │ ├── sdl-canvas.ts │ │ └── sdl-context.ts │ │ ├── color │ │ └── rgba.ts │ │ ├── document │ │ └── sdl-document.ts │ │ ├── event │ │ ├── key-event.ts │ │ └── mouse-event.ts │ │ ├── image │ │ └── image.ts │ │ ├── index.ts │ │ ├── performance │ │ └── sdl-performance.ts │ │ ├── sdl-context │ │ ├── index.ts │ │ ├── sdl-context-2d.ts │ │ ├── sdl-renderer.ts │ │ └── sdl-texture.ts │ │ ├── sdl-window │ │ ├── index.ts │ │ ├── messagebox.ts │ │ ├── sdl-navigator.ts │ │ ├── sdl-window-opts.ts │ │ └── sdl-window.ts │ │ ├── sdl │ │ ├── index.ts │ │ ├── lib-loader.ts │ │ ├── libs │ │ │ ├── linux │ │ │ │ ├── arm │ │ │ │ │ └── libSDL2.so │ │ │ │ └── x64 │ │ │ │ │ └── libSDL2.so │ │ │ ├── osx │ │ │ │ ├── arm64 │ │ │ │ │ └── libSDL2-2.0.dylib │ │ │ │ └── x64 │ │ │ │ │ └── libSDL2-2.0.dylib │ │ │ └── windows │ │ │ │ ├── ia32 │ │ │ │ └── SDL2.dll │ │ │ │ └── x64 │ │ │ │ └── SDL2.dll │ │ ├── sdl-events.ts │ │ ├── sdl-gesture.ts │ │ ├── sdl-joystick.ts │ │ ├── sdl-keyboard.ts │ │ ├── sdl-keycode.ts │ │ ├── sdl-messagebox.ts │ │ ├── sdl-mouse.ts │ │ ├── sdl-pixels.ts │ │ ├── sdl-power.ts │ │ ├── sdl-rect.ts │ │ ├── sdl-render.ts │ │ ├── sdl-rwops.ts │ │ ├── sdl-surface.ts │ │ ├── sdl-thread.ts │ │ ├── sdl-timer.ts │ │ ├── sdl-touch.ts │ │ ├── sdl-video.ts │ │ ├── sdl.ts │ │ └── types.ts │ │ ├── shape │ │ ├── point.ts │ │ └── rect.ts │ │ └── thread │ │ └── thread.ts ├── index.ts ├── nodejs │ ├── global.ts │ └── index.ts └── window │ ├── native-window.ts │ └── window-options.ts ├── tsconfig.json ├── tslint.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*.html] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.css] 12 | charset = utf-8 13 | indent_style = space 14 | indent_size = 2 15 | insert_final_newline = true 16 | trim_trailing_whitespace = true 17 | 18 | [*.json] 19 | charset = utf-8 20 | indent_style = space 21 | indent_size = 2 22 | insert_final_newline = true 23 | trim_trailing_whitespace = true 24 | 25 | [*.ejs] 26 | charset = utf-8 27 | indent_style = space 28 | indent_size = 4 29 | insert_final_newline = true 30 | trim_trailing_whitespace = true 31 | 32 | [*.js] 33 | charset = utf-8 34 | indent_style = space 35 | indent_size = 4 36 | insert_final_newline = true 37 | trim_trailing_whitespace = true 38 | 39 | [*.ts] 40 | charset = utf-8 41 | indent_style = space 42 | indent_size = 4 43 | insert_final_newline = true 44 | trim_trailing_whitespace = true 45 | 46 | [*.md] 47 | max_line_length = off 48 | trim_trailing_whitespace = false 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .git 2 | src/test 3 | .idea 4 | .vscode 5 | node_modules 6 | antlr4-parser-tool.iml 7 | lib 8 | *.tgz 9 | dist 10 | package-lock.json 11 | *.iml 12 | build 13 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "modules/SDL2"] 2 | path = modules/SDL2 3 | url = git@github.com:libsdl-org/SDL.git 4 | branch = SDL2 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .git 2 | .idea 3 | node_modules 4 | src 5 | samples 6 | tsconfig.json 7 | antlr4-parser-tool.iml 8 | antlr4-tool.iml 9 | webpack.*.js 10 | 11 | 12 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v21.5.0 2 | -------------------------------------------------------------------------------- /LiCENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2018 by Marlon Chatman 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # native-canvas 2 | 3 | ## Overview 4 | The purpose and intent of this project was to create a library that allows for developers 5 | to create a browser canvas element that runs natively, without the need of a WebBrowser. 6 | Allowing for developers to code and develop portable canvas based applications that 7 | can run both on the WebBrowser and natively on any NodeJS platform. 8 | 9 | ## Requirements 10 | * NodeJS 10+ 11 | 12 | ## Getting Stated 13 | 14 | * Install the **native-canvas** library 15 | 16 | ```bash 17 | npm install native-canvas 18 | ``` 19 | 20 | ## A Simple Example 21 | ```javascript 22 | // Load the library 23 | require('native-canvas'); 24 | 25 | // Use the globally exposed canvas 26 | const ctx = canvas.getContext("2d"); 27 | 28 | ctx.lineWidth = 1; 29 | ctx.fillStyle = "#FF0000"; 30 | ctx.fillRect(0, 0, 150, 75); 31 | ``` 32 | 33 | View the [samples](./samples) directory to see more examples. 34 | 35 | 36 | ## Running a Browser Example 37 | ```javascript 38 | // Load the library 39 | require('native-canvas'); 40 | 41 | // Title the title attribute 42 | document.title = 'Create Canvas with Document'; 43 | 44 | // Provides the current running canvas 45 | const canvas = document.createElement('canvas'); 46 | const ctx = canvas.getContext("2d"); 47 | 48 | canvas.height = 150; 49 | 50 | ctx.lineWidth = 1; 51 | 52 | ctx.clearRect(0, 0, 400, 400); 53 | ctx.beginPath(); 54 | ctx.arc(40, 40, 40, 0, 2 * Math.PI); 55 | ctx.closePath(); 56 | ctx.stroke(); 57 | ``` 58 | 59 | ## Mac OS [Apple Silicon] 60 | 61 | To install you need to install system deps first. 62 | 63 | ```bash 64 | brew install python 65 | arch -arm64 brew install pkg-config cairo pango jpeg giflib librsvg libffi 66 | ``` 67 | 68 | ## Raspberry Pi 69 | 70 | To install on Raspberry Pi, you need to prep your environment 71 | by installing a few dev libraries. 72 | 73 | ```bash 74 | sudo apt install \ 75 | libpixman-1-dev \ 76 | libcairo2-dev \ 77 | libpango1.0-dev \ 78 | libjpeg-dev \ 79 | libgif-dev \ 80 | libsdl2-dev 81 | ``` 82 | 83 | ## Screenshots 84 | 85 | ![Bouncing Ball](./images/bouncing-ball.png) 86 | ![Mario](./images/mario.png) 87 | 88 | ![Example](./images/clock-example.png) 89 | 90 | ## Acknowledgments 91 | Special Thanks to [@dmcquillan314](https://github.com/dmcquillan314) for the support! 92 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | rm -rf node_modules 4 | npm install 5 | npm run build 6 | npm publish 7 | -------------------------------------------------------------------------------- /images/bouncing-ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/images/bouncing-ball.png -------------------------------------------------------------------------------- /images/clock-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/images/clock-example.png -------------------------------------------------------------------------------- /images/mario.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/images/mario.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-canvas", 3 | "version": "1.0.5", 4 | "description": "A canvas library allows for a HTML canvas to run natively on NodeJs, without a WebBrowser", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "lint": "tslint -p . -c tslint.json 'src/**/*.ts'", 10 | "mkdirs": "mkdir -p dist/engine/sdl/sdl/libs", 11 | "libs": "cp -r src/engine/sdl/sdl/libs dist/engine/sdl/sdl", 12 | "build": "rm -rf dist && mkdir -p dist/engine/sdl/sdl/libs && cp -r src/engine/sdl/sdl/libs dist/engine/sdl/sdl && tsc", 13 | "compile": "tsc", 14 | "clean": "rm -rf dist" 15 | }, 16 | "files": [ 17 | "dist", 18 | "LICENSE", 19 | "docs" 20 | ], 21 | "keywords": [ 22 | "canvas", 23 | "native", 24 | "native-javascript", 25 | "typescript", 26 | "node", 27 | "nodejs", 28 | "html-canvas", 29 | "html5", 30 | "html5-canvas", 31 | "game", 32 | "game-development", 33 | "graphics", 34 | "2d-graphics", 35 | "2d", 36 | "game-graphics", 37 | "native-canvas", 38 | "sdl", 39 | "es6", 40 | "sdl2" 41 | ], 42 | "author": { 43 | "name": "Marlon Chatman", 44 | "email": "mcchatman8009@gmail.com" 45 | }, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/mcchatman8009/native-canvas" 49 | }, 50 | "license": "ISC", 51 | "devDependencies": { 52 | "@types/node": "^10.12.2", 53 | "tslint": "^5.11.0", 54 | "typescript": "^3.2.4" 55 | }, 56 | "dependencies": { 57 | "@rgba-image/png": "^0.1.0", 58 | "canvas": "^2.11.2", 59 | "color-rgba": "^2.1.0", 60 | "ffi-napi": "^4.0.3", 61 | "jsdom": "^13.0.0", 62 | "keycode": "^2.2.0", 63 | "pngjs": "^3.3.3", 64 | "ref-array-di": "^1.2.1", 65 | "ref-union-di": "^1.0.1" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /samples/alert-and-confirm-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ok = confirm("Are you ok?"); 4 | 5 | if (ok) { 6 | alert("That's great to hear!"); 7 | } 8 | process.exit(0); 9 | 10 | -------------------------------------------------------------------------------- /samples/bouncing-ball-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | var canvas = document.getElementById('canvas'); 4 | var ctx = canvas.getContext('2d'); 5 | var raf; 6 | 7 | var ball = { 8 | x: 100, 9 | y: 100, 10 | vx: 5, 11 | vy: 2, 12 | radius: 25, 13 | color: 'blue', 14 | draw: function () { 15 | ctx.beginPath(); 16 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); 17 | ctx.closePath(); 18 | ctx.fillStyle = this.color; 19 | ctx.fill(); 20 | } 21 | }; 22 | 23 | function draw() { 24 | ctx.clearRect(0, 0, canvas.width, canvas.height); 25 | ball.draw(); 26 | ball.x += ball.vx; 27 | ball.y += ball.vy; 28 | 29 | if (ball.y + ball.vy > canvas.height || 30 | ball.y + ball.vy < 0) { 31 | ball.vy = -ball.vy; 32 | } 33 | if (ball.x + ball.vx > canvas.width || 34 | ball.x + ball.vx < 0) { 35 | ball.vx = -ball.vx; 36 | } 37 | 38 | raf = window.requestAnimationFrame(draw); 39 | } 40 | 41 | addEventListener('mouseover', function (e) { 42 | raf = window.requestAnimationFrame(draw); 43 | }); 44 | 45 | addEventListener('mouseout', function (e) { 46 | window.cancelAnimationFrame(raf); 47 | }); 48 | 49 | ball.draw(); 50 | -------------------------------------------------------------------------------- /samples/circle-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = window.canvas.getContext("2d"); 4 | canvas.height = 150; 5 | 6 | ctx.lineWidth = 1; 7 | 8 | ctx.clearRect(0, 0, 400, 400); 9 | ctx.beginPath(); 10 | ctx.arc(40, 40, 40, 0, 2 * Math.PI); 11 | ctx.closePath(); 12 | ctx.stroke(); 13 | 14 | -------------------------------------------------------------------------------- /samples/clip-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | // const canvas = nativeCanvas.createCanvas('Basic Example'); 3 | const ctx = canvas.getContext('2d'); 4 | 5 | // Create circular clipping region 6 | ctx.beginPath(); 7 | ctx.arc(100, 75, 50, 0, Math.PI * 2); 8 | ctx.clip(); 9 | 10 | // Draw stuff that gets clipped 11 | ctx.fillStyle = 'blue'; 12 | ctx.fillRect(0, 0, canvas.width, canvas.height); 13 | ctx.fillStyle = 'orange'; 14 | ctx.fillRect(0, 0, 100, 100); 15 | -------------------------------------------------------------------------------- /samples/clock-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | window.title = "Clock Example"; 4 | 5 | function clock() { 6 | const now = new Date(); 7 | const ctx = canvas.getContext('2d'); 8 | ctx.save(); 9 | ctx.clearRect(0, 0, 150, 150); 10 | ctx.translate(75, 75); 11 | ctx.scale(0.4, 0.4); 12 | ctx.rotate(-Math.PI / 2); 13 | ctx.strokeStyle = 'black'; 14 | ctx.fillStyle = 'white'; 15 | ctx.lineWidth = 8; 16 | ctx.lineCap = 'round'; 17 | 18 | // Hour marks 19 | ctx.save(); 20 | for (let i = 0; i < 12; i++) { 21 | ctx.beginPath(); 22 | ctx.rotate(Math.PI / 6); 23 | ctx.moveTo(100, 0); 24 | ctx.lineTo(120, 0); 25 | ctx.stroke(); 26 | } 27 | ctx.restore(); 28 | 29 | // Minute marks 30 | ctx.save(); 31 | ctx.lineWidth = 5; 32 | for (i = 0; i < 60; i++) { 33 | if (i % 5 != 0) { 34 | ctx.beginPath(); 35 | ctx.moveTo(117, 0); 36 | ctx.lineTo(120, 0); 37 | ctx.stroke(); 38 | } 39 | ctx.rotate(Math.PI / 30); 40 | } 41 | ctx.restore(); 42 | 43 | let sec = now.getSeconds(); 44 | let min = now.getMinutes(); 45 | let hr = now.getHours(); 46 | hr = hr >= 12 ? hr - 12 : hr; 47 | 48 | ctx.fillStyle = 'black'; 49 | 50 | // write Hours 51 | ctx.save(); 52 | ctx.rotate(hr * (Math.PI / 6) + (Math.PI / 360) * min + (Math.PI / 21600) * sec); 53 | ctx.lineWidth = 14; 54 | ctx.beginPath(); 55 | ctx.moveTo(-20, 0); 56 | ctx.lineTo(80, 0); 57 | ctx.stroke(); 58 | ctx.restore(); 59 | 60 | // write Minutes 61 | ctx.save(); 62 | ctx.rotate((Math.PI / 30) * min + (Math.PI / 1800) * sec); 63 | ctx.lineWidth = 10; 64 | ctx.beginPath(); 65 | ctx.moveTo(-28, 0); 66 | ctx.lineTo(112, 0); 67 | ctx.stroke(); 68 | ctx.restore(); 69 | 70 | // Write seconds 71 | ctx.save(); 72 | ctx.rotate(sec * Math.PI / 30); 73 | ctx.strokeStyle = '#D40000'; 74 | ctx.fillStyle = '#D40000'; 75 | ctx.lineWidth = 6; 76 | ctx.beginPath(); 77 | ctx.moveTo(-30, 0); 78 | ctx.lineTo(83, 0); 79 | ctx.stroke(); 80 | ctx.beginPath(); 81 | ctx.arc(0, 0, 10, 0, Math.PI * 2, true); 82 | ctx.fill(); 83 | ctx.beginPath(); 84 | ctx.arc(95, 0, 10, 0, Math.PI * 2, true); 85 | ctx.stroke(); 86 | ctx.fillStyle = 'rgba(0, 0, 0, 0)'; 87 | ctx.arc(0, 0, 3, 0, Math.PI * 2, true); 88 | ctx.fill(); 89 | ctx.restore(); 90 | 91 | ctx.beginPath(); 92 | ctx.lineWidth = 14; 93 | ctx.strokeStyle = '#325FA2'; 94 | ctx.arc(0, 0, 142, 0, Math.PI * 2, true); 95 | ctx.stroke(); 96 | 97 | ctx.restore(); 98 | 99 | setTimeout(clock, 15); 100 | } 101 | 102 | setTimeout(clock, 15); 103 | -------------------------------------------------------------------------------- /samples/clock-example2.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | var canvas = document.getElementById("canvas"); 4 | var ctx = canvas.getContext("2d"); 5 | var radius = canvas.height / 2; 6 | ctx.translate(radius, radius); 7 | radius = radius * 0.90; 8 | setInterval(drawClock, 1000); 9 | 10 | function drawClock() { 11 | drawFace(ctx, radius); 12 | drawNumbers(ctx, radius); 13 | drawTime(ctx, radius); 14 | } 15 | 16 | function drawFace(ctx, radius) { 17 | var grad; 18 | ctx.beginPath(); 19 | ctx.arc(0, 0, radius, 0, 2 * Math.PI); 20 | ctx.fillStyle = 'white'; 21 | ctx.fill(); 22 | grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05); 23 | grad.addColorStop(0, '#333'); 24 | grad.addColorStop(0.5, 'white'); 25 | grad.addColorStop(1, '#333'); 26 | ctx.strokeStyle = grad; 27 | ctx.lineWidth = radius * 0.1; 28 | ctx.stroke(); 29 | ctx.beginPath(); 30 | ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI); 31 | ctx.fillStyle = '#333'; 32 | ctx.fill(); 33 | } 34 | 35 | function drawNumbers(ctx, radius) { 36 | var ang; 37 | var num; 38 | ctx.font = radius * 0.15 + "px arial"; 39 | ctx.textBaseline = "middle"; 40 | ctx.textAlign = "center"; 41 | for (num = 1; num < 13; num++) { 42 | ang = num * Math.PI / 6; 43 | ctx.rotate(ang); 44 | ctx.translate(0, -radius * 0.85); 45 | ctx.rotate(-ang); 46 | ctx.fillText(num.toString(), 0, 0); 47 | ctx.rotate(ang); 48 | ctx.translate(0, radius * 0.85); 49 | ctx.rotate(-ang); 50 | } 51 | } 52 | 53 | function drawTime(ctx, radius) { 54 | var now = new Date(); 55 | var hour = now.getHours(); 56 | var minute = now.getMinutes(); 57 | var second = now.getSeconds(); 58 | //hour 59 | hour = hour % 12; 60 | hour = (hour * Math.PI / 6) + 61 | (minute * Math.PI / (6 * 60)) + 62 | (second * Math.PI / (360 * 60)); 63 | drawHand(ctx, hour, radius * 0.5, radius * 0.07); 64 | //minute 65 | minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60)); 66 | drawHand(ctx, minute, radius * 0.8, radius * 0.07); 67 | // second 68 | second = (second * Math.PI / 30); 69 | drawHand(ctx, second, radius * 0.9, radius * 0.02); 70 | } 71 | 72 | function drawHand(ctx, pos, length, width) { 73 | ctx.beginPath(); 74 | ctx.lineWidth = width; 75 | ctx.lineCap = "round"; 76 | ctx.moveTo(0, 0); 77 | ctx.rotate(pos); 78 | ctx.lineTo(0, -length); 79 | ctx.stroke(); 80 | ctx.rotate(-pos); 81 | } 82 | -------------------------------------------------------------------------------- /samples/cubic-bezier-curve-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext("2d"); 4 | 5 | // ctx.lineWidth = 2; 6 | ctx.beginPath(); 7 | ctx.moveTo(20,20); 8 | ctx.bezierCurveTo(20,100,200,100,200,20); 9 | ctx.stroke(); 10 | -------------------------------------------------------------------------------- /samples/document-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const canvas = document.createElement('canvas'); 4 | const ctx = canvas.getContext("2d"); 5 | canvas.height = 150; 6 | 7 | ctx.lineWidth = 1; 8 | 9 | ctx.clearRect(0, 0, 400, 400); 10 | ctx.beginPath(); 11 | ctx.arc(40, 40, 40, 0, 2 * Math.PI); 12 | ctx.closePath(); 13 | ctx.stroke(); 14 | 15 | document.title = 'Create Canvas with Document'; 16 | 17 | -------------------------------------------------------------------------------- /samples/draw-image-example.js: -------------------------------------------------------------------------------- 1 | const nativeCanvas = require('../dist'); 2 | 3 | global.window.close(); // close the default window 4 | 5 | const window = nativeCanvas.createWindow({title: 'Yamcha', fitCanvasInWindow: true}); 6 | // window.fullScreen = true; 7 | const canvas = window.canvas; 8 | canvas.width = 520; 9 | const ctx = canvas.getContext('2d'); 10 | 11 | ctx.scale(2, 2); 12 | 13 | window.loadImage(__dirname + '/yamcha.jpg').then((img) => { 14 | ctx.drawImage(img, 0, 0); 15 | }); 16 | 17 | window.canvasX = 100; 18 | window.canvasY = 100; 19 | console.log(canvas.width); 20 | 21 | -------------------------------------------------------------------------------- /samples/draw-image-example2.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | window.title = 'Basic Example'; 4 | 5 | const ctx = canvas.getContext('2d'); 6 | 7 | loadImage(__dirname + '/mooninites.png').then((img) => { 8 | ctx.drawImage(img, 0, 0); 9 | }); 10 | 11 | -------------------------------------------------------------------------------- /samples/file-drop-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | window.title = 'Basic Example'; 4 | 5 | const ctx = canvas.getContext("2d"); 6 | 7 | window.addEventListener('drop', (evt) => { 8 | createImage(evt.file).then((img) => { 9 | ctx.drawImage(img, 0, 0); 10 | }); 11 | }); 12 | 13 | ctx.font = "30px Comic Sans MS"; 14 | ctx.fillStyle = 'black'; 15 | ctx.fillText("Please Drag and Drop a Image", 10, 50); 16 | -------------------------------------------------------------------------------- /samples/filled-rect-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext("2d"); 4 | 5 | ctx.lineWidth = 1; 6 | ctx.fillStyle = "#FF0000"; 7 | // ctx.fillStyle = "#FF0000"; 8 | ctx.fillRect(0, 0, 150, 75); 9 | // ctx.rect(0, 0, 150, 75); 10 | // ctx.stroke(); 11 | -------------------------------------------------------------------------------- /samples/focus-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext("2d"); 4 | 5 | canvas.addEventListener('focus', (evt) => { 6 | ctx.clearRect(0, 0, canvas.width, canvas.height); 7 | ctx.fillStyle = 'red'; 8 | ctx.fillRect(0, 0, canvas.width, canvas.height); 9 | }); 10 | 11 | canvas.addEventListener('blur', (evt) => { 12 | ctx.clearRect(0, 0, canvas.width, canvas.height); 13 | ctx.fillStyle = 'white'; 14 | ctx.fillRect(0, 0, canvas.width, canvas.height); 15 | }); 16 | -------------------------------------------------------------------------------- /samples/fullscreen.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const canvas = document.createElement('canvas'); 4 | 5 | const ctx = canvas.getContext("2d"); 6 | canvas.height = 150; 7 | 8 | canvas.requestFullscreen(); 9 | 10 | ctx.font = "30px Comic Sans MS"; 11 | ctx.fillStyle = 'black'; 12 | ctx.fillText("Click to Exit FullScreen", 10, 50); 13 | 14 | document.title = 'Fullscreen'; 15 | 16 | 17 | document.onclick = (evt) => { 18 | document.exitFullscreen(); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /samples/get-image-data-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext("2d"); 4 | ctx.rect(10, 10, 100, 100); 5 | ctx.fill(); 6 | 7 | let imageData = ctx.getImageData(60, 60, 200, 100); 8 | ctx.putImageData(imageData, 150, 10); 9 | -------------------------------------------------------------------------------- /samples/keypress-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext("2d"); 4 | 5 | canvas.addEventListener('keypress', (evt) => { 6 | console.log(evt); 7 | ctx.clearRect(0, 0, canvas.width, canvas.height); 8 | ctx.lineWidth = 1; 9 | ctx.beginPath(); 10 | ctx.arc(40, 40, 40, 0, 2 * Math.PI); 11 | ctx.closePath(); 12 | ctx.stroke(); 13 | ctx.font = "30px Comic Sans MS"; 14 | ctx.fillStyle = 'black'; 15 | ctx.fillText(`"${evt.key}"`, 10, 50); 16 | }); 17 | 18 | ctx.clearRect(0, 0, canvas.width, canvas.height); 19 | ctx.lineWidth = 1; 20 | ctx.beginPath(); 21 | ctx.arc(40, 40, 40, 0, 2 * Math.PI); 22 | ctx.closePath(); 23 | ctx.stroke(); 24 | 25 | -------------------------------------------------------------------------------- /samples/keyup-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext("2d"); 4 | // internalCanvas.height = 150; 5 | 6 | ctx.lineWidth = 1; 7 | canvas.addEventListener('keydown', (evt) => { 8 | console.log(evt); 9 | }); 10 | ctx.clearRect(0, 0, canvas.width, canvas.height); 11 | 12 | ctx.beginPath(); 13 | ctx.arc(40, 40, 40, 0, 2 * Math.PI); 14 | ctx.closePath(); 15 | ctx.stroke(); 16 | 17 | -------------------------------------------------------------------------------- /samples/line-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext('2d'); 4 | ctx.moveTo(0, 0); 5 | ctx.lineTo(200, 100); 6 | ctx.stroke(); 7 | -------------------------------------------------------------------------------- /samples/lineOffsetExample.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext('2d'); 4 | 5 | let offset = 0; 6 | let x = 10; 7 | let y = 10; 8 | 9 | let color = 'white'; 10 | 11 | canvas.addEventListener('mouseleave', (evt) => { 12 | color = "white"; 13 | }); 14 | 15 | canvas.addEventListener('mouseover', (evt) => { 16 | color = "cyan"; 17 | }); 18 | 19 | canvas.addEventListener('mousemove', (evt) => { 20 | x = evt.clientX; 21 | y = evt.clientY; 22 | }); 23 | 24 | // let offset = 0; 25 | 26 | function draw() { 27 | ctx.clearRect(0, 0, canvas.width, canvas.height); 28 | ctx.fillStyle = color; 29 | ctx.fillRect(0, 0, canvas.width, canvas.height); 30 | ctx.setLineDash([4, 2]); 31 | ctx.lineDashOffset = -offset; 32 | ctx.strokeRect(x, y, 100, 100); 33 | } 34 | 35 | function march() { 36 | offset++; 37 | if (offset > 16) { 38 | offset = 0; 39 | } 40 | draw(); 41 | setTimeout(march, 20); 42 | } 43 | 44 | march(); 45 | -------------------------------------------------------------------------------- /samples/looping-panorama-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | let img = new Image(); 4 | 5 | 6 | // User Variables - customize these to change the image being scrolled, its 7 | // direction, and the speed. 8 | 9 | img.src = 'https://mdn.mozillademos.org/files/4553/Capitan_Meadows,_Yosemite_National_Park.jpg'; 10 | 11 | let CanvasXSize = 800; 12 | let CanvasYSize = 200; 13 | let speed = 30; // lower is faster 14 | let scale = 1.05; 15 | let y = -4.5; // vertical offset 16 | 17 | // Main program 18 | 19 | let dx = 0.75; 20 | let imgW; 21 | let imgH; 22 | let x = 0; 23 | let clearX; 24 | let clearY; 25 | let ctx; 26 | 27 | img.onload = function () { 28 | imgW = img.width * scale; 29 | imgH = img.height * scale; 30 | 31 | if (imgW > CanvasXSize) { 32 | // image larger than internalCanvas 33 | x = CanvasXSize - imgW; 34 | } 35 | if (imgW > CanvasXSize) { 36 | // image width larger than internalCanvas 37 | clearX = imgW; 38 | } else { 39 | clearX = CanvasXSize; 40 | } 41 | if (imgH > CanvasYSize) { 42 | // image height larger than internalCanvas 43 | clearY = imgH; 44 | } else { 45 | clearY = CanvasYSize; 46 | } 47 | 48 | // get internalCanvas context 49 | ctx = document.getElementById('internalCanvas').getContext('2d'); 50 | 51 | // set refresh rate 52 | return setInterval(draw, speed); 53 | }; 54 | 55 | function draw() { 56 | ctx.clearRect(0, 0, clearX, clearY); // clear the internalCanvas 57 | 58 | // if image is <= Canvas Size 59 | if (imgW <= CanvasXSize) { 60 | // reset, start from beginning 61 | if (x > CanvasXSize) { 62 | x = -imgW + x; 63 | } 64 | // draw additional image1 65 | if (x > 0) { 66 | ctx.drawImage(img, -imgW + x, y, imgW, imgH); 67 | } 68 | // draw additional image2 69 | if (x - imgW > 0) { 70 | ctx.drawImage(img, -imgW * 2 + x, y, imgW, imgH); 71 | } 72 | } 73 | 74 | // image is > Canvas Size 75 | else { 76 | // reset, start from beginning 77 | if (x > (CanvasXSize)) { 78 | x = CanvasXSize - imgW; 79 | } 80 | // draw aditional image 81 | if (x > (CanvasXSize - imgW)) { 82 | ctx.drawImage(img, x - imgW + 1, y, imgW, imgH); 83 | } 84 | } 85 | // draw image 86 | ctx.drawImage(img, x, y, imgW, imgH); 87 | // amount to move 88 | x += dx; 89 | } 90 | -------------------------------------------------------------------------------- /samples/mooninites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/samples/mooninites.png -------------------------------------------------------------------------------- /samples/mouse-move-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext("2d"); 4 | // internalCanvas.height = 150; 5 | 6 | ctx.lineWidth = 1; 7 | canvas.addEventListener('mousemove', (evt) => { 8 | ctx.clearRect(0, 0, canvas.width, canvas.height); 9 | 10 | ctx.beginPath(); 11 | ctx.arc(evt.clientX, evt.clientY, 40, 0, 2 * Math.PI); 12 | ctx.closePath(); 13 | ctx.stroke(); 14 | 15 | if (evt.ctrlKey) { 16 | console.log(evt); 17 | } 18 | 19 | }); 20 | 21 | -------------------------------------------------------------------------------- /samples/polygon-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext("2d"); 4 | 5 | ctx.fillStyle = '#ff0000'; 6 | ctx.beginPath(); 7 | ctx.moveTo(0, 0); 8 | ctx.lineTo(100, 50); 9 | ctx.lineTo(50, 100); 10 | ctx.lineTo(0, 90); 11 | ctx.closePath(); 12 | ctx.fill(); 13 | -------------------------------------------------------------------------------- /samples/put-image-data-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext("2d"); 4 | 5 | function putImageData(ctx, imageData, dx, dy, 6 | dirtyX, dirtyY, dirtyWidth, dirtyHeight) { 7 | const data = imageData.data; 8 | const height = imageData.height; 9 | const width = imageData.width; 10 | dirtyX = dirtyX || 0; 11 | dirtyY = dirtyY || 0; 12 | dirtyWidth = dirtyWidth !== undefined ? dirtyWidth : width; 13 | dirtyHeight = dirtyHeight !== undefined ? dirtyHeight : height; 14 | const limitBottom = dirtyY + dirtyHeight; 15 | const limitRight = dirtyX + dirtyWidth; 16 | 17 | for (let y = dirtyY; y < limitBottom; y++) { 18 | for (let x = dirtyX; x < limitRight; x++) { 19 | let pos = y * width + x; 20 | ctx.fillStyle = 'rgba(' + data[pos * 4 + 0] 21 | + ',' + data[pos * 4 + 1] 22 | + ',' + data[pos * 4 + 2] 23 | + ',' + (data[pos * 4 + 3] / 255) + ')'; 24 | ctx.fillRect(x + dx, y + dy, 1, 1); 25 | } 26 | } 27 | } 28 | 29 | // Draw content onto the internalCanvas 30 | ctx.fillRect(0, 0, 100, 100); 31 | // Create an ImageData object from it 32 | const imagedata = ctx.getImageData(0, 0, 100, 100); 33 | // use the putImageData function that illustrates how putImageData works 34 | putImageData(ctx, imagedata, 150, 0, 50, 50, 25, 25); 35 | -------------------------------------------------------------------------------- /samples/simple-bounce.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | var myGamePiece; 4 | 5 | function startGame() { 6 | myGamePiece = new component(30, 30, "red", 80, 75); 7 | myGameArea.start(); 8 | } 9 | 10 | var myGameArea = { 11 | canvas: document.createElement("canvas"), 12 | start: function () { 13 | this.canvas.width = 480; 14 | this.canvas.height = 270; 15 | this.context = this.canvas.getContext("2d"); 16 | document.body.insertBefore(this.canvas, document.body.childNodes[0]); 17 | this.interval = setInterval(updateGameArea, 20); 18 | }, 19 | stop: function () { 20 | clearInterval(this.interval); 21 | }, 22 | clear: function () { 23 | this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 24 | } 25 | }; 26 | 27 | function component(width, height, color, x, y, type) { 28 | this.type = type; 29 | this.width = width; 30 | this.height = height; 31 | this.x = x; 32 | this.y = y; 33 | this.speedX = 0; 34 | this.speedY = 0; 35 | this.gravity = 0.1; 36 | this.gravitySpeed = 0; 37 | this.bounce = 0.6; 38 | this.update = function () { 39 | ctx = myGameArea.context; 40 | ctx.fillStyle = color; 41 | ctx.fillRect(this.x, this.y, this.width, this.height); 42 | }; 43 | this.newPos = function () { 44 | this.gravitySpeed += this.gravity; 45 | this.x += this.speedX; 46 | this.y += this.speedY + this.gravitySpeed; 47 | this.hitBottom(); 48 | }; 49 | this.hitBottom = function () { 50 | var rockbottom = myGameArea.canvas.height - this.height; 51 | if (this.y > rockbottom) { 52 | this.y = rockbottom; 53 | this.gravitySpeed = -(this.gravitySpeed * this.bounce); 54 | } 55 | }; 56 | } 57 | 58 | function updateGameArea() { 59 | myGameArea.clear(); 60 | myGamePiece.newPos(); 61 | myGamePiece.update(); 62 | } 63 | 64 | window.addEventListener('load', () => startGame()); 65 | -------------------------------------------------------------------------------- /samples/simple-game.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | var myGamePiece; 4 | var myObstacles = []; 5 | var myScore; 6 | var description; 7 | 8 | function startGame() { 9 | myGamePiece = new component(30, 30, "red", 10, 120); 10 | myGamePiece.gravity = 0.05; 11 | myScore = new component("30px", "Consolas", "black", 280, 40, "text"); 12 | description = new component("10px", "Consolas", "black", 10, 10, "text"); 13 | myGameArea.start(); 14 | } 15 | 16 | var myGameArea = { 17 | canvas: document.createElement("canvas"), 18 | start: function () { 19 | this.canvas.width = 480; 20 | this.canvas.height = 270; 21 | this.context = this.canvas.getContext("2d"); 22 | document.body.insertBefore(this.canvas, document.body.childNodes[0]); 23 | this.frameNo = 0; 24 | this.interval = setInterval(updateGameArea, 20); 25 | }, 26 | clear: function () { 27 | this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 28 | } 29 | }; 30 | 31 | function component(width, height, color, x, y, type) { 32 | this.type = type; 33 | this.score = 0; 34 | this.width = width; 35 | this.height = height; 36 | this.speedX = 0; 37 | this.speedY = 0; 38 | this.x = x; 39 | this.y = y; 40 | this.gravity = 0; 41 | this.gravitySpeed = 0; 42 | 43 | this.update = function () { 44 | ctx = myGameArea.context; 45 | if (this.type == "text") { 46 | ctx.font = this.width + " " + this.height; 47 | ctx.fillStyle = color; 48 | ctx.fillText(this.text, this.x, this.y); 49 | } else { 50 | ctx.fillStyle = color; 51 | ctx.fillRect(this.x, this.y, this.width, this.height); 52 | } 53 | }; 54 | this.newPos = function () { 55 | this.gravitySpeed += this.gravity; 56 | this.x += this.speedX; 57 | this.y += this.speedY + this.gravitySpeed; 58 | this.hitBottom(); 59 | }; 60 | this.hitBottom = function () { 61 | var rockbottom = myGameArea.canvas.height - this.height; 62 | if (this.y > rockbottom) { 63 | this.y = rockbottom; 64 | this.gravitySpeed = 0; 65 | } 66 | }; 67 | this.crashWith = function (otherobj) { 68 | var myleft = this.x; 69 | var myright = this.x + (this.width); 70 | var mytop = this.y; 71 | var mybottom = this.y + (this.height); 72 | var otherleft = otherobj.x; 73 | var otherright = otherobj.x + (otherobj.width); 74 | var othertop = otherobj.y; 75 | var otherbottom = otherobj.y + (otherobj.height); 76 | var crash = true; 77 | if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) { 78 | crash = false; 79 | } 80 | return crash; 81 | }; 82 | } 83 | 84 | function updateGameArea() { 85 | var x, height, gap, minHeight, maxHeight, minGap, maxGap; 86 | for (i = 0; i < myObstacles.length; i += 1) { 87 | if (myGamePiece.crashWith(myObstacles[i])) { 88 | return; 89 | } 90 | } 91 | myGameArea.clear(); 92 | myGameArea.frameNo += 1; 93 | if (myGameArea.frameNo == 1 || everyinterval(150)) { 94 | x = myGameArea.canvas.width; 95 | minHeight = 20; 96 | maxHeight = 200; 97 | height = Math.floor(Math.random() * (maxHeight - minHeight + 1) + minHeight); 98 | minGap = 50; 99 | maxGap = 200; 100 | gap = Math.floor(Math.random() * (maxGap - minGap + 1) + minGap); 101 | myObstacles.push(new component(10, height, "green", x, 0)); 102 | myObstacles.push(new component(10, x - height - gap, "green", x, height + gap)); 103 | } 104 | for (i = 0; i < myObstacles.length; i += 1) { 105 | myObstacles[i].x += -1; 106 | myObstacles[i].update(); 107 | } 108 | myScore.text = "SCORE: " + myGameArea.frameNo; 109 | description.text = "Hold the mouse to accelerate"; 110 | 111 | description.update(); 112 | myScore.update(); 113 | myGamePiece.newPos(); 114 | myGamePiece.update(); 115 | } 116 | 117 | function everyinterval(n) { 118 | if ((myGameArea.frameNo / n) % 1 == 0) { 119 | return true; 120 | } 121 | return false; 122 | } 123 | 124 | function accelerate(n) { 125 | myGamePiece.gravity = n; 126 | } 127 | 128 | window.addEventListener('load', () => startGame()); 129 | 130 | window.addEventListener('mousedown', () => accelerate(-0.2)); 131 | 132 | window.addEventListener('mouseup', () => accelerate(0.05)); 133 | -------------------------------------------------------------------------------- /samples/solar-system.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const canvas = document.getElementById('canvas'); 4 | const ctx = canvas.getContext('2d'); 5 | 6 | const sun = new Image(); 7 | const moon = new Image(); 8 | const earth = new Image(); 9 | let counter = 3; 10 | 11 | function init() { 12 | sun.src = 'https://mdn.mozillademos.org/files/1456/Canvas_sun.png'; 13 | sun.onload = () => counter--; 14 | moon.src = 'https://mdn.mozillademos.org/files/1443/Canvas_moon.png'; 15 | moon.onload = () => counter--; 16 | earth.src = 'https://mdn.mozillademos.org/files/1429/Canvas_earth.png'; 17 | earth.onload = () => counter--; 18 | 19 | requestAnimationFrame(draw); 20 | } 21 | 22 | function draw() { 23 | if (counter === 0) { 24 | 25 | ctx.globalCompositeOperation = 'destination-over'; 26 | ctx.clearRect(0, 0, 300, 300); // clear internalCanvas 27 | 28 | ctx.fillStyle = 'rgba(0, 0, 0, 0.4)'; 29 | ctx.strokeStyle = 'rgba(0, 153, 255, 0.4)'; 30 | ctx.save(); 31 | ctx.translate(150, 150); 32 | 33 | // Earth 34 | const time = new Date(); 35 | ctx.rotate(((2 * Math.PI) / 60) * time.getSeconds() + ((2 * Math.PI) / 60000) * time.getMilliseconds()); 36 | ctx.translate(105, 0); 37 | ctx.fillRect(0, -12, 40, 24); // Shadow 38 | ctx.drawImage(earth, -12, -12); 39 | 40 | // Moon 41 | ctx.save(); 42 | ctx.rotate(((2 * Math.PI) / 6) * time.getSeconds() + ((2 * Math.PI) / 6000) * time.getMilliseconds()); 43 | ctx.translate(0, 28.5); 44 | ctx.drawImage(moon, -3.5, -3.5); 45 | ctx.restore(); 46 | 47 | ctx.restore(); 48 | 49 | ctx.beginPath(); 50 | ctx.arc(150, 150, 105, 0, Math.PI * 2, false); // Earth orbit 51 | ctx.stroke(); 52 | 53 | ctx.drawImage(sun, 0, 0, 300, 300); 54 | } 55 | 56 | requestAnimationFrame(draw); 57 | } 58 | 59 | init(); 60 | -------------------------------------------------------------------------------- /samples/spark.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext('2d'); 4 | 5 | function spark(ctx, data) { 6 | let len = data.length; 7 | let pad = 1; 8 | let width = ctx.canvas.width; 9 | let height = ctx.canvas.height; 10 | let barWidth = width / len; 11 | let max = Math.max.apply(null, data); 12 | 13 | ctx.fillStyle = 'rgba(0,0,255,0.5)'; 14 | ctx.strokeStyle = 'red'; 15 | ctx.lineWidth = 1; 16 | 17 | data.forEach(function (n, i) { 18 | let x = i * barWidth + pad; 19 | let y = height * (n / max); 20 | 21 | ctx.lineTo(x, height - y); 22 | ctx.fillRect(x, height, barWidth - pad, -y); 23 | }); 24 | 25 | ctx.stroke(); 26 | } 27 | 28 | spark(ctx, [1, 2, 4, 5, 10, 4, 2, 5, 4, 3, 3, 2]); 29 | -------------------------------------------------------------------------------- /samples/trailing-bouncing-ball-example.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const canvas = document.getElementById('internalCanvas'); 4 | const ctx = canvas.getContext('2d'); 5 | window.title = 'Bouncing Ball'; 6 | let raf; 7 | 8 | const ball = { 9 | x: 100, 10 | y: 100, 11 | vx: 5, 12 | vy: 2, 13 | radius: 25, 14 | color: 'blue', 15 | draw: function () { 16 | ctx.beginPath(); 17 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); 18 | ctx.closePath(); 19 | ctx.fillStyle = this.color; 20 | ctx.fill(); 21 | } 22 | }; 23 | 24 | function draw() { 25 | ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; 26 | ctx.fillRect(0, 0, canvas.width, canvas.height); 27 | ball.draw(); 28 | ball.x += ball.vx; 29 | ball.y += ball.vy; 30 | ball.vy *= .99; 31 | ball.vy += .25; 32 | 33 | if (ball.y + ball.vy > canvas.height || 34 | ball.y + ball.vy < 0) { 35 | ball.vy = -ball.vy; 36 | } 37 | if (ball.x + ball.vx > canvas.width || 38 | ball.x + ball.vx < 0) { 39 | ball.vx = -ball.vx; 40 | } 41 | 42 | raf = window.requestAnimationFrame(draw); 43 | } 44 | 45 | canvas.addEventListener('mouseover', function (e) { 46 | raf = window.requestAnimationFrame(draw); 47 | }); 48 | 49 | canvas.addEventListener('mouseout', function (e) { 50 | window.cancelAnimationFrame(raf); 51 | }); 52 | 53 | ball.draw(); 54 | -------------------------------------------------------------------------------- /samples/window-resize.js: -------------------------------------------------------------------------------- 1 | require('../dist'); 2 | 3 | const ctx = canvas.getContext("2d"); 4 | 5 | const draw = () => { 6 | ctx.clearRect(0, 0, canvas.width, canvas.height); 7 | ctx.lineWidth = 10; 8 | ctx.strokeStyle = 'black'; 9 | ctx.rect(0, 0, canvas.width, canvas.height); 10 | ctx.stroke(); 11 | }; 12 | 13 | window.addEventListener('resize', draw); 14 | 15 | draw(); 16 | 17 | -------------------------------------------------------------------------------- /samples/yamcha.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/samples/yamcha.jpg -------------------------------------------------------------------------------- /src/engine/index.ts: -------------------------------------------------------------------------------- 1 | import {WindowOptions} from '../window/window-options'; 2 | import * as SDL from './sdl'; 3 | import {NativeWindow} from '../window/native-window'; 4 | 5 | export function cancelAnimationFrame(engine: string, request: number): void { 6 | switch (engine) { 7 | case 'sdl': 8 | SDL.cancelAnimationFrame(request); 9 | return; 10 | } 11 | 12 | throw new ReferenceError(`Unknown engine ${engine}`); 13 | } 14 | 15 | export function requestAnimationFrame(engine: string, callback: FrameRequestCallback): number { 16 | switch (engine) { 17 | case 'sdl': 18 | return SDL.requestAnimationFrame(callback); 19 | } 20 | 21 | throw new ReferenceError(`Unknown engine ${engine}`); 22 | } 23 | 24 | export function alert(engine: string, message?: string) { 25 | switch (engine) { 26 | case 'sdl': 27 | SDL.alert(message); 28 | return; 29 | } 30 | 31 | throw new ReferenceError(`Unknown engine ${engine}`); 32 | } 33 | 34 | export function confirm(engine: string, message?: string): boolean { 35 | switch (engine) { 36 | case 'sdl': 37 | return SDL.confirm(message); 38 | } 39 | 40 | throw new ReferenceError(`Unknown engine ${engine}`); 41 | } 42 | 43 | export function createWindow(engine: string, options: WindowOptions): NativeWindow { 44 | switch (engine) { 45 | case 'sdl': 46 | return SDL.createWindow(options); 47 | } 48 | 49 | throw new ReferenceError(`Unknown engine ${engine}`); 50 | } 51 | -------------------------------------------------------------------------------- /src/engine/sdl/app/application-context.ts: -------------------------------------------------------------------------------- 1 | import {SdlWindow} from '../sdl-window/sdl-window'; 2 | import EventEmitter = require('events'); 3 | import { 4 | createEventFilterFunction, createSDLEvent, 5 | SDL_AddEventWatch, 6 | SDL_EventType, 7 | SDL_Init, SDL_PollEvent, SDL_PumpEvents, 8 | SDL_Quit 9 | } from '../sdl'; 10 | import {ApplicationFrameManager} from './application-frame-manager'; 11 | import {createThreadFunction, SDL_CreateThread} from '../sdl/sdl-thread'; 12 | import {SDL_Delay} from '../sdl/sdl-timer'; 13 | 14 | const FPS = 60; 15 | 16 | // const globalAppHolder: any = { 17 | // filter: (data: any, event: any) => { 18 | // } 19 | // }; 20 | let globalEventFilterFunction = null as any; 21 | let f = null; 22 | 23 | export class ApplicationContext extends EventEmitter implements ApplicationFrameManager { 24 | private windows: { [id: number]: SdlWindow } = {}; 25 | 26 | constructor() { 27 | super(); 28 | const sdlFlags = 0x00000020; 29 | 30 | if (SDL_Init(sdlFlags) !== 0) { 31 | this.quit(); 32 | return; 33 | } 34 | 35 | 36 | this.initEvents(); 37 | this.initEventWatcher(); 38 | this.startRenderingFrames(); 39 | } 40 | 41 | initEventWatcher() { 42 | globalEventFilterFunction = createEventFilterFunction((data: any, event: any) => { 43 | event = event.deref(); 44 | if (event.type === SDL_EventType.SDL_DROPFILE) { 45 | this.emitToWindows(event); 46 | } else if (event.type === SDL_EventType.SDL_DROPBEGIN) { 47 | this.emitToWindows(event); 48 | } else if (event.type === SDL_EventType.SDL_DROPCOMPLETE) { 49 | this.emitToWindows(event); 50 | } else if (event.type >= SDL_EventType.SDL_WINDOWEVENT && event.type <= SDL_EventType.SDL_MOUSEWHEEL) { 51 | const windowId = event.window.windowID; 52 | const win = this.windows[windowId]; 53 | 54 | if (win) { 55 | win.emit('sdlEvent', event); 56 | } 57 | } else { 58 | this.emit('sdlEvent', event); 59 | } 60 | }); 61 | SDL_AddEventWatch(globalEventFilterFunction, null); 62 | } 63 | 64 | emitToWindows(event: any) { 65 | Object.keys(this.windows).forEach((key: any) => { 66 | const window = this.windows[key]; 67 | window.emit('sdlEvent', event); 68 | }); 69 | } 70 | 71 | initEvents() { 72 | this.on('sdlEvent', (event) => { 73 | if (event.type === SDL_EventType.SDL_QUIT) { 74 | this.quit(); 75 | } 76 | }); 77 | 78 | this.on('beforeQuit', () => { 79 | /*tslint:disable*/ 80 | for (let key in this.windows) { 81 | /*tslint:enable*/ 82 | const window = this.windows[key]; 83 | window.destroy(); 84 | } 85 | }); 86 | } 87 | 88 | renderFrame(ms: number): void { 89 | this.emit('renderFrame', ms); 90 | 91 | /*tslint:disable*/ 92 | for (let key in this.windows) { 93 | const window = this.windows[key]; 94 | window.renderFrame(ms); 95 | } 96 | /*tslint:enable*/ 97 | } 98 | 99 | cancelAnimationFrame(request: number): void { 100 | this.listeners('renderFrame').forEach((listener) => { 101 | this.off('renderFrame', listener as any); 102 | }); 103 | } 104 | 105 | requestAnimationFrame(callback: FrameRequestCallback): number { 106 | this.once('renderFrame', callback); 107 | 108 | return Number.MAX_VALUE; 109 | } 110 | 111 | 112 | startRenderingFrames(): void { 113 | this.startRenderingFramesUsingInterval(); 114 | } 115 | 116 | private startRenderingFramesUsingInterval(): void { 117 | const targetRefreshRate = 1000 / FPS; 118 | // let lastRenderedTime = new Date().getTime(); 119 | // let pendingEvent = 0; 120 | const event = createSDLEvent(); 121 | 122 | SDL_PumpEvents(); 123 | const loop = () => { 124 | // console.time('SDL_PollEvent'); 125 | SDL_PumpEvents(); 126 | // console.timeEnd('SDL_PollEvent'); 127 | 128 | const currentTime = new Date().getTime(); 129 | // const diff = currentTime - lastRenderedTime; 130 | // console.log(diff); 131 | 132 | // console.time('renderFrame'); 133 | this.renderFrame(currentTime); 134 | // console.timeEnd('renderFrame'); 135 | 136 | // lastRenderedTime = currentTime; 137 | }; 138 | 139 | setInterval(loop, targetRefreshRate); 140 | } 141 | 142 | private startRenderingFramesUsingTimeouts(): void { 143 | let lastRenderedTime = new Date().getTime(); 144 | const targetRefreshRate = 1000 / FPS; 145 | 146 | let update: () => void; 147 | 148 | update = () => { 149 | 150 | const currentTime = new Date().getTime(); 151 | 152 | this.renderFrame(currentTime); 153 | 154 | const timeToRender = currentTime - lastRenderedTime; 155 | const timeoutValue = Math.max(targetRefreshRate - timeToRender, 0); 156 | 157 | lastRenderedTime = currentTime; 158 | // console.log(timeoutValue); 159 | 160 | setTimeout(update, timeoutValue); 161 | }; 162 | 163 | setImmediate(update); 164 | } 165 | 166 | getWindows() { 167 | return this.windows; 168 | } 169 | 170 | registerWindow(window: SdlWindow) { 171 | this.windows[window.id] = window; 172 | } 173 | 174 | quit() { 175 | this.exit(); 176 | } 177 | 178 | exit(exitCode = 0) { 179 | SDL_Quit(); 180 | process.exit(exitCode); 181 | } 182 | } 183 | 184 | export const applicationContext = new ApplicationContext(); 185 | -------------------------------------------------------------------------------- /src/engine/sdl/app/application-frame-manager.ts: -------------------------------------------------------------------------------- 1 | export interface ApplicationFrameManager { 2 | startRenderingFrames(): void; 3 | 4 | renderFrame(ms: number): void; 5 | } 6 | -------------------------------------------------------------------------------- /src/engine/sdl/canvas/sdl-context.ts: -------------------------------------------------------------------------------- 1 | import {Image} from '../image/image'; 2 | 3 | export class SdlContext implements CanvasRenderingContext2D { 4 | private _mozImageSmoothingEnabled: boolean; 5 | private _msFillRule: CanvasFillRule; 6 | private _oImageSmoothingEnabled: boolean; 7 | private _webkitImageSmoothingEnabled: boolean; 8 | private _direction: any; 9 | private _filter: string; 10 | private _font: string; 11 | private _globalAlpha: number; 12 | private _globalCompositeOperation: string; 13 | private _imageSmoothingEnabled: boolean; 14 | private _imageSmoothingQuality: any; 15 | private _lineCap: any; 16 | private _lineDashOffset: number; 17 | private _lineJoin: any; 18 | private _lineWidth: number; 19 | private _miterLimit: number; 20 | private _shadowBlur: number; 21 | private _shadowColor: string; 22 | private _shadowOffsetX: number; 23 | private _shadowOffsetY: number; 24 | private _strokeStyle: string | CanvasGradient | CanvasPattern; 25 | private _textAlign: any; 26 | private _textBaseline: any; 27 | private _fillStyle: string | CanvasGradient | CanvasPattern; 28 | private _canvas: HTMLCanvasElement; 29 | private _ctx: CanvasRenderingContext2D; 30 | 31 | constructor(canvas: HTMLCanvasElement) { 32 | this._canvas = canvas; 33 | this._ctx = canvas.getContext('2d'); 34 | 35 | // this.fillStyle = '#FFFFFF'; 36 | // this.strokeStyle = '#000000'; 37 | // this.fillRect(0, 0, internalCanvas.width, internalCanvas.height); 38 | // 39 | // this.fillStyle = '#000000'; 40 | // this.strokeStyle = '#000000'; 41 | } 42 | 43 | get canvas() { 44 | return this._canvas; 45 | } 46 | 47 | get mozImageSmoothingEnabled(): boolean { 48 | return this._mozImageSmoothingEnabled; 49 | } 50 | 51 | set mozImageSmoothingEnabled(value: boolean) { 52 | this._mozImageSmoothingEnabled = value; 53 | } 54 | 55 | get msFillRule(): CanvasFillRule { 56 | return this._msFillRule; 57 | } 58 | 59 | set msFillRule(value: CanvasFillRule) { 60 | this._msFillRule = value; 61 | } 62 | 63 | get oImageSmoothingEnabled(): boolean { 64 | return this._oImageSmoothingEnabled; 65 | } 66 | 67 | set oImageSmoothingEnabled(value: boolean) { 68 | this._oImageSmoothingEnabled = value; 69 | } 70 | 71 | get webkitImageSmoothingEnabled(): boolean { 72 | return this._webkitImageSmoothingEnabled; 73 | } 74 | 75 | set webkitImageSmoothingEnabled(value: boolean) { 76 | this._webkitImageSmoothingEnabled = value; 77 | } 78 | 79 | get direction(): any { 80 | return this._direction; 81 | } 82 | 83 | set direction(value: any) { 84 | this._direction = value; 85 | this._ctx.direction = value; 86 | } 87 | 88 | get filter(): string { 89 | return this._filter; 90 | } 91 | 92 | set filter(value: string) { 93 | this._filter = value; 94 | this._ctx.filter = value; 95 | } 96 | 97 | get font(): string { 98 | return this._font; 99 | } 100 | 101 | set font(value: string) { 102 | this._font = value; 103 | this._ctx.font = value; 104 | } 105 | 106 | get globalAlpha(): number { 107 | return this._globalAlpha; 108 | } 109 | 110 | set globalAlpha(value: number) { 111 | this._globalAlpha = value; 112 | this._ctx.globalAlpha = value; 113 | } 114 | 115 | get globalCompositeOperation(): string { 116 | return this._globalCompositeOperation; 117 | } 118 | 119 | set globalCompositeOperation(value: string) { 120 | this._globalCompositeOperation = value; 121 | this._ctx.globalCompositeOperation = value; 122 | } 123 | 124 | get imageSmoothingEnabled(): boolean { 125 | return this._imageSmoothingEnabled; 126 | } 127 | 128 | set imageSmoothingEnabled(value: boolean) { 129 | this._imageSmoothingEnabled = value; 130 | this._ctx.imageSmoothingEnabled = value; 131 | } 132 | 133 | get imageSmoothingQuality(): any { 134 | return this._imageSmoothingQuality; 135 | } 136 | 137 | set imageSmoothingQuality(value: any) { 138 | this._imageSmoothingQuality = value; 139 | this._ctx.imageSmoothingQuality = value; 140 | } 141 | 142 | get lineCap(): any { 143 | return this._lineCap; 144 | } 145 | 146 | set lineCap(value: any) { 147 | this._lineCap = value; 148 | this._ctx.lineCap = value; 149 | } 150 | 151 | get lineJoin(): any { 152 | return this._lineJoin; 153 | } 154 | 155 | set lineJoin(value: any) { 156 | this._lineJoin = value; 157 | this._ctx.lineJoin = value; 158 | } 159 | 160 | get lineWidth(): number { 161 | return this._lineWidth; 162 | } 163 | 164 | set lineWidth(value: number) { 165 | this._lineWidth = value; 166 | this._ctx.lineWidth = value; 167 | } 168 | 169 | get miterLimit(): number { 170 | return this._miterLimit; 171 | } 172 | 173 | set miterLimit(value: number) { 174 | this._miterLimit = value; 175 | this._ctx.miterLimit = value; 176 | } 177 | 178 | get shadowBlur(): number { 179 | return this._shadowBlur; 180 | } 181 | 182 | set shadowBlur(value: number) { 183 | this._shadowBlur = value; 184 | this._ctx.shadowBlur = value; 185 | } 186 | 187 | get shadowColor(): string { 188 | return this._shadowColor; 189 | } 190 | 191 | set shadowColor(value: string) { 192 | this._shadowColor = value; 193 | this._ctx.shadowColor = value; 194 | } 195 | 196 | get shadowOffsetX(): number { 197 | return this._shadowOffsetX; 198 | } 199 | 200 | set shadowOffsetX(value: number) { 201 | this._shadowOffsetX = value; 202 | this._ctx.shadowOffsetX = value; 203 | } 204 | 205 | get shadowOffsetY(): number { 206 | return this._shadowOffsetY; 207 | } 208 | 209 | set shadowOffsetY(value: number) { 210 | this._shadowOffsetY = value; 211 | this._ctx.shadowOffsetY = value; 212 | } 213 | 214 | get strokeStyle(): string | CanvasGradient | CanvasPattern { 215 | return this._strokeStyle; 216 | } 217 | 218 | set strokeStyle(value: string | CanvasGradient | CanvasPattern) { 219 | this._strokeStyle = value; 220 | this._ctx.strokeStyle = value; 221 | } 222 | 223 | get textAlign(): any { 224 | return this._textAlign; 225 | } 226 | 227 | set textAlign(value: any) { 228 | this._textAlign = value; 229 | this._ctx.textAlign = value; 230 | } 231 | 232 | get textBaseline(): any { 233 | return this._textBaseline; 234 | } 235 | 236 | set textBaseline(value: any) { 237 | this._textBaseline = value; 238 | this._ctx.textBaseline = value; 239 | } 240 | 241 | get lineDashOffset(): number { 242 | return this._lineDashOffset; 243 | } 244 | 245 | set lineDashOffset(value: number) { 246 | this._lineDashOffset = value; 247 | this._ctx.lineDashOffset = value; 248 | } 249 | 250 | get fillStyle(): string | CanvasGradient | CanvasPattern { 251 | return this._fillStyle; 252 | } 253 | 254 | set fillStyle(value: string | CanvasGradient | CanvasPattern) { 255 | this._fillStyle = value; 256 | this._ctx.fillStyle = value; 257 | } 258 | 259 | arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void { 260 | // this.save(); 261 | // this.beginPath(); 262 | const args = Array.from(arguments); 263 | this._ctx.arc.apply(this._ctx, args); 264 | // this.closePath(); 265 | // this.restore(); 266 | } 267 | 268 | arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void { 269 | this._ctx.arcTo(x1, y1, x2, y2, radius); 270 | } 271 | 272 | beginPath(): void { 273 | this._ctx.beginPath(); 274 | } 275 | 276 | bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void { 277 | this._ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); 278 | } 279 | 280 | clearRect(x: number, y: number, w: number, h: number): void { 281 | // this._ctx.save(); 282 | this._ctx.clearRect(0, 0, w, h); 283 | // this._ctx.restore(); 284 | 285 | // const fillStyle = this.fillStyle; 286 | // this.fillStyle = '#FFFFFF'; 287 | // this._ctx.fillRect(x, y, w, h); 288 | // this.fillStyle = fillStyle; 289 | } 290 | 291 | clip(fillRule?: any | Path2D): void { 292 | const args = Array.from(arguments); 293 | return this._ctx.clip.apply(this._ctx, args); 294 | } 295 | 296 | closePath(): void { 297 | this._ctx.closePath(); 298 | } 299 | 300 | createImageData(sw: number | ImageData, sh?: number): ImageData { 301 | const args = Array.from(arguments); 302 | return this._ctx.createImageData.apply(this._ctx, args); 303 | } 304 | 305 | createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient { 306 | const args = Array.from(arguments); 307 | return this._ctx.createLinearGradient.apply(this._ctx, args); 308 | } 309 | 310 | createPattern(image: any, repetition: string): CanvasPattern | null { 311 | const args = Array.from(arguments); 312 | return this._ctx.createPattern.apply(this._ctx, args); 313 | } 314 | 315 | createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient { 316 | const args = Array.from(arguments); 317 | return this._ctx.createRadialGradient.apply(this._ctx, args); 318 | } 319 | 320 | drawFocusIfNeeded(element: any): void { 321 | const args = Array.from(arguments); 322 | return this._ctx.drawFocusIfNeeded.apply(this._ctx, args); 323 | } 324 | 325 | drawImage(image: any, dx: number, dy: number, dw?: number, dh?: number, dx2?: number, dy2?: number, dw2?: number, dh2?: number): void { 326 | const args = Array.from(arguments); 327 | if (image instanceof Image) { 328 | args[0] = image.imageImplementation; 329 | } 330 | 331 | this._ctx.drawImage.apply(this._ctx, args); 332 | } 333 | 334 | ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void { 335 | // this.save(); 336 | // this.beginPath(); 337 | this._ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise); 338 | // this.closePath(); 339 | // this.restore(); 340 | } 341 | 342 | fill(fillRule?: any): void { 343 | const args = Array.from(arguments); 344 | return this._ctx.fill.apply(this._ctx, args); 345 | } 346 | 347 | fillRect(x: number, y: number, w: number, h: number): void { 348 | this._ctx.fillRect(x, y, w, h); 349 | } 350 | 351 | fillText(text: string, x: number, y: number, maxWidth?: number): void { 352 | const args = Array.from(arguments); 353 | this._ctx.fillText.apply(this._ctx, args); 354 | } 355 | 356 | getImageData(sx: number, sy: number, sw: number, sh: number): ImageData { 357 | return this._ctx.getImageData(sx, sy, sw, sh); 358 | } 359 | 360 | getLineDash(): number[] { 361 | return this._ctx.getLineDash(); 362 | } 363 | 364 | getTransform(): any { 365 | return (this._ctx as any).getTransform(); 366 | } 367 | 368 | isPointInPath(x: any, y: number, fillRule?: any): boolean { 369 | const args = Array.from(arguments); 370 | return this._ctx.isPointInPath.apply(this._ctx, args); 371 | } 372 | 373 | isPointInStroke(x: number | Path2D, y: number): boolean { 374 | const args = Array.from(arguments); 375 | return this._ctx.isPointInStroke.apply(this._ctx, args); 376 | } 377 | 378 | lineTo(x: number, y: number): void { 379 | this._ctx.lineTo(x, y); 380 | } 381 | 382 | measureText(text: string): TextMetrics { 383 | return this._ctx.measureText(text); 384 | } 385 | 386 | moveTo(x: number, y: number): void { 387 | this._ctx.moveTo(x, y); 388 | } 389 | 390 | putImageData(imagedata: ImageData, dx: number, dy: number, dirtyX?: number, dirtyY?: number, dirtyWidth?: number, dirtyHeight?: number): void { 391 | const args = Array.from(arguments); 392 | this._ctx.putImageData.apply(this._ctx, args); 393 | } 394 | 395 | quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void { 396 | this._ctx.quadraticCurveTo(cpx, cpy, x, y); 397 | } 398 | 399 | rect(x: number, y: number, w: number, h: number): void { 400 | // this.save(); 401 | // this.beginPath(); 402 | this._ctx.rect(x, y, w, h); 403 | // this.closePath(); 404 | // this.restore(); 405 | } 406 | 407 | resetTransform(): void { 408 | (this._ctx as any).resetTransform(); 409 | } 410 | 411 | restore(): void { 412 | this._ctx.restore(); 413 | } 414 | 415 | rotate(angle: number): void { 416 | this._ctx.rotate(angle); 417 | } 418 | 419 | save(): void { 420 | this._ctx.save(); 421 | } 422 | 423 | scale(x: number, y: number): void { 424 | this._ctx.scale(x, y); 425 | } 426 | 427 | // scrollPathIntoView(): void; 428 | scrollPathIntoView(path?: Path2D): void { 429 | (this._ctx as any).scrollPathIntoView(path); 430 | } 431 | 432 | setLineDash(segments: number[]): void { 433 | this._ctx.setLineDash(segments); 434 | } 435 | 436 | setTransform(a?: number | any, b?: number, c?: number, d?: number, e?: number, f?: number): void { 437 | this._ctx.setTransform(a, b, c, d, e, f); 438 | } 439 | 440 | stroke(path?: Path2D): void { 441 | this._ctx.stroke(path); 442 | } 443 | 444 | strokeRect(x: number, y: number, w: number, h: number): void { 445 | this._ctx.strokeRect(x, y, w, h); 446 | } 447 | 448 | strokeText(text: string, x: number, y: number, maxWidth?: number): void { 449 | const args = Array.from(arguments); 450 | this._ctx.strokeText.apply(this._ctx, args); 451 | } 452 | 453 | transform(a: number, b: number, c: number, d: number, e: number, f: number): void { 454 | this._ctx.transform(a, b, c, d, e, f); 455 | } 456 | 457 | translate(x: number, y: number): void { 458 | this._ctx.translate(x, y); 459 | } 460 | 461 | } 462 | -------------------------------------------------------------------------------- /src/engine/sdl/color/rgba.ts: -------------------------------------------------------------------------------- 1 | const parseRgba = require('color-rgba'); 2 | 3 | export class Rgba { 4 | r: number; 5 | g: number; 6 | b: number; 7 | a: number; 8 | 9 | clone() { 10 | const color = new Rgba(); 11 | 12 | color.r = this.r; 13 | color.g = this.g; 14 | color.b = this.b; 15 | color.a = this.a; 16 | 17 | return color; 18 | } 19 | 20 | static createWhite(): Rgba { 21 | const color = new Rgba(); 22 | 23 | color.r = 255; 24 | color.g = 255; 25 | color.b = 255; 26 | color.a = 255; 27 | 28 | return color; 29 | } 30 | 31 | static createBlack(): Rgba { 32 | const color = new Rgba(); 33 | 34 | color.r = 0; 35 | color.g = 0; 36 | color.b = 0; 37 | color.a = 255; 38 | 39 | return color; 40 | } 41 | 42 | static parse(rgb: number | string): Rgba { 43 | const color = new Rgba(); 44 | 45 | if (typeof rgb === 'number') { 46 | /*tslint:disable*/ 47 | const color = new Rgba(); 48 | color.r = (rgb >> 16) & 0xFF; 49 | color.g = (rgb >> 8) & 0xFF; 50 | color.b = rgb & 0xFF; 51 | color.a = 255; 52 | /*tslint:enable*/ 53 | 54 | } else if (typeof rgb === 'string') { 55 | if (Rgba._HexRE.test(rgb)) { 56 | const hex = rgb.replace('#', '').trim(); 57 | const num = parseInt(hex, 16); 58 | /*tslint:disable*/ 59 | color.r = (num >> 16) & 0xFF; 60 | color.g = (num >> 8) & 0xFF; 61 | color.b = num & 0xFF; 62 | color.a = 255; 63 | /*tslint:enable*/ 64 | } else { 65 | const list = parseRgba(rgb) as number[]; 66 | 67 | color.r = list[0]; 68 | color.g = list[1]; 69 | color.b = list[2]; 70 | color.a = list[3] * 255; 71 | } 72 | } 73 | 74 | return color; 75 | } 76 | 77 | private static _HexRE = /[0-9A-Fa-f]+/; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /src/engine/sdl/event/key-event.ts: -------------------------------------------------------------------------------- 1 | import {SdlWindow} from '../sdl-window/sdl-window'; 2 | import {SDL_GetKeyName, SDL_GetScancodeName, SDL_Keymod} from '../sdl'; 3 | 4 | const keycode = require('keycode'); 5 | 6 | const keymod = SDL_Keymod; 7 | const KMOD_KEYS = Object.keys(keymod); 8 | 9 | const currentKeyEvent = {} as any; 10 | 11 | export function getCurrentKeyEvent(sdlEvent: any, window: SdlWindow): KeyboardEvent { 12 | currentKeyEvent.preventDefault = () => window.preventDefault(currentKeyEvent); 13 | currentKeyEvent.stopImmediatePropagation = () => window.stopImmediatePropagation(currentKeyEvent); 14 | currentKeyEvent.stopPropagation = () => window.stopPropagation(currentKeyEvent); 15 | 16 | const key = sdlEvent.key; 17 | 18 | currentKeyEvent.key = getKey(key); 19 | const normalizedKey = currentKeyEvent.key 20 | .toLowerCase() 21 | .trim() 22 | .replace('left ', '') 23 | .replace('right ', '') 24 | .trim(); 25 | 26 | if (normalizedKey.length > 0) { 27 | currentKeyEvent.which = currentKeyEvent.keyCode = currentKeyEvent.charCode = keycode(normalizedKey); 28 | } else { 29 | currentKeyEvent.which = currentKeyEvent.keyCode = currentKeyEvent.charCode = keycode(currentKeyEvent.key); 30 | } 31 | 32 | currentKeyEvent.code = getKeyCode(key); 33 | currentKeyEvent.repeat = !!key.repeat; 34 | 35 | currentKeyEvent.ctrlKey = false; 36 | currentKeyEvent.shiftKey = false; 37 | currentKeyEvent.altKey = false; 38 | currentKeyEvent.metaKey = false; 39 | 40 | KMOD_KEYS.forEach((modName) => { 41 | const keyModValue = keymod[modName]; 42 | const mod = key.keysym.mod; 43 | 44 | /*tslint:disable*/ 45 | const val = !!(keyModValue & mod); 46 | /*tslint:enable*/ 47 | 48 | switch (modName) { 49 | case 'KMOD_LCTRL': 50 | case 'KMOD_RCTRL': 51 | if (!currentKeyEvent.ctrlKey) { 52 | currentKeyEvent.ctrlKey = val; 53 | } 54 | break; 55 | 56 | case 'KMOD_LSHIFT': 57 | case 'KMOD_RSHIFT': 58 | if (!currentKeyEvent.shiftKey) { 59 | currentKeyEvent.shiftKey = val; 60 | } 61 | 62 | break; 63 | 64 | case 'KMOD_RALT': 65 | case 'KMOD_LALT': 66 | if (!currentKeyEvent.altKey) { 67 | currentKeyEvent.altKey = val; 68 | } 69 | break; 70 | 71 | case 'KMOD_LGUI': 72 | case 'KMOD_RGUI': 73 | if (!currentKeyEvent.metaKey) { 74 | currentKeyEvent.metaKey = val; 75 | } 76 | break; 77 | } 78 | }); 79 | 80 | return currentKeyEvent; 81 | } 82 | 83 | function getKeyCode(key: any) { 84 | const codeName = SDL_GetScancodeName(key.keysym.scancode); 85 | 86 | if (codeName.length === 1 && codeName.match(/[A-Z]/i)) { 87 | return `Key${codeName}`; 88 | } else if (codeName.length === 1 && codeName.match(/[0-9]/i)) { 89 | return `Digit${codeName}`; 90 | } else { 91 | return codeName; 92 | } 93 | } 94 | 95 | function getKey(key: any) { 96 | const keyName = SDL_GetKeyName(key.keysym.sym); 97 | 98 | if (keyName.length === 1 && keyName.match(/[A-Z]/i)) { 99 | return keyName.toLowerCase(); 100 | } 101 | 102 | switch (keyName) { 103 | case 'Space': 104 | return ' '; 105 | default: 106 | return keyName; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/engine/sdl/event/mouse-event.ts: -------------------------------------------------------------------------------- 1 | import {SdlWindow} from '../sdl-window/sdl-window'; 2 | import {SDL_GetGlobalMouseState} from '../sdl/sdl-mouse'; 3 | 4 | const currentMouseEvent = {} as any; 5 | 6 | export function getCurrentMouseEvent(sdlEvent: any, window: SdlWindow): MouseEvent { 7 | currentMouseEvent.preventDefault = () => window.preventDefault(currentMouseEvent); 8 | currentMouseEvent.stopImmediatePropagation = () => window.stopImmediatePropagation(currentMouseEvent); 9 | currentMouseEvent.stopPropagation = () => window.stopPropagation(currentMouseEvent); 10 | 11 | 12 | const mouseButtonEvt = sdlEvent.button; 13 | 14 | const screen = SDL_GetGlobalMouseState(); 15 | // const button = sdlEvent.button.button; 16 | 17 | currentMouseEvent.screenX = screen.x; 18 | currentMouseEvent.screenY = screen.y; 19 | 20 | currentMouseEvent.offsetX = sdlEvent.motion.x - window.canvasX; 21 | currentMouseEvent.offsetY = sdlEvent.motion.y - window.canvasX; 22 | 23 | currentMouseEvent.clientX = sdlEvent.motion.x; // X coordinate, relative to window 24 | currentMouseEvent.clientY = sdlEvent.motion.y; // Y coordinate, relative to window 25 | currentMouseEvent.pageX = sdlEvent.motion.x; 26 | currentMouseEvent.pageY = sdlEvent.motion.y; 27 | currentMouseEvent.relatedTarget = window.getCanvas(); 28 | 29 | 30 | currentMouseEvent.ctrlKey = false; 31 | currentMouseEvent.shiftKey = false; 32 | currentMouseEvent.altKey = false; 33 | currentMouseEvent.metaKey = false; 34 | 35 | const key = sdlEvent.key; 36 | currentMouseEvent.which = currentMouseEvent.button = (mouseButtonEvt.button); 37 | 38 | return currentMouseEvent; 39 | } 40 | -------------------------------------------------------------------------------- /src/engine/sdl/image/image.ts: -------------------------------------------------------------------------------- 1 | const NodeCanvasImage = require('canvas').Image; 2 | 3 | export class Image { 4 | private image: any; 5 | 6 | constructor() { 7 | this.image = new NodeCanvasImage(); 8 | } 9 | 10 | get width(): number { 11 | return this.image.width; 12 | } 13 | 14 | get height(): number { 15 | return this.image.height; 16 | } 17 | 18 | get imageImplementation(): any { 19 | return this.image; 20 | } 21 | 22 | get onload(): () => void { 23 | return this.image.onload; 24 | } 25 | 26 | set onload(onload: () => void) { 27 | this.image.onload = onload; 28 | } 29 | 30 | get src() { 31 | return this.image.src as string; 32 | } 33 | 34 | set src(src: string) { 35 | this.image.src = src; 36 | } 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/engine/sdl/index.ts: -------------------------------------------------------------------------------- 1 | import {WindowOptions} from '../../window/window-options'; 2 | import {NativeWindow} from '../../window/native-window'; 3 | import {SdlWindow} from './sdl-window/sdl-window'; 4 | import {applicationContext} from './app/application-context'; 5 | import {SdlCanvas} from './canvas/sdl-canvas'; 6 | 7 | export function createWindow(options: WindowOptions): NativeWindow { 8 | const opts = options || SdlWindow.windowDefaults(); 9 | const sdlWindow = new SdlWindow(opts); 10 | // @ts-ignore 11 | sdlWindow.canvas = new SdlCanvas(sdlWindow); 12 | // @ts-ignore 13 | return sdlWindow; 14 | } 15 | 16 | export function alert(message?: string) { 17 | SdlWindow.alert(message); 18 | 19 | } 20 | 21 | export function confirm(message?: string): boolean { 22 | return SdlWindow.confirm(message); 23 | } 24 | 25 | export function requestAnimationFrame(callback: FrameRequestCallback): number { 26 | return applicationContext.requestAnimationFrame(callback); 27 | } 28 | 29 | export function cancelAnimationFrame(request: number): void { 30 | applicationContext.cancelAnimationFrame(request); 31 | } 32 | -------------------------------------------------------------------------------- /src/engine/sdl/performance/sdl-performance.ts: -------------------------------------------------------------------------------- 1 | import {SdlWindow} from '../sdl-window/sdl-window'; 2 | 3 | export class SdlPerformance implements Performance { 4 | readonly navigation: PerformanceNavigation; 5 | onresourcetimingbufferfull: ((this: Performance, ev: Event) => any) | null; 6 | readonly timeOrigin: number; 7 | readonly timing: PerformanceTiming; 8 | 9 | constructor(private window: SdlWindow) { 10 | } 11 | 12 | addEventListener(type: any, listener: any, options?: boolean | AddEventListenerOptions): void { 13 | } 14 | 15 | clearMarks(markName?: string): void { 16 | } 17 | 18 | clearMeasures(measureName?: string): void { 19 | } 20 | 21 | clearResourceTimings(): void { 22 | } 23 | 24 | dispatchEvent(event: Event): boolean { 25 | return false; 26 | } 27 | 28 | getEntries(): PerformanceEntryList { 29 | return undefined; 30 | } 31 | 32 | getEntriesByName(name: string, type?: string): PerformanceEntryList { 33 | return undefined; 34 | } 35 | 36 | getEntriesByType(type: string): PerformanceEntryList { 37 | return undefined; 38 | } 39 | 40 | mark(markName: string): void { 41 | } 42 | 43 | measure(measureName: string, startMark?: string, endMark?: string): void { 44 | } 45 | 46 | now(): number { 47 | return new Date().getTime(); 48 | } 49 | 50 | removeEventListener(type: any, listener: any, options?: boolean | EventListenerOptions): void { 51 | } 52 | 53 | setResourceTimingBufferSize(maxSize: number): void { 54 | } 55 | 56 | toJSON(): any { 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl-context/index.ts: -------------------------------------------------------------------------------- 1 | import {SdlRenderer} from './sdl-renderer'; 2 | import {SdlContext2d} from './sdl-context-2d'; 3 | import {SDL_GetWindowSurface} from '../sdl'; 4 | 5 | export function createSdlContext2D(windowPtr: any) { 6 | const renderer = SdlRenderer.createRenderer(windowPtr, -1); 7 | 8 | return new SdlContext2d(renderer); 9 | } 10 | 11 | export function createSoftwareSdlContext2D(windowPtr: any) { 12 | const surfacePtr = SDL_GetWindowSurface(windowPtr); 13 | const renderer = SdlRenderer.createSoftwareRenderer(windowPtr, surfacePtr); 14 | 15 | return new SdlContext2d(renderer); 16 | } 17 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl-context/sdl-context-2d.ts: -------------------------------------------------------------------------------- 1 | import {Rgba} from '../color/rgba'; 2 | import {SdlRenderer} from './sdl-renderer'; 3 | import {SdlTexture} from './sdl-texture'; 4 | import { 5 | SDL_RenderCopy, 6 | SDL_TEXTUREACCESS_STATIC, 7 | SDL_TEXTUREACCESS_STREAMING, 8 | SDL_TEXTUREACCESS_TARGET, SDL_UpdateTexture 9 | } from '../sdl'; 10 | import {Rect} from '../shape/rect'; 11 | 12 | export class SdlContext2d { 13 | private color: Rgba; 14 | private textureFormat: number; 15 | width: number; 16 | height: number; 17 | x: number; 18 | y: number; 19 | srcRect: Rect; 20 | destRect: Rect; 21 | texture: SdlTexture; 22 | 23 | constructor(private renderer: SdlRenderer) { 24 | this.x = 0; 25 | this.y = 0; 26 | this.textureFormat = SdlTexture.getARGBFormat(); 27 | this.color = Rgba.createWhite(); 28 | this.texture = null; 29 | this.srcRect = {x: 0, y: 0, w: 0, h: 0}; 30 | this.destRect = {x: 0, y: 0, w: 0, h: 0}; 31 | } 32 | 33 | renderFrame(pixels: Buffer, pixelWidth: number, pixelHeight: number): void { 34 | if (this.texture) { 35 | this.setRgba(this.color); 36 | this.clear(); 37 | 38 | // 39 | // pixels are in the ARGB32 format 40 | // 41 | this.texture.update(0, 0, pixelWidth, pixelHeight, pixels); 42 | 43 | pixelWidth = this.width < pixelWidth ? this.width : pixelWidth; 44 | pixelHeight = (this.height < pixelHeight) ? this.height : pixelHeight; 45 | 46 | this.srcRect.x = 0; 47 | this.srcRect.y = 0; 48 | this.srcRect.w = pixelWidth; 49 | this.srcRect.h = pixelHeight; 50 | 51 | this.destRect.x = this.x; 52 | this.destRect.y = this.y; 53 | this.destRect.w = pixelWidth; 54 | this.destRect.h = pixelHeight; 55 | 56 | this.renderer.copy(this.texture, this.srcRect, this.destRect); 57 | this.update(); 58 | } 59 | } 60 | 61 | destroy() { 62 | this.renderer.destroy(); 63 | this.renderer = null; 64 | } 65 | 66 | private clear() { 67 | this.renderer.clear(); 68 | } 69 | 70 | update() { 71 | this.renderer.present(); 72 | } 73 | 74 | setSize(w: number, h: number) { 75 | if (this.texture) { 76 | this.texture.destroy(); 77 | this.texture = null; 78 | } 79 | 80 | this.renderer.size = {w, h}; 81 | this.width = w; 82 | this.height = h; 83 | this.texture = this.createDynamicTexture(this.textureFormat); 84 | } 85 | 86 | getSize(): { w: number, h: number } { 87 | return this.renderer.size; 88 | } 89 | 90 | private setRgba(rgba: Rgba): void { 91 | /*tslint:disable*/ 92 | this.color = rgba; 93 | this.renderer.color = rgba; 94 | /*tslint:enable*/ 95 | } 96 | 97 | private createDynamicTexture(format: number): SdlTexture { 98 | // const size = this.getSize(); 99 | return this.renderer.createTexture(this.width, this.height, SDL_TEXTUREACCESS_STREAMING, format); 100 | } 101 | 102 | private createStaticTexture(format: number): SdlTexture { 103 | // const size = this.getSize(); 104 | return this.renderer.createTexture(this.width, this.height, SDL_TEXTUREACCESS_STATIC, format); 105 | } 106 | 107 | private createRendererTexture(): SdlTexture { 108 | // const size = this.getSize(); 109 | return this.renderer.createTexture(this.width, this.height, SDL_TEXTUREACCESS_TARGET); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl-context/sdl-renderer.ts: -------------------------------------------------------------------------------- 1 | import {SdlTexture} from './sdl-texture'; 2 | import {Rgba} from '../color/rgba'; 3 | import { 4 | SDL_CreateRenderer, 5 | SDL_CreateSoftwareRenderer, 6 | SDL_DestroyRenderer, 7 | SDL_GetRenderTarget, 8 | SDL_RenderClear, 9 | SDL_RenderCopy, 10 | SDL_RendererFlags, 11 | SDL_RenderGetLogicalSize, 12 | SDL_RenderPresent, 13 | SDL_RenderSetLogicalSize, 14 | SDL_SetRenderDrawColor, 15 | SDL_SetRenderTarget 16 | } from '../sdl'; 17 | import {Rect} from '../shape/rect'; 18 | 19 | export class SdlRenderer { 20 | private _color: Rgba; 21 | private _size: { w: number, h: number }; 22 | 23 | constructor(private _rendererPtr: any) { 24 | this._color = Rgba.createWhite(); 25 | this._size = SDL_RenderGetLogicalSize(this._rendererPtr); 26 | } 27 | 28 | destroy(): void { 29 | SDL_DestroyRenderer(this._rendererPtr); 30 | } 31 | 32 | clear(): void { 33 | SDL_RenderClear(this._rendererPtr); 34 | } 35 | 36 | copy(tt: SdlTexture, src: Rect, dest: Rect): void { 37 | SDL_RenderCopy(this._rendererPtr, tt._texturePtr, src, dest); 38 | } 39 | 40 | present() { 41 | SDL_RenderPresent(this._rendererPtr); 42 | } 43 | 44 | createTexture(w: number, h: number, access = 2, format?: number) { 45 | return SdlTexture.createTexture(this.rendererPtr, w, h, access, format); 46 | } 47 | 48 | get color(): Rgba { 49 | // SDL_GetRenderDrawColor(this._rendererPtr, this._color); 50 | return this._color; 51 | } 52 | 53 | set color(rgba: Rgba) { 54 | this._color = rgba; 55 | SDL_SetRenderDrawColor(this._rendererPtr, rgba.r, rgba.g, rgba.b, rgba.a); 56 | } 57 | 58 | set size(size: { w: number, h: number }) { 59 | this._size = size; 60 | SDL_RenderSetLogicalSize(this._rendererPtr, size.w, size.h); 61 | } 62 | 63 | get size(): { w: number, h: number } { 64 | return this._size; 65 | } 66 | 67 | get target(): SdlTexture { 68 | const texturePtr = SDL_GetRenderTarget(this._rendererPtr); 69 | return new SdlTexture(texturePtr); 70 | } 71 | 72 | set target(texture: SdlTexture) { 73 | if (texture === null) { 74 | SDL_SetRenderTarget(this._rendererPtr, null); 75 | } else { 76 | SDL_SetRenderTarget(this._rendererPtr, texture._texturePtr); 77 | } 78 | } 79 | 80 | get rendererPtr(): any { 81 | return this._rendererPtr; 82 | } 83 | 84 | static createRenderer(windowPtr: any, driver: number): SdlRenderer { 85 | /*tslint:disable*/ 86 | const renderPtr = SDL_CreateRenderer(windowPtr, driver, SDL_RendererFlags.SDL_RENDERER_ACCELERATED | SDL_RendererFlags.SDL_RENDERER_PRESENTVSYNC); 87 | /*tslint:enable*/ 88 | return new SdlRenderer(renderPtr); 89 | } 90 | 91 | static createSoftwareRenderer(windowPtr: any, surfacePtr: any): SdlRenderer { 92 | const renderPtr = SDL_CreateSoftwareRenderer(surfacePtr); 93 | return new SdlRenderer(renderPtr); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl-context/sdl-texture.ts: -------------------------------------------------------------------------------- 1 | import { 2 | SDL_BlendMode, SDL_CreateRGBSurfaceFrom, 3 | SDL_CreateTexture, SDL_CreateTextureFromSurface, 4 | SDL_DestroyTexture, SDL_FreeSurface, 5 | SDL_MasksToPixelFormatEnum, 6 | SDL_QueryTexture, SDL_SetTextureBlendMode, 7 | SDL_UpdateTexture 8 | } from '../sdl'; 9 | import {Rect} from '../shape/rect'; 10 | 11 | export class SdlTexture { 12 | rect: Rect; 13 | 14 | constructor(public _texturePtr: any) { 15 | SDL_SetTextureBlendMode(this._texturePtr, SDL_BlendMode.SDL_BLENDMODE_BLEND); 16 | this.rect = {x: 0, y: 0, w: 0, h: 0}; 17 | } 18 | 19 | destroy() { 20 | SDL_DestroyTexture(this._texturePtr); 21 | } 22 | 23 | 24 | update(x: number, y: number, width: number, height: number, pixels: Buffer): any { 25 | const depth = 4; 26 | const pitch = depth * width; 27 | 28 | this.rect.x = x; 29 | this.rect.y = y; 30 | this.rect.w = width; 31 | this.rect.h = height; 32 | 33 | SDL_UpdateTexture(this._texturePtr, this.rect, pixels, pitch); 34 | } 35 | 36 | query() { 37 | return SDL_QueryTexture(this._texturePtr); 38 | } 39 | 40 | get texturePtr(): any { 41 | return this._texturePtr; 42 | } 43 | 44 | static createTexture(rendererPtr: any, w: number, h: number, access = 2, format?: number): SdlTexture { 45 | format = format !== undefined ? format : null; 46 | const texturePtr = SDL_CreateTexture(rendererPtr, format, access, w, h); 47 | 48 | return new SdlTexture(texturePtr); 49 | } 50 | 51 | static createARGBSurface(pixels: any, width: number, height: number): any { 52 | const rmask = 0x00FF0000; 53 | const gmask = 0x0000FF00; 54 | const bmask = 0x000000FF; 55 | const amask = 0xFF000000; 56 | const depth = 32; 57 | const pitch = 4 * width; 58 | 59 | const surfacePtr = SDL_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, rmask, gmask, bmask, amask); 60 | return surfacePtr; 61 | } 62 | 63 | static createARGBTexture(pixels: any, width: number, height: number, rendererPtr: any): any { 64 | const rmask = 0x00FF0000; 65 | const gmask = 0x0000FF00; 66 | const bmask = 0x000000FF; 67 | const amask = 0xFF000000; 68 | const depth = 32; 69 | const pitch = 4 * width; 70 | 71 | const surfacePtr = SDL_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, rmask, gmask, bmask, amask); 72 | 73 | const texturePtr = SDL_CreateTextureFromSurface(rendererPtr, surfacePtr); 74 | 75 | SDL_FreeSurface(surfacePtr); 76 | 77 | return new SdlTexture(texturePtr); 78 | } 79 | 80 | static getARGBFormat(): number { 81 | const bpp = 32; 82 | const rmask = 0x00FF0000; 83 | const gmask = 0x0000FF00; 84 | const bmask = 0x000000FF; 85 | const amask = 0xFF000000; 86 | /* 87 | SDL_PIXELFORMAT_ARGB8888 88 | (Rmask == 0x00FF0000 && Gmask == 0x0000FF00 && Bmask == 0x000000FF && Amask == 0xFF000000) 89 | */ 90 | const format = SDL_MasksToPixelFormatEnum(bpp, rmask, gmask, bmask, amask); 91 | 92 | return format; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl-window/index.ts: -------------------------------------------------------------------------------- 1 | import {SdlWindow} from './sdl-window'; 2 | 3 | function createSdlWindow(options: any) { 4 | return new SdlWindow(options); 5 | } 6 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl-window/messagebox.ts: -------------------------------------------------------------------------------- 1 | import {SDL_Create_MessageBoxButtonData, SDL_ShowMessageBox} from '../sdl'; 2 | 3 | export function confirm(message: string, windowPtr: any = null): boolean { 4 | 5 | const buttons = [ 6 | { 7 | type: 'cancel', 8 | text: 'Cancel' 9 | } 10 | , { 11 | type: 'yes', 12 | text: 'OK' 13 | }]; 14 | 15 | const numberOfButtons = buttons.length; 16 | const buttonData = SDL_Create_MessageBoxButtonData(buttons); 17 | 18 | const buttonIndex = SDL_ShowMessageBox('info', '', message, buttonData, numberOfButtons, windowPtr); 19 | 20 | return buttonIndex === 1; 21 | } 22 | 23 | export function alert(message: string, windowPtr: any = null) { 24 | const buttons = [{ 25 | type: 'yes', 26 | text: 'OK' 27 | }]; 28 | 29 | const numberOfButtons = buttons.length; 30 | const buttonData = SDL_Create_MessageBoxButtonData(buttons); 31 | 32 | SDL_ShowMessageBox('info', '', message, buttonData, numberOfButtons, windowPtr); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl-window/sdl-navigator.ts: -------------------------------------------------------------------------------- 1 | import {SdlWindow} from './sdl-window'; 2 | 3 | export class SdlNavigator implements Navigator { 4 | private readonly _activeVRDisplays: ReadonlyArray; 5 | private readonly _appCodeName: string; 6 | private readonly _appName: string; 7 | private readonly _appVersion: string; 8 | private readonly _authentication: WebAuthentication; 9 | private readonly _cookieEnabled: boolean; 10 | private readonly _doNotTrack: string | null; 11 | private readonly _geolocation: Geolocation; 12 | private readonly _hardwareConcurrency: number; 13 | private readonly _language: string; 14 | private readonly _languages: ReadonlyArray; 15 | private readonly _maxTouchPoints: number; 16 | private readonly _mediaDevices: MediaDevices; 17 | private readonly _mimeTypes: MimeTypeArray; 18 | private readonly _msManipulationViewsEnabled: boolean; 19 | private readonly _msMaxTouchPoints: number; 20 | private readonly _msPointerEnabled: boolean; 21 | private readonly _onLine: boolean; 22 | private readonly _platform: string; 23 | private readonly _plugins: PluginArray; 24 | private readonly _pointerEnabled: boolean; 25 | private readonly _product: string; 26 | private readonly _productSub: string; 27 | private readonly _serviceWorker: ServiceWorkerContainer; 28 | private readonly _storage: StorageManager; 29 | private readonly _userAgent: string; 30 | private readonly _vendor: string; 31 | private readonly _vendorSub: string; 32 | private readonly _webdriver: boolean; 33 | 34 | constructor(private window: SdlWindow) { 35 | } 36 | 37 | clipboard: Clipboard; 38 | credentials: CredentialsContainer; 39 | permissions: Permissions; 40 | share(data?: ShareData): Promise { 41 | throw new Error('Method not implemented.'); 42 | } 43 | registerProtocolHandler(scheme: string, url: string, title: string): void { 44 | throw new Error('Method not implemented.'); 45 | } 46 | unregisterProtocolHandler(scheme: string, url: string): void { 47 | throw new Error('Method not implemented.'); 48 | } 49 | 50 | confirmSiteSpecificTrackingException(args: ConfirmSiteSpecificExceptionsInformation): boolean { 51 | return false; 52 | } 53 | 54 | confirmWebWideTrackingException(args: ExceptionInformation): boolean { 55 | return false; 56 | } 57 | 58 | getDisplayMedia(constraints: MediaStreamConstraints): Promise { 59 | return undefined; 60 | } 61 | 62 | getGamepads(): (Gamepad | null)[] { 63 | return []; 64 | } 65 | 66 | getUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void { 67 | } 68 | 69 | getVRDisplays(): Promise { 70 | return undefined; 71 | } 72 | 73 | javaEnabled(): boolean { 74 | return false; 75 | } 76 | 77 | msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void { 78 | } 79 | 80 | msSaveBlob(blob: any, defaultName?: string): boolean { 81 | return false; 82 | } 83 | 84 | msSaveOrOpenBlob(blob: any, defaultName?: string): boolean { 85 | return false; 86 | } 87 | 88 | removeSiteSpecificTrackingException(args: ExceptionInformation): void { 89 | } 90 | 91 | removeWebWideTrackingException(args: ExceptionInformation): void { 92 | } 93 | 94 | requestMediaKeySystemAccess(keySystem: string, supportedConfigurations: MediaKeySystemConfiguration[]): Promise { 95 | return undefined; 96 | } 97 | 98 | sendBeacon(url: string, data?: Blob | Int8Array | Int16Array | Int32Array | Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array | DataView | ArrayBuffer | FormData | string | null): boolean { 99 | return false; 100 | } 101 | 102 | storeSiteSpecificTrackingException(args: StoreSiteSpecificExceptionsInformation): void { 103 | } 104 | 105 | storeWebWideTrackingException(args: StoreExceptionsInformation): void { 106 | } 107 | 108 | vibrate(pattern: number | number[]): boolean { 109 | return false; 110 | } 111 | 112 | get activeVRDisplays(): ReadonlyArray { 113 | return this._activeVRDisplays; 114 | } 115 | 116 | get appCodeName(): string { 117 | return this._appCodeName; 118 | } 119 | 120 | get appName(): string { 121 | return this._appName; 122 | } 123 | 124 | get appVersion(): string { 125 | return this._appVersion; 126 | } 127 | 128 | get authentication(): WebAuthentication { 129 | return this._authentication; 130 | } 131 | 132 | get cookieEnabled(): boolean { 133 | return false; 134 | } 135 | 136 | get doNotTrack(): string | null { 137 | return this._doNotTrack; 138 | } 139 | 140 | get geolocation(): Geolocation { 141 | return this._geolocation; 142 | } 143 | 144 | get hardwareConcurrency(): number { 145 | return this._hardwareConcurrency; 146 | } 147 | 148 | get language(): string { 149 | return this._language; 150 | } 151 | 152 | get languages(): ReadonlyArray { 153 | return this._languages; 154 | } 155 | 156 | get maxTouchPoints(): number { 157 | return this._maxTouchPoints; 158 | } 159 | 160 | get mediaDevices(): MediaDevices { 161 | return this._mediaDevices; 162 | } 163 | 164 | get mimeTypes(): MimeTypeArray { 165 | return this._mimeTypes; 166 | } 167 | 168 | get msManipulationViewsEnabled(): boolean { 169 | return this._msManipulationViewsEnabled; 170 | } 171 | 172 | get msMaxTouchPoints(): number { 173 | return this._msMaxTouchPoints; 174 | } 175 | 176 | get msPointerEnabled(): boolean { 177 | return this._msPointerEnabled; 178 | } 179 | 180 | get onLine(): boolean { 181 | return true; 182 | } 183 | 184 | get platform(): string { 185 | return 'MacIntel'; 186 | } 187 | 188 | get plugins(): PluginArray { 189 | return this._plugins; 190 | } 191 | 192 | get pointerEnabled(): boolean { 193 | return this._pointerEnabled; 194 | } 195 | 196 | get product(): string { 197 | return this._product; 198 | } 199 | 200 | get productSub(): string { 201 | return this._productSub; 202 | } 203 | 204 | get serviceWorker(): ServiceWorkerContainer { 205 | return this._serviceWorker; 206 | } 207 | 208 | get storage(): StorageManager { 209 | return this._storage; 210 | } 211 | 212 | get userAgent(): string { 213 | return 'User-agent header: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'; 214 | } 215 | 216 | get vendor(): string { 217 | return this._vendor; 218 | } 219 | 220 | get vendorSub(): string { 221 | return this._vendorSub; 222 | } 223 | 224 | get webdriver(): boolean { 225 | return this._webdriver; 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl-window/sdl-window-opts.ts: -------------------------------------------------------------------------------- 1 | import {WindowOptions} from '../../../window/window-options'; 2 | import {SDL_WindowFlags} from '../sdl'; 3 | 4 | 5 | export function sdlWindowDefaults(): WindowOptions { 6 | const opts = {} as any; 7 | 8 | opts.title = ''; 9 | opts.width = 640; 10 | opts.height = 480; 11 | 12 | opts.x = 0x2FFF0000; 13 | opts.y = 0x2FFF0000; 14 | opts.closable = true; 15 | opts.fullscreen = false; 16 | opts.show = true; 17 | opts.resizable = true; 18 | opts.borderless = false; 19 | opts.minimized = false; 20 | opts.allowHighDPI = false; 21 | opts.grabInputFocus = false; 22 | opts.fitCanvasInWindow = true; 23 | opts.scaleCanvasToWindowSize = false; 24 | 25 | return opts; 26 | } 27 | 28 | export function getSdlWindowOptions(options: WindowOptions): { title: string, x: number, y: number, w: number, h: number, flags: number } { 29 | if (options === null || options === undefined) { 30 | options = {} as any; 31 | } 32 | 33 | const defaults = sdlWindowDefaults(); 34 | const opts: WindowOptions = ({...defaults, ...options} as any); 35 | 36 | /*tslint:disable*/ 37 | let flags = 0; 38 | 39 | flags |= SDL_WindowFlags.SDL_WINDOW_OPENGL; 40 | flags |= opts.fullscreen ? SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP : 0; 41 | flags |= opts.show ? SDL_WindowFlags.SDL_WINDOW_SHOWN : SDL_WindowFlags.SDL_WINDOW_HIDDEN; 42 | flags |= opts.resizable ? SDL_WindowFlags.SDL_WINDOW_RESIZABLE : 0; 43 | flags |= opts.borderless ? SDL_WindowFlags.SDL_WINDOW_BORDERLESS : 0; 44 | flags |= opts.minimized ? SDL_WindowFlags.SDL_WINDOW_MINIMIZED : 0; 45 | flags |= opts.maximized ? SDL_WindowFlags.SDL_WINDOW_MAXIMIZED : 0; 46 | flags |= opts.allowHighDPI ? SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI : 0; 47 | // flags |= opts.mouseCapture ? SDL_WindowFlags.SDL_WINDOW_MOUSE_CAPTURE : 0; 48 | flags |= opts.grabInputFocus ? SDL_WindowFlags.SDL_WINDOW_INPUT_GRABBED : 0; 49 | /*tslint:enable*/ 50 | 51 | const title = opts.title; 52 | const x = opts.x; 53 | const y = opts.y; 54 | 55 | const w = opts.width; 56 | const h = opts.height; 57 | 58 | return {x, y, w, h, flags, title}; 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sdl'; 2 | export * from './sdl-events'; 3 | export * from './sdl-events'; 4 | export * from './sdl-gesture'; 5 | export * from './sdl-joystick'; 6 | export * from './sdl-keyboard'; 7 | export * from './sdl-messagebox'; 8 | export * from './sdl-pixels'; 9 | export * from './sdl-power'; 10 | export * from './sdl-rect'; 11 | export * from './sdl-render'; 12 | export * from './sdl-rwops'; 13 | export * from './sdl-surface'; 14 | export * from './sdl-touch'; 15 | export * from './sdl-video'; 16 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/lib-loader.ts: -------------------------------------------------------------------------------- 1 | const ffi = require('ffi-napi'); 2 | 3 | const SDL_LIBS_PATH = __dirname; 4 | 5 | export function loadLibrary(module: any, moduleExports: any) { 6 | const moduleLibrary = getLibraryPath(); 7 | ffi.Library(moduleLibrary, module, moduleExports); 8 | } 9 | 10 | function getLibraryPath(): string { 11 | switch (process.platform) { 12 | case 'darwin': 13 | return getOSXLibraryPath(); 14 | case 'win32': 15 | return getWindowsLibraryPath(); 16 | case 'linux': 17 | return getLinuxLibraryPath(); 18 | default: 19 | throw new ReferenceError(`Unsupported pattform: ${process.platform}`); 20 | } 21 | } 22 | 23 | function getWindowsLibraryPath(): string { 24 | const dir = SDL_LIBS_PATH; 25 | const arch = process.arch; 26 | const libName = 'SDL2'; 27 | 28 | return `${dir}/libs/windows/${arch}/${libName}.dll`; 29 | } 30 | 31 | function getOSXLibraryPath(): string { 32 | const dir = SDL_LIBS_PATH; 33 | const arch = process.arch; 34 | const libName = 'libSDL2'; 35 | const version = '2.0'; 36 | 37 | return `${dir}/libs/osx/${arch}/${libName}-${version}.dylib`; 38 | } 39 | 40 | function getLinuxLibraryPath(): string { 41 | const dir = SDL_LIBS_PATH; 42 | const arch = process.arch; 43 | const libName = 'libSDL2'; 44 | 45 | return `${dir}/libs/linux/${arch}/${libName}.so`; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/libs/linux/arm/libSDL2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/src/engine/sdl/sdl/libs/linux/arm/libSDL2.so -------------------------------------------------------------------------------- /src/engine/sdl/sdl/libs/linux/x64/libSDL2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/src/engine/sdl/sdl/libs/linux/x64/libSDL2.so -------------------------------------------------------------------------------- /src/engine/sdl/sdl/libs/osx/arm64/libSDL2-2.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/src/engine/sdl/sdl/libs/osx/arm64/libSDL2-2.0.dylib -------------------------------------------------------------------------------- /src/engine/sdl/sdl/libs/osx/x64/libSDL2-2.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/src/engine/sdl/sdl/libs/osx/x64/libSDL2-2.0.dylib -------------------------------------------------------------------------------- /src/engine/sdl/sdl/libs/windows/ia32/SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/src/engine/sdl/sdl/libs/windows/ia32/SDL2.dll -------------------------------------------------------------------------------- /src/engine/sdl/sdl/libs/windows/x64/SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcchatman8009/native-canvas/6eae43a79acc56d5109506b403851ed803566b6f/src/engine/sdl/sdl/libs/windows/x64/SDL2.dll -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-events.ts: -------------------------------------------------------------------------------- 1 | import {loadLibrary} from './lib-loader'; 2 | import { 3 | char, 4 | float, 5 | int32, 6 | Sint16, 7 | Sint32, 8 | string, 9 | Uint16, 10 | uint32, 11 | Uint32, 12 | Uint8, 13 | voit, 14 | voit_ptr, 15 | voit_ptr_ptr 16 | } from './types'; 17 | import {SDL_GestureID} from './sdl-gesture'; 18 | import {SDL_FingerID, SDL_TouchID} from './sdl-touch'; 19 | import {SDL_JoystickID} from './sdl-joystick'; 20 | import {SDL_Keysym} from './sdl-keyboard'; 21 | 22 | const FFI = require('ffi-napi'); 23 | const ref = require('ref-napi'); 24 | const ArrayType = require('ref-array-di')(ref); 25 | const Struct = require('ref-struct-di')(ref); 26 | const Union = require('ref-union-di')(ref); 27 | 28 | const SDL = {} as any; 29 | 30 | export enum SDL_EventType { 31 | SDL_FIRSTEVENT = 0, 32 | SDL_QUIT = 256, 33 | SDL_APP_TERMINATING = 257, 34 | SDL_APP_LOWMEMORY = 258, 35 | SDL_APP_WILLENTERBACKGROUND = 259, 36 | SDL_APP_DIDENTERBACKGROUND = 260, 37 | SDL_APP_WILLENTERFOREGROUND = 261, 38 | SDL_APP_DIDENTERFOREGROUND = 262, 39 | SDL_WINDOWEVENT = 512, 40 | SDL_SYSWMEVENT = 513, 41 | SDL_KEYDOWN = 768, 42 | SDL_KEYUP = 769, 43 | SDL_TEXTEDITING = 770, 44 | SDL_TEXTINPUT = 771, 45 | SDL_KEYMAPCHANGED = 772, 46 | SDL_MOUSEMOTION = 1024, 47 | SDL_MOUSEBUTTONDOWN = 1025, 48 | SDL_MOUSEBUTTONUP = 1026, 49 | SDL_MOUSEWHEEL = 1027, 50 | SDL_JOYAXISMOTION = 1536, 51 | SDL_JOYBALLMOTION = 1537, 52 | SDL_JOYHATMOTION = 1538, 53 | SDL_JOYBUTTONDOWN = 1539, 54 | SDL_JOYBUTTONUP = 1540, 55 | SDL_JOYDEVICEADDED = 1541, 56 | SDL_JOYDEVICEREMOVED = 1542, 57 | SDL_CONTROLLERAXISMOTION = 1616, 58 | SDL_CONTROLLERBUTTONDOWN = 1617, 59 | SDL_CONTROLLERBUTTONUP = 1618, 60 | SDL_CONTROLLERDEVICEADDED = 1619, 61 | SDL_CONTROLLERDEVICEREMOVED = 1620, 62 | SDL_CONTROLLERDEVICEREMAPPED = 1621, 63 | SDL_FINGERDOWN = 1792, 64 | SDL_FINGERUP = 1793, 65 | SDL_FINGERMOTION = 1794, 66 | SDL_DOLLARGESTURE = 2048, 67 | SDL_DOLLARRECORD = 2049, 68 | SDL_MULTIGESTURE = 2050, 69 | SDL_CLIPBOARDUPDATE = 2304, 70 | SDL_DROPFILE = 4096, 71 | SDL_DROPTEXT, 72 | SDL_DROPBEGIN, 73 | SDL_DROPCOMPLETE, 74 | SDL_AUDIODEVICEADDED = 4352, 75 | SDL_AUDIODEVICEREMOVED = 4353, 76 | SDL_RENDER_TARGETS_RESET = 8192, 77 | SDL_RENDER_DEVICE_RESET = 8193, 78 | SDL_USEREVENT = 32768, 79 | SDL_LASTEVENT = 65535 80 | } 81 | 82 | export function createSDLEvent() { 83 | 84 | return ref.alloc(SDL_Event); 85 | } 86 | export function pollForEventsForever() { 87 | function forever() { 88 | SDL.SDL_PollEvent(null); 89 | // setTimeout(forever, 10); 90 | } 91 | 92 | setInterval(forever, 10); 93 | } 94 | 95 | export function SDL_PumpEvents() { 96 | return SDL.SDL_PumpEvents(); 97 | } 98 | 99 | export function SDL_PollEvent(sdlEvent: any) { 100 | return SDL.SDL_PollEvent(sdlEvent); 101 | } 102 | 103 | export function createEventFilterFunction(filter: (data: any, event: any) => void) { 104 | return SDL_EventFilter.toPointer(filter); 105 | } 106 | 107 | // SDL_events.SDL_AddEventWatch(globals.filter, null); 108 | export function SDL_AddEventWatch(filterFunctionPtr: any, dataPtr: any) { 109 | SDL.SDL_AddEventWatch(filterFunctionPtr, dataPtr); 110 | } 111 | 112 | export function SDL_EventState(flag: number, value: number) { 113 | return SDL.SDL_EventState(flag, value); 114 | 115 | } 116 | 117 | export enum SDL_eventaction { 118 | SDL_ADDEVEN = 0, 119 | SDL_PEEKEVENT = 1, 120 | SDL_GETEVENT = 2 121 | } 122 | 123 | export const SDL_CommonEvent = Struct({ 124 | type: Uint32, 125 | timestamp: Uint32 126 | }); 127 | 128 | export const SDL_WindowEvent = Struct({ 129 | type: Uint32, 130 | timestamp: Uint32, 131 | windowID: Uint32, 132 | event: Uint8, 133 | padding1: Uint8, 134 | padding2: Uint8, 135 | padding3: Uint8, 136 | data1: Sint32, 137 | data2: Sint32 138 | }); 139 | 140 | export const SDL_KeyboardEvent = Struct({ 141 | type: Uint32, 142 | timestamp: Uint32, 143 | windowID: Uint32, 144 | state: Uint8, 145 | repeat: Uint8, 146 | padding2: Uint8, 147 | padding3: Uint8, 148 | keysym: SDL_Keysym 149 | }); 150 | 151 | export const SDL_TextEditingEvent = Struct({ 152 | type: Uint32, 153 | timestamp: Uint32, 154 | windowID: Uint32, 155 | text: ArrayType(char, 32), 156 | start: Sint32, 157 | length: Sint32 158 | }); 159 | 160 | export const SDL_TextInputEvent = Struct({ 161 | type: Uint32, 162 | timestamp: Uint32, 163 | windowID: Uint32, 164 | text: ArrayType(char, 32) 165 | }); 166 | 167 | export const SDL_MouseMotionEvent = Struct({ 168 | type: Uint32, 169 | timestamp: Uint32, 170 | windowID: Uint32, 171 | which: Uint32, 172 | state: Uint32, 173 | x: Sint32, 174 | y: Sint32, 175 | xrel: Sint32, 176 | yrel: Sint32 177 | }); 178 | 179 | export const SDL_MouseButtonEvent = Struct({ 180 | type: Uint32, 181 | timestamp: Uint32, 182 | windowID: Uint32, 183 | which: Uint32, 184 | button: Uint8, 185 | state: Uint8, 186 | clicks: Uint8, 187 | padding1: Uint8, 188 | x: Sint32, 189 | y: Sint32 190 | }); 191 | 192 | export const SDL_MouseWheelEvent = Struct({ 193 | type: Uint32, 194 | timestamp: Uint32, 195 | windowID: Uint32, 196 | which: Uint32, 197 | x: Sint32, 198 | y: Sint32, 199 | direction: Uint32 200 | }); 201 | 202 | export const SDL_JoyAxisEvent = Struct({ 203 | type: Uint32, 204 | timestamp: Uint32, 205 | which: SDL_JoystickID, 206 | axis: Uint8, 207 | padding1: Uint8, 208 | padding2: Uint8, 209 | padding3: Uint8, 210 | value: Sint16, 211 | padding4: Uint16 212 | }); 213 | 214 | export const SDL_JoyBallEvent = Struct({ 215 | type: Uint32, 216 | timestamp: Uint32, 217 | which: SDL_JoystickID, 218 | ball: Uint8, 219 | padding1: Uint8, 220 | padding2: Uint8, 221 | padding3: Uint8, 222 | xrel: Sint16, 223 | yrel: Sint16 224 | }); 225 | 226 | export const SDL_JoyHatEvent = Struct({ 227 | type: Uint32, 228 | timestamp: Uint32, 229 | which: SDL_JoystickID, 230 | hat: Uint8, 231 | value: Uint8, 232 | padding1: Uint8, 233 | padding2: Uint8 234 | }); 235 | 236 | export const SDL_JoyButtonEvent = Struct({ 237 | type: Uint32, 238 | timestamp: Uint32, 239 | which: SDL_JoystickID, 240 | button: Uint8, 241 | state: Uint8, 242 | padding1: Uint8, 243 | padding2: Uint8 244 | }); 245 | 246 | export const SDL_JoyDeviceEvent = Struct({ 247 | type: Uint32, 248 | timestamp: Uint32, 249 | which: Sint32 250 | }); 251 | 252 | export const SDL_ControllerAxisEvent = Struct({ 253 | type: Uint32, 254 | timestamp: Uint32, 255 | which: SDL_JoystickID, 256 | axis: Uint8, 257 | padding1: Uint8, 258 | padding2: Uint8, 259 | padding3: Uint8, 260 | value: Sint16, 261 | padding4: Uint16 262 | }); 263 | 264 | export const SDL_ControllerButtonEvent = Struct({ 265 | type: Uint32, 266 | timestamp: Uint32, 267 | which: SDL_JoystickID, 268 | button: Uint8, 269 | state: Uint8, 270 | padding1: Uint8, 271 | padding2: Uint8, 272 | }); 273 | 274 | export const SDL_ControllerDeviceEvent = Struct({ 275 | type: Uint32, 276 | timestamp: Uint32, 277 | which: Sint32, 278 | }); 279 | 280 | export const SDL_AudioDeviceEvent = Struct({ 281 | type: Uint32, 282 | timestamp: Uint32, 283 | which: Uint32, 284 | iscapture: Uint8, 285 | padding1: Uint8, 286 | padding2: Uint8, 287 | padding3: Uint8, 288 | }); 289 | 290 | export const SDL_TouchFingerEvent = Struct({ 291 | type: Uint32, 292 | timestamp: Uint32, 293 | touchId: SDL_TouchID, 294 | fingerId: SDL_FingerID, 295 | x: float, 296 | y: float, 297 | dx: float, 298 | dy: float, 299 | pressure: float, 300 | }); 301 | 302 | export const SDL_MultiGestureEvent = Struct({ 303 | type: Uint32, 304 | timestamp: Uint32, 305 | touchId: SDL_TouchID, 306 | dTheta: float, 307 | dDist: float, 308 | x: float, 309 | y: float, 310 | numFingers: Uint16, 311 | padding: Uint16, 312 | }); 313 | 314 | 315 | export const SDL_DollarGestureEvent = Struct({ 316 | type: Uint32, 317 | timestamp: Uint32, 318 | touchId: SDL_TouchID, 319 | gestureId: SDL_GestureID, 320 | numFingers: Uint32, 321 | error: float, 322 | x: float, 323 | y: float, 324 | }); 325 | 326 | export const SDL_DropEvent = Struct({ 327 | type: Uint32, 328 | timestamp: Uint32, 329 | file: string, 330 | }); 331 | 332 | export const SDL_QuitEvent = Struct({ 333 | type: Uint32, 334 | timestamp: Uint32, 335 | }); 336 | 337 | export const SDL_OSEvent = Struct({ 338 | type: Uint32, 339 | timestamp: Uint32, 340 | }); 341 | 342 | 343 | export const SDL_UserEvent = Struct({ 344 | type: Uint32, 345 | timestamp: Uint32, 346 | windowID: Uint32, 347 | code: Sint32, 348 | data1: voit_ptr, 349 | data2: voit_ptr 350 | }); 351 | 352 | export const SDL_SysWMmsg = voit; 353 | 354 | export const SDL_SysWMmsg_ptr = ref.refType(SDL_SysWMmsg); 355 | 356 | export const SDL_SysWMEvent = Struct({ 357 | type: Uint32, 358 | timestamp: Uint32, 359 | msg: SDL_SysWMmsg_ptr, 360 | }); 361 | 362 | export const c__U_SDL_Event_FI_padding_arr = ArrayType(Uint8, 56); 363 | 364 | export const SDL_Event = Union({ 365 | type: Uint32, 366 | common: SDL_CommonEvent, 367 | window: SDL_WindowEvent, 368 | key: SDL_KeyboardEvent, 369 | edit: SDL_TextEditingEvent, 370 | text: SDL_TextInputEvent, 371 | motion: SDL_MouseMotionEvent, 372 | button: SDL_MouseButtonEvent, 373 | wheel: SDL_MouseWheelEvent, 374 | jaxis: SDL_JoyAxisEvent, 375 | jball: SDL_JoyBallEvent, 376 | jhat: SDL_JoyHatEvent, 377 | jbutton: SDL_JoyButtonEvent, 378 | jdevice: SDL_JoyDeviceEvent, 379 | caxis: SDL_ControllerAxisEvent, 380 | cbutton: SDL_ControllerButtonEvent, 381 | cdevice: SDL_ControllerDeviceEvent, 382 | adevice: SDL_AudioDeviceEvent, 383 | quit: SDL_QuitEvent, 384 | user: SDL_UserEvent, 385 | syswm: SDL_SysWMEvent, 386 | tfinger: SDL_TouchFingerEvent, 387 | mgesture: SDL_MultiGestureEvent, 388 | dgesture: SDL_DollarGestureEvent, 389 | drop: SDL_DropEvent, 390 | padding: c__U_SDL_Event_FI_padding_arr, 391 | }); 392 | 393 | export const SDL_Event_ptr = ref.refType(SDL_Event); 394 | 395 | export const SDL_EventFilter = FFI.Function(int32, [voit_ptr, SDL_Event_ptr]); 396 | 397 | export const SDL_EventFilter_ptr = ref.refType(SDL_EventFilter); 398 | 399 | loadLibrary({ 400 | SDL_PumpEvents: [voit, []], 401 | SDL_PeepEvents: [int32, [SDL_Event_ptr, int32, uint32, Uint32, Uint32]], 402 | SDL_HasEvent: [uint32, [Uint32]], 403 | SDL_HasEvents: [uint32, [Uint32, Uint32]], 404 | SDL_FlushEvent: [voit, [Uint32]], 405 | SDL_FlushEvents: [voit, [Uint32, Uint32]], 406 | SDL_PollEvent: [int32, [SDL_Event_ptr]], 407 | SDL_WaitEvent: [int32, [SDL_Event_ptr]], 408 | SDL_WaitEventTimeout: [int32, [SDL_Event_ptr, int32]], 409 | SDL_PushEvent: [int32, [SDL_Event_ptr]], 410 | SDL_SetEventFilter: [voit, [SDL_EventFilter, voit_ptr]], 411 | SDL_GetEventFilter: [uint32, [SDL_EventFilter_ptr, voit_ptr_ptr]], 412 | SDL_AddEventWatch: [voit, [SDL_EventFilter, voit_ptr]], 413 | SDL_DelEventWatch: [voit, [SDL_EventFilter, voit_ptr]], 414 | SDL_FilterEvents: [voit, [SDL_EventFilter, voit_ptr]], 415 | SDL_EventState: [Uint8, [Uint32, int32]], 416 | SDL_RegisterEvents: [Uint32, [int32]], 417 | }, SDL); 418 | 419 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-gesture.ts: -------------------------------------------------------------------------------- 1 | import {SDL_TouchID} from './sdl-touch'; 2 | import {loadLibrary} from './lib-loader'; 3 | import {SDL_RWops_ptr} from './sdl-rwops'; 4 | import {int32, longlong} from './types'; 5 | 6 | export const SDL_GestureID = longlong; 7 | 8 | const SDL = {} as any; 9 | 10 | loadLibrary({ 11 | SDL_RecordGesture: [int32, [SDL_TouchID]], 12 | SDL_SaveAllDollarTemplates: [int32, [SDL_RWops_ptr]], 13 | SDL_SaveDollarTemplate: [int32, [SDL_GestureID, SDL_RWops_ptr]], 14 | SDL_LoadDollarTemplates: [int32, [SDL_TouchID, SDL_RWops_ptr]], 15 | }, SDL); 16 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-joystick.ts: -------------------------------------------------------------------------------- 1 | import {int32, int32_ptr, Sint16, string, uint32, Uint8, voit} from './types'; 2 | import {loadLibrary} from './lib-loader'; 3 | 4 | const ref = require('ref-napi'); 5 | const ArrayType = require('ref-array-di')(ref); 6 | const Struct = require('ref-struct-di')(ref); 7 | 8 | const SDL = {} as any; 9 | 10 | export enum SDL_JoystickPowerLevel { 11 | SDL_JOYSTICK_POWER_UNKNOWN = -1, 12 | SDL_JOYSTICK_POWER_EMPTY = 0, 13 | SDL_JOYSTICK_POWER_LOW = 1, 14 | SDL_JOYSTICK_POWER_MEDIUM = 2, 15 | SDL_JOYSTICK_POWER_FULL = 3, 16 | SDL_JOYSTICK_POWER_WIRED = 4, 17 | SDL_JOYSTICK_POWER_MAX = 5 18 | } 19 | 20 | export const SDL_Joystick = voit; 21 | 22 | export const SDL_JoystickGUID = Struct({ 23 | data: ArrayType(Uint8, 16), 24 | }); 25 | 26 | export const SDL_JoystickID = int32; 27 | 28 | export const SDL_Joystick_ptr = ref.refType(SDL_Joystick); 29 | 30 | loadLibrary({ 31 | SDL_NumJoysticks: [int32, []], 32 | SDL_JoystickNameForIndex: [string, [int32]], 33 | SDL_JoystickOpen: [SDL_Joystick_ptr, [int32]], 34 | SDL_JoystickFromInstanceID: [SDL_Joystick_ptr, [SDL_JoystickID]], 35 | SDL_JoystickName: [string, [SDL_Joystick_ptr]], 36 | SDL_JoystickGetDeviceGUID: [SDL_JoystickGUID, [int32]], 37 | SDL_JoystickGetGUID: [SDL_JoystickGUID, [SDL_Joystick_ptr]], 38 | SDL_JoystickGetGUIDString: [voit, [SDL_JoystickGUID, string, int32]], 39 | SDL_JoystickGetGUIDFromString: [SDL_JoystickGUID, [string]], 40 | SDL_JoystickGetAttached: [uint32, [SDL_Joystick_ptr]], 41 | SDL_JoystickInstanceID: [SDL_JoystickID, [SDL_Joystick_ptr]], 42 | SDL_JoystickNumAxes: [int32, [SDL_Joystick_ptr]], 43 | SDL_JoystickNumBalls: [int32, [SDL_Joystick_ptr]], 44 | SDL_JoystickNumHats: [int32, [SDL_Joystick_ptr]], 45 | SDL_JoystickNumButtons: [int32, [SDL_Joystick_ptr]], 46 | SDL_JoystickUpdate: [voit, []], 47 | SDL_JoystickEventState: [int32, [int32]], 48 | SDL_JoystickGetAxis: [Sint16, [SDL_Joystick_ptr, int32]], 49 | SDL_JoystickGetHat: [Uint8, [SDL_Joystick_ptr, int32]], 50 | SDL_JoystickGetBall: [int32, [SDL_Joystick_ptr, int32, int32_ptr, int32_ptr]], 51 | SDL_JoystickGetButton: [Uint8, [SDL_Joystick_ptr, int32]], 52 | SDL_JoystickClose: [voit, [SDL_Joystick_ptr]], 53 | SDL_JoystickCurrentPowerLevel: [int32, [SDL_Joystick_ptr]], 54 | }, SDL); 55 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-keyboard.ts: -------------------------------------------------------------------------------- 1 | import {loadLibrary} from './lib-loader'; 2 | import {SDL_Rect_ptr} from './sdl-rect'; 3 | import {int32_ptr, string, Uint16, uint32, Uint32, Uint8_ptr, voit} from './types'; 4 | import {SDL_Keycode} from './sdl-keycode'; 5 | import {SDL_Window_ptr} from './sdl-video'; 6 | 7 | const ref = require('ref-napi'); 8 | const Struct = require('ref-struct-di')(ref); 9 | 10 | const SDL = {} as any; 11 | 12 | export function SDL_GetKeyboardState(numOfKeysPtr: any) { 13 | return SDL.SDL_GetKeyboardState(numOfKeysPtr); 14 | } 15 | 16 | export const SDL_Keymod = { 17 | KMOD_NONE: 0, 18 | KMOD_LSHIFT: 1, 19 | KMOD_RSHIFT: 2, 20 | KMOD_LCTRL: 64, 21 | KMOD_RCTRL: 128, 22 | KMOD_LALT: 256, 23 | KMOD_RALT: 512, 24 | KMOD_LGUI: 1024, 25 | KMOD_RGUI: 2048, 26 | KMOD_NUM: 4096, 27 | KMOD_CAPS: 8192, 28 | KMOD_MODE: 16384, 29 | KMOD_RESERVED: 32768, 30 | } as any; 31 | 32 | export const SDL_Scancode = { 33 | SDL_SCANCODE_UNKNOWN: 0, 34 | SDL_SCANCODE_A: 4, 35 | SDL_SCANCODE_B: 5, 36 | SDL_SCANCODE_C: 6, 37 | SDL_SCANCODE_D: 7, 38 | SDL_SCANCODE_E: 8, 39 | SDL_SCANCODE_F: 9, 40 | SDL_SCANCODE_G: 10, 41 | SDL_SCANCODE_H: 11, 42 | SDL_SCANCODE_I: 12, 43 | SDL_SCANCODE_J: 13, 44 | SDL_SCANCODE_K: 14, 45 | SDL_SCANCODE_L: 15, 46 | SDL_SCANCODE_M: 16, 47 | SDL_SCANCODE_N: 17, 48 | SDL_SCANCODE_O: 18, 49 | SDL_SCANCODE_P: 19, 50 | SDL_SCANCODE_Q: 20, 51 | SDL_SCANCODE_R: 21, 52 | SDL_SCANCODE_S: 22, 53 | SDL_SCANCODE_T: 23, 54 | SDL_SCANCODE_U: 24, 55 | SDL_SCANCODE_V: 25, 56 | SDL_SCANCODE_W: 26, 57 | SDL_SCANCODE_X: 27, 58 | SDL_SCANCODE_Y: 28, 59 | SDL_SCANCODE_Z: 29, 60 | SDL_SCANCODE_1: 30, 61 | SDL_SCANCODE_2: 31, 62 | SDL_SCANCODE_3: 32, 63 | SDL_SCANCODE_4: 33, 64 | SDL_SCANCODE_5: 34, 65 | SDL_SCANCODE_6: 35, 66 | SDL_SCANCODE_7: 36, 67 | SDL_SCANCODE_8: 37, 68 | SDL_SCANCODE_9: 38, 69 | SDL_SCANCODE_0: 39, 70 | SDL_SCANCODE_RETURN: 40, 71 | SDL_SCANCODE_ESCAPE: 41, 72 | SDL_SCANCODE_BACKSPACE: 42, 73 | SDL_SCANCODE_TAB: 43, 74 | SDL_SCANCODE_SPACE: 44, 75 | SDL_SCANCODE_MINUS: 45, 76 | SDL_SCANCODE_EQUALS: 46, 77 | SDL_SCANCODE_LEFTBRACKET: 47, 78 | SDL_SCANCODE_RIGHTBRACKET: 48, 79 | SDL_SCANCODE_BACKSLASH: 49, 80 | SDL_SCANCODE_NONUSHASH: 50, 81 | SDL_SCANCODE_SEMICOLON: 51, 82 | SDL_SCANCODE_APOSTROPHE: 52, 83 | SDL_SCANCODE_GRAVE: 53, 84 | SDL_SCANCODE_COMMA: 54, 85 | SDL_SCANCODE_PERIOD: 55, 86 | SDL_SCANCODE_SLASH: 56, 87 | SDL_SCANCODE_CAPSLOCK: 57, 88 | SDL_SCANCODE_F1: 58, 89 | SDL_SCANCODE_F2: 59, 90 | SDL_SCANCODE_F3: 60, 91 | SDL_SCANCODE_F4: 61, 92 | SDL_SCANCODE_F5: 62, 93 | SDL_SCANCODE_F6: 63, 94 | SDL_SCANCODE_F7: 64, 95 | SDL_SCANCODE_F8: 65, 96 | SDL_SCANCODE_F9: 66, 97 | SDL_SCANCODE_F10: 67, 98 | SDL_SCANCODE_F11: 68, 99 | SDL_SCANCODE_F12: 69, 100 | SDL_SCANCODE_PRINTSCREEN: 70, 101 | SDL_SCANCODE_SCROLLLOCK: 71, 102 | SDL_SCANCODE_PAUSE: 72, 103 | SDL_SCANCODE_INSERT: 73, 104 | SDL_SCANCODE_HOME: 74, 105 | SDL_SCANCODE_PAGEUP: 75, 106 | SDL_SCANCODE_DELETE: 76, 107 | SDL_SCANCODE_END: 77, 108 | SDL_SCANCODE_PAGEDOWN: 78, 109 | SDL_SCANCODE_RIGHT: 79, 110 | SDL_SCANCODE_LEFT: 80, 111 | SDL_SCANCODE_DOWN: 81, 112 | SDL_SCANCODE_UP: 82, 113 | SDL_SCANCODE_NUMLOCKCLEAR: 83, 114 | SDL_SCANCODE_KP_DIVIDE: 84, 115 | SDL_SCANCODE_KP_MULTIPLY: 85, 116 | SDL_SCANCODE_KP_MINUS: 86, 117 | SDL_SCANCODE_KP_PLUS: 87, 118 | SDL_SCANCODE_KP_ENTER: 88, 119 | SDL_SCANCODE_KP_1: 89, 120 | SDL_SCANCODE_KP_2: 90, 121 | SDL_SCANCODE_KP_3: 91, 122 | SDL_SCANCODE_KP_4: 92, 123 | SDL_SCANCODE_KP_5: 93, 124 | SDL_SCANCODE_KP_6: 94, 125 | SDL_SCANCODE_KP_7: 95, 126 | SDL_SCANCODE_KP_8: 96, 127 | SDL_SCANCODE_KP_9: 97, 128 | SDL_SCANCODE_KP_0: 98, 129 | SDL_SCANCODE_KP_PERIOD: 99, 130 | SDL_SCANCODE_NONUSBACKSLASH: 100, 131 | SDL_SCANCODE_APPLICATION: 101, 132 | SDL_SCANCODE_POWER: 102, 133 | SDL_SCANCODE_KP_EQUALS: 103, 134 | SDL_SCANCODE_F13: 104, 135 | SDL_SCANCODE_F14: 105, 136 | SDL_SCANCODE_F15: 106, 137 | SDL_SCANCODE_F16: 107, 138 | SDL_SCANCODE_F17: 108, 139 | SDL_SCANCODE_F18: 109, 140 | SDL_SCANCODE_F19: 110, 141 | SDL_SCANCODE_F20: 111, 142 | SDL_SCANCODE_F21: 112, 143 | SDL_SCANCODE_F22: 113, 144 | SDL_SCANCODE_F23: 114, 145 | SDL_SCANCODE_F24: 115, 146 | SDL_SCANCODE_EXECUTE: 116, 147 | SDL_SCANCODE_HELP: 117, 148 | SDL_SCANCODE_MENU: 118, 149 | SDL_SCANCODE_SELECT: 119, 150 | SDL_SCANCODE_STOP: 120, 151 | SDL_SCANCODE_AGAIN: 121, 152 | SDL_SCANCODE_UNDO: 122, 153 | SDL_SCANCODE_CUT: 123, 154 | SDL_SCANCODE_COPY: 124, 155 | SDL_SCANCODE_PASTE: 125, 156 | SDL_SCANCODE_FIND: 126, 157 | SDL_SCANCODE_MUTE: 127, 158 | SDL_SCANCODE_VOLUMEUP: 128, 159 | SDL_SCANCODE_VOLUMEDOWN: 129, 160 | SDL_SCANCODE_KP_COMMA: 133, 161 | SDL_SCANCODE_KP_EQUALSAS400: 134, 162 | SDL_SCANCODE_INTERNATIONAL1: 135, 163 | SDL_SCANCODE_INTERNATIONAL2: 136, 164 | SDL_SCANCODE_INTERNATIONAL3: 137, 165 | SDL_SCANCODE_INTERNATIONAL4: 138, 166 | SDL_SCANCODE_INTERNATIONAL5: 139, 167 | SDL_SCANCODE_INTERNATIONAL6: 140, 168 | SDL_SCANCODE_INTERNATIONAL7: 141, 169 | SDL_SCANCODE_INTERNATIONAL8: 142, 170 | SDL_SCANCODE_INTERNATIONAL9: 143, 171 | SDL_SCANCODE_LANG1: 144, 172 | SDL_SCANCODE_LANG2: 145, 173 | SDL_SCANCODE_LANG3: 146, 174 | SDL_SCANCODE_LANG4: 147, 175 | SDL_SCANCODE_LANG5: 148, 176 | SDL_SCANCODE_LANG6: 149, 177 | SDL_SCANCODE_LANG7: 150, 178 | SDL_SCANCODE_LANG8: 151, 179 | SDL_SCANCODE_LANG9: 152, 180 | SDL_SCANCODE_ALTERASE: 153, 181 | SDL_SCANCODE_SYSREQ: 154, 182 | SDL_SCANCODE_CANCEL: 155, 183 | SDL_SCANCODE_CLEAR: 156, 184 | SDL_SCANCODE_PRIOR: 157, 185 | SDL_SCANCODE_RETURN2: 158, 186 | SDL_SCANCODE_SEPARATOR: 159, 187 | SDL_SCANCODE_OUT: 160, 188 | SDL_SCANCODE_OPER: 161, 189 | SDL_SCANCODE_CLEARAGAIN: 162, 190 | SDL_SCANCODE_CRSEL: 163, 191 | SDL_SCANCODE_EXSEL: 164, 192 | SDL_SCANCODE_KP_00: 176, 193 | SDL_SCANCODE_KP_000: 177, 194 | SDL_SCANCODE_THOUSANDSSEPARATOR: 178, 195 | SDL_SCANCODE_DECIMALSEPARATOR: 179, 196 | SDL_SCANCODE_CURRENCYUNIT: 180, 197 | SDL_SCANCODE_CURRENCYSUBUNIT: 181, 198 | SDL_SCANCODE_KP_LEFTPAREN: 182, 199 | SDL_SCANCODE_KP_RIGHTPAREN: 183, 200 | SDL_SCANCODE_KP_LEFTBRACE: 184, 201 | SDL_SCANCODE_KP_RIGHTBRACE: 185, 202 | SDL_SCANCODE_KP_TAB: 186, 203 | SDL_SCANCODE_KP_BACKSPACE: 187, 204 | SDL_SCANCODE_KP_A: 188, 205 | SDL_SCANCODE_KP_B: 189, 206 | SDL_SCANCODE_KP_C: 190, 207 | SDL_SCANCODE_KP_D: 191, 208 | SDL_SCANCODE_KP_E: 192, 209 | SDL_SCANCODE_KP_F: 193, 210 | SDL_SCANCODE_KP_XOR: 194, 211 | SDL_SCANCODE_KP_POWER: 195, 212 | SDL_SCANCODE_KP_PERCENT: 196, 213 | SDL_SCANCODE_KP_LESS: 197, 214 | SDL_SCANCODE_KP_GREATER: 198, 215 | SDL_SCANCODE_KP_AMPERSAND: 199, 216 | SDL_SCANCODE_KP_DBLAMPERSAND: 200, 217 | SDL_SCANCODE_KP_VERTICALBAR: 201, 218 | SDL_SCANCODE_KP_DBLVERTICALBAR: 202, 219 | SDL_SCANCODE_KP_COLON: 203, 220 | SDL_SCANCODE_KP_HASH: 204, 221 | SDL_SCANCODE_KP_SPACE: 205, 222 | SDL_SCANCODE_KP_AT: 206, 223 | SDL_SCANCODE_KP_EXCLAM: 207, 224 | SDL_SCANCODE_KP_MEMSTORE: 208, 225 | SDL_SCANCODE_KP_MEMRECALL: 209, 226 | SDL_SCANCODE_KP_MEMCLEAR: 210, 227 | SDL_SCANCODE_KP_MEMADD: 211, 228 | SDL_SCANCODE_KP_MEMSUBTRACT: 212, 229 | SDL_SCANCODE_KP_MEMMULTIPLY: 213, 230 | SDL_SCANCODE_KP_MEMDIVIDE: 214, 231 | SDL_SCANCODE_KP_PLUSMINUS: 215, 232 | SDL_SCANCODE_KP_CLEAR: 216, 233 | SDL_SCANCODE_KP_CLEARENTRY: 217, 234 | SDL_SCANCODE_KP_BINARY: 218, 235 | SDL_SCANCODE_KP_OCTAL: 219, 236 | SDL_SCANCODE_KP_DECIMAL: 220, 237 | SDL_SCANCODE_KP_HEXADECIMAL: 221, 238 | SDL_SCANCODE_LCTRL: 224, 239 | SDL_SCANCODE_LSHIFT: 225, 240 | SDL_SCANCODE_LALT: 226, 241 | SDL_SCANCODE_LGUI: 227, 242 | SDL_SCANCODE_RCTRL: 228, 243 | SDL_SCANCODE_RSHIFT: 229, 244 | SDL_SCANCODE_RALT: 230, 245 | SDL_SCANCODE_RGUI: 231, 246 | SDL_SCANCODE_MODE: 257, 247 | SDL_SCANCODE_AUDIONEXT: 258, 248 | SDL_SCANCODE_AUDIOPREV: 259, 249 | SDL_SCANCODE_AUDIOSTOP: 260, 250 | SDL_SCANCODE_AUDIOPLAY: 261, 251 | SDL_SCANCODE_AUDIOMUTE: 262, 252 | SDL_SCANCODE_MEDIASELECT: 263, 253 | SDL_SCANCODE_WWW: 264, 254 | SDL_SCANCODE_MAIL: 265, 255 | SDL_SCANCODE_CALCULATOR: 266, 256 | SDL_SCANCODE_COMPUTER: 267, 257 | SDL_SCANCODE_AC_SEARCH: 268, 258 | SDL_SCANCODE_AC_HOME: 269, 259 | SDL_SCANCODE_AC_BACK: 270, 260 | SDL_SCANCODE_AC_FORWARD: 271, 261 | SDL_SCANCODE_AC_STOP: 272, 262 | SDL_SCANCODE_AC_REFRESH: 273, 263 | SDL_SCANCODE_AC_BOOKMARKS: 274, 264 | SDL_SCANCODE_BRIGHTNESSDOWN: 275, 265 | SDL_SCANCODE_BRIGHTNESSUP: 276, 266 | SDL_SCANCODE_DISPLAYSWITCH: 277, 267 | SDL_SCANCODE_KBDILLUMTOGGLE: 278, 268 | SDL_SCANCODE_KBDILLUMDOWN: 279, 269 | SDL_SCANCODE_KBDILLUMUP: 280, 270 | SDL_SCANCODE_EJECT: 281, 271 | SDL_SCANCODE_SLEEP: 282, 272 | SDL_SCANCODE_APP1: 283, 273 | SDL_SCANCODE_APP2: 284, 274 | SDL_NUM_SCANCODES: 512, 275 | } as any; 276 | 277 | export const SDL_Keysym = Struct({ 278 | scancode: uint32, 279 | sym: SDL_Keycode, 280 | mod: Uint16, 281 | unused: Uint32, 282 | }); 283 | 284 | export function SDL_GetScancodeName(keyCode: number): string { 285 | return SDL.SDL_GetScancodeName(keyCode); 286 | } 287 | 288 | export function SDL_GetKeyName(keyCode: number): string { 289 | return SDL.SDL_GetKeyName(keyCode); 290 | } 291 | 292 | loadLibrary({ 293 | SDL_GetKeyboardFocus: [SDL_Window_ptr, []], 294 | SDL_GetKeyboardState: [Uint8_ptr, [int32_ptr]], 295 | SDL_GetModState: [uint32, []], 296 | SDL_SetModState: [voit, [uint32]], 297 | SDL_GetKeyFromScancode: [SDL_Keycode, [uint32]], 298 | SDL_GetScancodeFromKey: [uint32, [SDL_Keycode]], 299 | SDL_GetScancodeName: [string, [uint32]], 300 | SDL_GetScancodeFromName: [uint32, [string]], 301 | SDL_GetKeyName: [string, [SDL_Keycode]], 302 | SDL_GetKeyFromName: [SDL_Keycode, [string]], 303 | SDL_StartTextInput: [voit, []], 304 | SDL_IsTextInputActive: [uint32, []], 305 | SDL_StopTextInput: [voit, []], 306 | SDL_SetTextInputRect: [voit, [SDL_Rect_ptr]], 307 | SDL_HasScreenKeyboardSupport: [uint32, []], 308 | SDL_IsScreenKeyboardShown: [uint32, [SDL_Window_ptr]], 309 | }, SDL); 310 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-keycode.ts: -------------------------------------------------------------------------------- 1 | import {int32} from './types'; 2 | 3 | export const SDL_Keycode = int32; 4 | 5 | export enum SDL_keycode { 6 | SDLK_UNKNOWN = 0, 7 | SDLK_RETURN = 13, 8 | SDLK_ESCAPE = 27, 9 | SDLK_BACKSPACE = 8, 10 | SDLK_TAB = 9, 11 | SDLK_SPACE = 32, 12 | SDLK_EXCLAIM = 33, 13 | SDLK_QUOTEDBL = 34, 14 | SDLK_HASH = 35, 15 | SDLK_PERCENT = 37, 16 | SDLK_DOLLAR = 36, 17 | SDLK_AMPERSAND = 38, 18 | SDLK_QUOTE = 39, 19 | SDLK_LEFTPAREN = 40, 20 | SDLK_RIGHTPAREN = 41, 21 | SDLK_ASTERISK = 42, 22 | SDLK_PLUS = 43, 23 | SDLK_COMMA = 44, 24 | SDLK_MINUS = 45, 25 | SDLK_PERIOD = 46, 26 | SDLK_SLASH = 47, 27 | SDLK_0 = 48, 28 | SDLK_1 = 49, 29 | SDLK_2 = 50, 30 | SDLK_3 = 51, 31 | SDLK_4 = 52, 32 | SDLK_5 = 53, 33 | SDLK_6 = 54, 34 | SDLK_7 = 55, 35 | SDLK_8 = 56, 36 | SDLK_9 = 57, 37 | SDLK_COLON = 58, 38 | SDLK_SEMICOLON = 59, 39 | SDLK_LESS = 60, 40 | SDLK_EQUALS = 61, 41 | SDLK_GREATER = 62, 42 | SDLK_QUESTION = 63, 43 | SDLK_AT = 64, 44 | SDLK_LEFTBRACKET = 91, 45 | SDLK_BACKSLASH = 92, 46 | SDLK_RIGHTBRACKET = 93, 47 | SDLK_CARET = 94, 48 | SDLK_UNDERSCORE = 95, 49 | SDLK_BACKQUOTE = 96, 50 | SDLK_a = 97, 51 | SDLK_b = 98, 52 | SDLK_c = 99, 53 | SDLK_d = 100, 54 | SDLK_e = 101, 55 | SDLK_f = 102, 56 | SDLK_g = 103, 57 | SDLK_h = 104, 58 | SDLK_i = 105, 59 | SDLK_j = 106, 60 | SDLK_k = 107, 61 | SDLK_l = 108, 62 | SDLK_m = 109, 63 | SDLK_n = 110, 64 | SDLK_o = 111, 65 | SDLK_p = 112, 66 | SDLK_q = 113, 67 | SDLK_r = 114, 68 | SDLK_s = 115, 69 | SDLK_t = 116, 70 | SDLK_u = 117, 71 | SDLK_v = 118, 72 | SDLK_w = 119, 73 | SDLK_x = 120, 74 | SDLK_y = 121, 75 | SDLK_z = 122, 76 | SDLK_CAPSLOCK = 1073741881, 77 | SDLK_F1 = 1073741882, 78 | SDLK_F2 = 1073741883, 79 | SDLK_F3 = 1073741884, 80 | SDLK_F4 = 1073741885, 81 | SDLK_F5 = 1073741886, 82 | SDLK_F6 = 1073741887, 83 | SDLK_F7 = 1073741888, 84 | SDLK_F8 = 1073741889, 85 | SDLK_F9 = 1073741890, 86 | SDLK_F10 = 1073741891, 87 | SDLK_F11 = 1073741892, 88 | SDLK_F12 = 1073741893, 89 | SDLK_PRINTSCREEN = 1073741894, 90 | SDLK_SCROLLLOCK = 1073741895, 91 | SDLK_PAUSE = 1073741896, 92 | SDLK_INSERT = 1073741897, 93 | SDLK_HOME = 1073741898, 94 | SDLK_PAGEUP = 1073741899, 95 | SDLK_DELETE = 127, 96 | SDLK_END = 1073741901, 97 | SDLK_PAGEDOWN = 1073741902, 98 | SDLK_RIGHT = 1073741903, 99 | SDLK_LEFT = 1073741904, 100 | SDLK_DOWN = 1073741905, 101 | SDLK_UP = 1073741906, 102 | SDLK_NUMLOCKCLEAR = 1073741907, 103 | SDLK_KP_DIVIDE = 1073741908, 104 | SDLK_KP_MULTIPLY = 1073741909, 105 | SDLK_KP_MINUS = 1073741910, 106 | SDLK_KP_PLUS = 1073741911, 107 | SDLK_KP_ENTER = 1073741912, 108 | SDLK_KP_1 = 1073741913, 109 | SDLK_KP_2 = 1073741914, 110 | SDLK_KP_3 = 1073741915, 111 | SDLK_KP_4 = 1073741916, 112 | SDLK_KP_5 = 1073741917, 113 | SDLK_KP_6 = 1073741918, 114 | SDLK_KP_7 = 1073741919, 115 | SDLK_KP_8 = 1073741920, 116 | SDLK_KP_9 = 1073741921, 117 | SDLK_KP_0 = 1073741922, 118 | SDLK_KP_PERIOD = 1073741923, 119 | SDLK_APPLICATION = 1073741925, 120 | SDLK_POWER = 1073741926, 121 | SDLK_KP_EQUALS = 1073741927, 122 | SDLK_F13 = 1073741928, 123 | SDLK_F14 = 1073741929, 124 | SDLK_F15 = 1073741930, 125 | SDLK_F16 = 1073741931, 126 | SDLK_F17 = 1073741932, 127 | SDLK_F18 = 1073741933, 128 | SDLK_F19 = 1073741934, 129 | SDLK_F20 = 1073741935, 130 | SDLK_F21 = 1073741936, 131 | SDLK_F22 = 1073741937, 132 | SDLK_F23 = 1073741938, 133 | SDLK_F24 = 1073741939, 134 | SDLK_EXECUTE = 1073741940, 135 | SDLK_HELP = 1073741941, 136 | SDLK_MENU = 1073741942, 137 | SDLK_SELECT = 1073741943, 138 | SDLK_STOP = 1073741944, 139 | SDLK_AGAIN = 1073741945, 140 | SDLK_UNDO = 1073741946, 141 | SDLK_CUT = 1073741947, 142 | SDLK_COPY = 1073741948, 143 | SDLK_PASTE = 1073741949, 144 | SDLK_FIND = 1073741950, 145 | SDLK_MUTE = 1073741951, 146 | SDLK_VOLUMEUP = 1073741952, 147 | SDLK_VOLUMEDOWN = 1073741953, 148 | SDLK_KP_COMMA = 1073741957, 149 | SDLK_KP_EQUALSAS400 = 1073741958, 150 | SDLK_ALTERASE = 1073741977, 151 | SDLK_SYSREQ = 1073741978, 152 | SDLK_CANCEL = 1073741979, 153 | SDLK_CLEAR = 1073741980, 154 | SDLK_PRIOR = 1073741981, 155 | SDLK_RETURN2 = 1073741982, 156 | SDLK_SEPARATOR = 1073741983, 157 | SDLK_OUT = 1073741984, 158 | SDLK_OPER = 1073741985, 159 | SDLK_CLEARAGAIN = 1073741986, 160 | SDLK_CRSEL = 1073741987, 161 | SDLK_EXSEL = 1073741988, 162 | SDLK_KP_00 = 1073742000, 163 | SDLK_KP_000 = 1073742001, 164 | SDLK_THOUSANDSSEPARATOR = 1073742002, 165 | SDLK_DECIMALSEPARATOR = 1073742003, 166 | SDLK_CURRENCYUNIT = 1073742004, 167 | SDLK_CURRENCYSUBUNIT = 1073742005, 168 | SDLK_KP_LEFTPAREN = 1073742006, 169 | SDLK_KP_RIGHTPAREN = 1073742007, 170 | SDLK_KP_LEFTBRACE = 1073742008, 171 | SDLK_KP_RIGHTBRACE = 1073742009, 172 | SDLK_KP_TAB = 1073742010, 173 | SDLK_KP_BACKSPACE = 1073742011, 174 | SDLK_KP_A = 1073742012, 175 | SDLK_KP_B = 1073742013, 176 | SDLK_KP_C = 1073742014, 177 | SDLK_KP_D = 1073742015, 178 | SDLK_KP_E = 1073742016, 179 | SDLK_KP_F = 1073742017, 180 | SDLK_KP_XOR = 1073742018, 181 | SDLK_KP_POWER = 1073742019, 182 | SDLK_KP_PERCENT = 1073742020, 183 | SDLK_KP_LESS = 1073742021, 184 | SDLK_KP_GREATER = 1073742022, 185 | SDLK_KP_AMPERSAND = 1073742023, 186 | SDLK_KP_DBLAMPERSAND = 1073742024, 187 | SDLK_KP_VERTICALBAR = 1073742025, 188 | SDLK_KP_DBLVERTICALBAR = 1073742026, 189 | SDLK_KP_COLON = 1073742027, 190 | SDLK_KP_HASH = 1073742028, 191 | SDLK_KP_SPACE = 1073742029, 192 | SDLK_KP_AT = 1073742030, 193 | SDLK_KP_EXCLAM = 1073742031, 194 | SDLK_KP_MEMSTORE = 1073742032, 195 | SDLK_KP_MEMRECALL = 1073742033, 196 | SDLK_KP_MEMCLEAR = 1073742034, 197 | SDLK_KP_MEMADD = 1073742035, 198 | SDLK_KP_MEMSUBTRACT = 1073742036, 199 | SDLK_KP_MEMMULTIPLY = 1073742037, 200 | SDLK_KP_MEMDIVIDE = 1073742038, 201 | SDLK_KP_PLUSMINUS = 1073742039, 202 | SDLK_KP_CLEAR = 1073742040, 203 | SDLK_KP_CLEARENTRY = 1073742041, 204 | SDLK_KP_BINARY = 1073742042, 205 | SDLK_KP_OCTAL = 1073742043, 206 | SDLK_KP_DECIMAL = 1073742044, 207 | SDLK_KP_HEXADECIMAL = 1073742045, 208 | SDLK_LCTRL = 1073742048, 209 | SDLK_LSHIFT = 1073742049, 210 | SDLK_LALT = 1073742050, 211 | SDLK_LGUI = 1073742051, 212 | SDLK_RCTRL = 1073742052, 213 | SDLK_RSHIFT = 1073742053, 214 | SDLK_RALT = 1073742054, 215 | SDLK_RGUI = 1073742055, 216 | SDLK_MODE = 1073742081, 217 | SDLK_AUDIONEXT = 1073742082, 218 | SDLK_AUDIOPREV = 1073742083, 219 | SDLK_AUDIOSTOP = 1073742084, 220 | SDLK_AUDIOPLAY = 1073742085, 221 | SDLK_AUDIOMUTE = 1073742086, 222 | SDLK_MEDIASELECT = 1073742087, 223 | SDLK_WWW = 1073742088, 224 | SDLK_MAIL = 1073742089, 225 | SDLK_CALCULATOR = 1073742090, 226 | SDLK_COMPUTER = 1073742091, 227 | SDLK_AC_SEARCH = 1073742092, 228 | SDLK_AC_HOME = 1073742093, 229 | SDLK_AC_BACK = 1073742094, 230 | SDLK_AC_FORWARD = 1073742095, 231 | SDLK_AC_STOP = 1073742096, 232 | SDLK_AC_REFRESH = 1073742097, 233 | SDLK_AC_BOOKMARKS = 1073742098, 234 | SDLK_BRIGHTNESSDOWN = 1073742099, 235 | SDLK_BRIGHTNESSUP = 1073742100, 236 | SDLK_DISPLAYSWITCH = 1073742101, 237 | SDLK_KBDILLUMTOGGLE = 1073742102, 238 | SDLK_KBDILLUMDOWN = 1073742103, 239 | SDLK_KBDILLUMUP = 1073742104, 240 | SDLK_EJECT = 1073742105, 241 | SDLK_SLEEP = 1073742106 242 | } 243 | 244 | export enum SDL_Keymod { 245 | KMOD_NONE = 0, 246 | KMOD_LSHIFT = 1, 247 | KMOD_RSHIFT = 2, 248 | KMOD_LCTRL = 64, 249 | KMOD_RCTRL = 128, 250 | KMOD_LALT = 256, 251 | KMOD_RALT = 512, 252 | KMOD_LGUI = 1024, 253 | KMOD_RGUI = 2048, 254 | KMOD_NUM = 4096, 255 | KMOD_CAPS = 8192, 256 | KMOD_MODE = 16384, 257 | KMOD_RESERVED = 32768 258 | } 259 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-messagebox.ts: -------------------------------------------------------------------------------- 1 | import {loadLibrary} from './lib-loader'; 2 | import {int32, int32_ptr, string, Uint32, Uint8} from './types'; 3 | import {SDL_Window_ptr} from './sdl-video'; 4 | 5 | const ref = require('ref-napi'); 6 | const ArrayType = require('ref-array-di')(ref); 7 | const Struct = require('ref-struct-di')(ref); 8 | 9 | const SDL = {} as any; 10 | 11 | export function SDL_Create_MessageBoxButtonData(buttons: { type: string, text: string }[]) { 12 | const num = buttons.length; 13 | const size = SDL_MessageBoxButtonData.size; 14 | 15 | const buttonData: any = new Buffer(num * size); 16 | buttonData.type = SDL_MessageBoxButtonData; 17 | 18 | buttons.forEach((button: any, index: number) => { 19 | let type = button.type; 20 | let flags = 0; 21 | 22 | if (type === 'yes') { 23 | flags = SDL_MessageBoxButtonFlags.SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; 24 | } else if (type = 'cancel') { 25 | flags = SDL_MessageBoxButtonFlags.SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; 26 | } 27 | 28 | ref.set(buttonData, index * size, new SDL_MessageBoxButtonData({ 29 | flags: flags, 30 | buttonid: index, 31 | text: (button.text || '') 32 | })); 33 | }); 34 | 35 | return buttonData; 36 | } 37 | 38 | function Create_SDL_MessageBoxData(title: string, message: string, flags: number, buttons: any, numbuttons: number, windowPtr: any = null): any { 39 | const messageBoxData = new SDL_MessageBoxData({ 40 | flags: flags, 41 | window: windowPtr, 42 | title: title, 43 | message: message, 44 | numbuttons: numbuttons, 45 | buttons: buttons, 46 | colorScheme: null 47 | }); 48 | 49 | return messageBoxData.ref(); 50 | } 51 | 52 | export function SDL_ShowMessageBox(type: string, title: string, message: string, buttons: any, numberOfButtons: number, windowPtr: any = null): number { 53 | let messageFlags; 54 | let id = ref.alloc('int'); 55 | 56 | if (type === 'error') { 57 | messageFlags = SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR; 58 | } else if (type === 'warning') { 59 | messageFlags = SDL_MessageBoxFlags.SDL_MESSAGEBOX_WARNING; 60 | } else { 61 | messageFlags = SDL_MessageBoxFlags.SDL_MESSAGEBOX_INFORMATION; 62 | } 63 | 64 | const messageBoxDataPtr = Create_SDL_MessageBoxData(title, message, messageFlags, buttons, numberOfButtons, windowPtr); 65 | SDL.SDL_ShowMessageBox(messageBoxDataPtr, id); 66 | 67 | id = id.deref(); 68 | 69 | return id; 70 | } 71 | 72 | export enum SDL_MessageBoxFlags { 73 | SDL_MESSAGEBOX_ERROR = 16, 74 | SDL_MESSAGEBOX_WARNING = 32, 75 | SDL_MESSAGEBOX_INFORMATION = 64 76 | } 77 | 78 | export enum SDL_MessageBoxButtonFlags { 79 | SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 1, 80 | SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 2 81 | } 82 | 83 | export enum SDL_MessageBoxColorType { 84 | SDL_MESSAGEBOX_COLOR_BACKGROUND = 0, 85 | SDL_MESSAGEBOX_COLOR_TEXT = 1, 86 | SDL_MESSAGEBOX_COLOR_BUTTON_BORDER = 2, 87 | SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND = 3, 88 | SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED = 4, 89 | SDL_MESSAGEBOX_COLOR_MAX = 5 90 | } 91 | 92 | export const c__SA_SDL_MessageBoxButtonData = Struct({ 93 | flags: Uint32, 94 | buttonid: int32, 95 | text: string, 96 | }); 97 | 98 | export const SDL_MessageBoxButtonData = c__SA_SDL_MessageBoxButtonData; 99 | 100 | export const SDL_MessageBoxColor = Struct({ 101 | r: Uint8, 102 | g: Uint8, 103 | b: Uint8, 104 | }); 105 | 106 | export const SDL_MessageBoxColorScheme_FI_colors_arr = ArrayType(SDL_MessageBoxColor, 5); 107 | 108 | export const SDL_MessageBoxColorScheme = exports.c__SA_SDL_MessageBoxColorScheme = Struct({ 109 | colors: SDL_MessageBoxColorScheme_FI_colors_arr, 110 | }); 111 | 112 | export const SDL_MessageBoxButtonData_ptr = ref.refType(SDL_MessageBoxButtonData); 113 | 114 | export const SDL_MessageBoxColorScheme_ptr = ref.refType(SDL_MessageBoxColorScheme); 115 | 116 | export const c__SA_SDL_MessageBoxData = Struct({ 117 | flags: Uint32, 118 | window: SDL_Window_ptr, 119 | title: string, 120 | message: string, 121 | numbuttons: int32, 122 | buttons: SDL_MessageBoxButtonData_ptr, 123 | colorScheme: SDL_MessageBoxColorScheme_ptr, 124 | }); 125 | 126 | export const SDL_MessageBoxData = exports.SDL_MessageBoxData = c__SA_SDL_MessageBoxData; 127 | 128 | export const SDL_MessageBoxData_ptr = exports.SDL_MessageBoxData_ptr = ref.refType(SDL_MessageBoxData); 129 | 130 | loadLibrary({ 131 | SDL_ShowMessageBox: [int32, [SDL_MessageBoxData_ptr, int32_ptr]], 132 | SDL_ShowSimpleMessageBox: [int32, [Uint32, string, string, SDL_Window_ptr]], 133 | }, SDL); 134 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-mouse.ts: -------------------------------------------------------------------------------- 1 | import {SDL_Window_ptr} from './sdl-video'; 2 | import {int32, int32_ptr, uint32, Uint32, Uint8_ptr, voit} from './types'; 3 | import {loadLibrary} from './lib-loader'; 4 | import {SDL_Surface_ptr} from './sdl-surface'; 5 | 6 | const ref = require('ref-napi'); 7 | 8 | const SDL = {} as any; 9 | 10 | export enum SDL_SystemCursor { 11 | SDL_SYSTEM_CURSOR_ARROW = 0, 12 | SDL_SYSTEM_CURSOR_IBEAM = 1, 13 | SDL_SYSTEM_CURSOR_WAIT = 2, 14 | SDL_SYSTEM_CURSOR_CROSSHAIR = 3, 15 | SDL_SYSTEM_CURSOR_WAITARROW = 4, 16 | SDL_SYSTEM_CURSOR_SIZENWSE = 5, 17 | SDL_SYSTEM_CURSOR_SIZENESW = 6, 18 | SDL_SYSTEM_CURSOR_SIZEWE = 7, 19 | SDL_SYSTEM_CURSOR_SIZENS = 8, 20 | SDL_SYSTEM_CURSOR_SIZEALL = 9, 21 | SDL_SYSTEM_CURSOR_NO = 10, 22 | SDL_SYSTEM_CURSOR_HAND = 11, 23 | SDL_NUM_SYSTEM_CURSORS = 12 24 | } 25 | 26 | export enum SDL_MouseWheelDirection { 27 | SDL_MOUSEWHEEL_NORMAL = 0, 28 | SDL_MOUSEWHEEL_FLIPPED = 1 29 | } 30 | 31 | export const SDL_Cursor = voit; 32 | export const SDL_Cursor_ptr = ref.refType(SDL_Cursor); 33 | 34 | export function SDL_GetGlobalMouseState(): { x: number, y: number } { 35 | const screenX = ref.alloc('int'); 36 | const screenY = ref.alloc('int'); 37 | 38 | SDL.SDL_GetGlobalMouseState(screenX, screenY); 39 | 40 | return { 41 | x: screenX.deref(), 42 | y: screenY.deref() 43 | }; 44 | 45 | 46 | } 47 | 48 | loadLibrary({ 49 | SDL_GetMouseFocus: [SDL_Window_ptr, []], 50 | SDL_GetMouseState: [Uint32, [int32_ptr, int32_ptr]], 51 | SDL_GetGlobalMouseState: [Uint32, [int32_ptr, int32_ptr]], 52 | SDL_GetRelativeMouseState: [Uint32, [int32_ptr, int32_ptr]], 53 | SDL_WarpMouseInWindow: [voit, [SDL_Window_ptr, int32, int32]], 54 | SDL_WarpMouseGlobal: [int32, [int32, int32]], 55 | SDL_SetRelativeMouseMode: [int32, [uint32]], 56 | SDL_CaptureMouse: [int32, [uint32]], 57 | SDL_GetRelativeMouseMode: [uint32, []], 58 | SDL_CreateCursor: [SDL_Cursor_ptr, [Uint8_ptr, Uint8_ptr, int32, int32, int32, int32]], 59 | SDL_CreateColorCursor: [SDL_Cursor_ptr, [SDL_Surface_ptr, int32, int32]], 60 | SDL_CreateSystemCursor: [SDL_Cursor_ptr, [uint32]], 61 | SDL_SetCursor: [voit, [SDL_Cursor_ptr]], 62 | SDL_GetCursor: [SDL_Cursor_ptr, []], 63 | SDL_GetDefaultCursor: [SDL_Cursor_ptr, []], 64 | SDL_FreeCursor: [voit, [SDL_Cursor_ptr]], 65 | SDL_ShowCursor: [int32, [int32]], 66 | }, SDL); 67 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-pixels.ts: -------------------------------------------------------------------------------- 1 | import { 2 | float, 3 | int32, 4 | int32_ptr, 5 | string, 6 | Uint16_ptr, 7 | uint32, 8 | Uint32, 9 | Uint32_ptr, 10 | Uint8, Uint8_ptr, 11 | voit, 12 | voit_ptr 13 | } from './types'; 14 | import {loadLibrary} from './lib-loader'; 15 | 16 | const ref = require('ref-napi'); 17 | const ArrayType = require('ref-array-di')(ref); 18 | const Struct = require('ref-struct-di')(ref); 19 | 20 | const SDL = {} as any; 21 | 22 | export function SDL_MasksToPixelFormatEnum(bpp: number, rmask: number, gmask: number, bmask: number, amask: number): number { 23 | return SDL.SDL_MasksToPixelFormatEnum(bpp, rmask, gmask, bmask, amask); 24 | } 25 | 26 | enum SDL_pixels_emum { 27 | SDL_PIXELTYPE_UNKNOWN = 0, 28 | SDL_PIXELTYPE_INDEX1 = 1, 29 | SDL_PIXELTYPE_INDEX4 = 2, 30 | SDL_PIXELTYPE_INDEX8 = 3, 31 | SDL_PIXELTYPE_PACKED8 = 4, 32 | SDL_PIXELTYPE_PACKED16 = 5, 33 | SDL_PIXELTYPE_PACKED32 = 6, 34 | SDL_PIXELTYPE_ARRAYU8 = 7, 35 | SDL_PIXELTYPE_ARRAYU16 = 8, 36 | SDL_PIXELTYPE_ARRAYU32 = 9, 37 | SDL_PIXELTYPE_ARRAYF16 = 10, 38 | SDL_PIXELTYPE_ARRAYF32 = 11 39 | } 40 | 41 | export const SDL_Color = Struct({ 42 | r: Uint8, 43 | g: Uint8, 44 | b: Uint8, 45 | a: Uint8, 46 | }); 47 | 48 | export const SDL_Color_ptr = ref.refType(SDL_Color); 49 | 50 | export const SDL_Palette = Struct({ 51 | ncolors: int32, 52 | colors: SDL_Color_ptr, 53 | version: Uint32, 54 | refcount: int32, 55 | }); 56 | 57 | export const SDL_Palette_ptr = ref.refType(SDL_Palette); 58 | 59 | export const SDL_PixelFormat_FI_padding_arr = ArrayType(Uint8, 2); 60 | 61 | export const SDL_PixelFormat = Struct({ 62 | format: Uint32, 63 | palette: SDL_Palette_ptr, 64 | BitsPerPixel: Uint8, 65 | BytesPerPixel: Uint8, 66 | padding: SDL_PixelFormat_FI_padding_arr, 67 | Rmask: Uint32, 68 | Gmask: Uint32, 69 | Bmask: Uint32, 70 | Amask: Uint32, 71 | Rloss: Uint8, 72 | Gloss: Uint8, 73 | Bloss: Uint8, 74 | Aloss: Uint8, 75 | Rshift: Uint8, 76 | Gshift: Uint8, 77 | Bshift: Uint8, 78 | Ashift: Uint8, 79 | refcount: int32, 80 | next: voit_ptr, 81 | }); 82 | 83 | export const SDL_PixelFormat_ptr = ref.refType(SDL_PixelFormat); 84 | 85 | 86 | loadLibrary({ 87 | SDL_GetPixelFormatName: [string, [Uint32]], 88 | SDL_PixelFormatEnumToMasks: [uint32, [Uint32, int32_ptr, Uint32_ptr, Uint32_ptr, Uint32_ptr, Uint32_ptr]], 89 | SDL_MasksToPixelFormatEnum: [Uint32, [int32, Uint32, Uint32, Uint32, Uint32]], 90 | SDL_AllocFormat: [SDL_PixelFormat_ptr, [Uint32]], 91 | SDL_FreeFormat: [voit, [SDL_PixelFormat_ptr]], 92 | SDL_AllocPalette: [SDL_Palette_ptr, [int32]], 93 | SDL_SetPixelFormatPalette: [int32, [SDL_PixelFormat_ptr, SDL_Palette_ptr]], 94 | SDL_SetPaletteColors: [int32, [SDL_Palette_ptr, SDL_Color_ptr, int32, int32]], 95 | SDL_FreePalette: [voit, [SDL_Palette_ptr]], 96 | SDL_MapRGB: [Uint32, [SDL_PixelFormat_ptr, Uint8, Uint8, Uint8]], 97 | SDL_MapRGBA: [Uint32, [SDL_PixelFormat_ptr, Uint8, Uint8, Uint8, Uint8]], 98 | SDL_GetRGB: [voit, [Uint32, SDL_PixelFormat_ptr, Uint8_ptr, Uint8_ptr, Uint8_ptr]], 99 | SDL_GetRGBA: [voit, [Uint32, SDL_PixelFormat_ptr, Uint8_ptr, Uint8_ptr, Uint8_ptr, Uint8_ptr]], 100 | SDL_CalculateGammaRamp: [voit, [float, Uint16_ptr]] 101 | }, SDL); 102 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-power.ts: -------------------------------------------------------------------------------- 1 | import {int32_ptr, uint32} from './types'; 2 | import {loadLibrary} from './lib-loader'; 3 | 4 | const SDL = {} as any; 5 | 6 | export enum SDL_PowerState { 7 | SDL_POWERSTATE_UNKNOWN = 0, 8 | SDL_POWERSTATE_ON_BATTERY = 1, 9 | SDL_POWERSTATE_NO_BATTERY = 2, 10 | SDL_POWERSTATE_CHARGING = 3, 11 | SDL_POWERSTATE_CHARGED = 4 12 | } 13 | 14 | loadLibrary({ 15 | SDL_GetPowerInfo: [uint32, [int32_ptr, int32_ptr]] 16 | }, SDL); 17 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-rect.ts: -------------------------------------------------------------------------------- 1 | import {Rect} from '../shape/rect'; 2 | import {int32} from './types'; 3 | 4 | const ref = require('ref-napi'); 5 | const Struct = require('ref-struct-di')(ref); 6 | 7 | export const SDL_Point = exports.SDL_Point = Struct({ 8 | x: int32, 9 | y: int32, 10 | }); 11 | export const SDL_Rect = Struct({ 12 | x: int32, 13 | y: int32, 14 | w: int32, 15 | h: int32, 16 | }); 17 | 18 | export const SDL_Rect_ptr = ref.refType(SDL_Rect); 19 | 20 | export const SDL_Point_ptr = ref.refType(SDL_Point); 21 | 22 | export function createSDL_RectPtr(rect: Rect): any { 23 | return SDL_Rect(arraylike2obj(rect, 'x,y,w,h')).ref(); 24 | } 25 | 26 | function arraylike2obj(obj: any = {}, keys: any = '') { 27 | keys = keys.split(','); 28 | const ret = {} as any; 29 | 30 | keys.forEach((value: any, index: any) => { 31 | value = value.trim(); 32 | ret[value] = (value in obj) ? obj[value] : (obj[index] || 0); 33 | }); 34 | 35 | return ret; 36 | } 37 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-render.ts: -------------------------------------------------------------------------------- 1 | import {Rgba} from '../color/rgba'; 2 | import {createSDL_RectPtr, SDL_Point_ptr, SDL_Rect_ptr} from './sdl-rect'; 3 | import {Rect} from '../shape/rect'; 4 | import {loadLibrary} from './lib-loader'; 5 | import { 6 | bool, 7 | double, 8 | float, 9 | float_ptr, int32, 10 | int32_ptr, string, uint32, Uint32, 11 | uint32_ptr, 12 | Uint32_ptr, 13 | Uint8, 14 | Uint8_ptr, voit, 15 | voit_ptr, 16 | voit_ptr_ptr 17 | } from './types'; 18 | import {SDL_Surface_ptr} from './sdl-surface'; 19 | import {SDL_Window_ptr} from './sdl-video'; 20 | 21 | 22 | const FFI = require('ffi-napi'); 23 | const ref = require('ref-napi'); 24 | const ArrayType = require('ref-array-di')(ref); 25 | const Struct = require('ref-struct-di')(ref); 26 | const Union = require('ref-union-di')(ref); 27 | 28 | const SDL = {} as any; 29 | 30 | export enum SDL_RendererFlags { 31 | SDL_RENDERER_SOFTWARE = 0x00000001, 32 | SDL_RENDERER_ACCELERATED = 0x00000002, 33 | SDL_RENDERER_PRESENTVSYNC = 0x00000004, 34 | SDL_RENDERER_TARGETTEXTURE = 0x00000008 35 | } 36 | 37 | export enum SDL_BlendMode { 38 | SDL_BLENDMODE_NONE = 0, 39 | SDL_BLENDMODE_BLEND = 1, 40 | SDL_BLENDMODE_ADD = 2, 41 | SDL_BLENDMODE_MOD = 4 42 | } 43 | 44 | export const SDL_TEXTUREACCESS_STATIC = 0x0; 45 | export const SDL_TEXTUREACCESS_STREAMING = 0x1; 46 | export const SDL_TEXTUREACCESS_TARGET = 0x2; 47 | 48 | // SDL_SetTextureBlendMode( mTexture, blending ); 49 | export function SDL_SetTextureBlendMode(texture: any, blendMode: number) { 50 | return SDL.SDL_SetTextureBlendMode(texture, blendMode); 51 | } 52 | 53 | export function SDL_CreateSoftwareRenderer(surfacePtr: any) { 54 | return SDL.SDL_CreateSoftwareRenderer(surfacePtr); 55 | } 56 | 57 | export function SDL_RenderCopy(rendererPtr: any, texturePtr: any, src: Rect, dest: Rect): number { 58 | if (src) { 59 | src = createSDL_RectPtr(src); 60 | } 61 | 62 | if (dest) { 63 | dest = createSDL_RectPtr(dest); 64 | } 65 | 66 | return SDL.SDL_RenderCopy(rendererPtr, texturePtr, src, dest); 67 | } 68 | 69 | export function SDL_CreateRenderer(windowPtr: any, driver: number, flags: number): any { 70 | const renderPtr = SDL.SDL_CreateRenderer(windowPtr, driver, flags); 71 | return renderPtr; 72 | } 73 | 74 | export function SDL_SetRenderTarget(rendererPtr: any, texturePtr: any) { 75 | return SDL.SDL_SetRenderTarget(rendererPtr, texturePtr); 76 | } 77 | 78 | export function SDL_GetRenderTarget(rendererPtr: any): any { 79 | return SDL.SDL_GetRenderTarget(rendererPtr); 80 | } 81 | 82 | export function SDL_GetRenderDrawColor(rendererPtr: any, rgba: Rgba): Rgba { 83 | const r = ref.alloc('uint8'); 84 | const g = ref.alloc('uint8'); 85 | const b = ref.alloc('uint8'); 86 | const a = ref.alloc('uint8'); 87 | 88 | SDL.SDL_GetRenderDrawColor(rendererPtr, r, g, b, a); 89 | 90 | rgba.r = r.deref(); 91 | rgba.g = g.deref(); 92 | rgba.b = b.deref(); 93 | rgba.a = a.deref(); 94 | 95 | 96 | return rgba; 97 | } 98 | 99 | export function SDL_SetRenderDrawColor(rendererPtr: any, r: number, g: number, b: number, a: number): number { 100 | return SDL.SDL_SetRenderDrawColor(rendererPtr, r, g, b, a); 101 | } 102 | 103 | export function SDL_RenderPresent(rendererPtr: any) { 104 | SDL.SDL_RenderPresent(rendererPtr); 105 | } 106 | 107 | export function SDL_DestroyRenderer(rendererPtr: any) { 108 | SDL.SDL_DestroyRenderer(rendererPtr); 109 | } 110 | 111 | export function SDL_RenderClear(rendererPtr: any): number { 112 | return SDL.SDL_RenderClear(rendererPtr); 113 | } 114 | 115 | export function SDL_DestroyTexture(texturePtr: any): number { 116 | return SDL.SDL_DestroyTexture(texturePtr); 117 | } 118 | 119 | export function SDL_RenderGetLogicalSize(rendererPtr: any): { w: number, h: number } { 120 | const w = ref.alloc('int'); 121 | const h = ref.alloc('int'); 122 | SDL.SDL_RenderGetLogicalSize(rendererPtr, w, h); 123 | 124 | return {w: w.deref(), h: h.deref()}; 125 | } 126 | 127 | export function SDL_GetRendererOutputSize(rendererPtr: any): { w: number, h: number } { 128 | const w = ref.alloc('int'); 129 | const h = ref.alloc('int'); 130 | SDL.SDL_GetRendererOutputSize(rendererPtr, w, h); 131 | 132 | return {w: w.deref(), h: h.deref()}; 133 | } 134 | 135 | export function SDL_RenderGetIntegerScale(rendererPtr: any): boolean { 136 | return !!SDL.SDL_RenderGetIntegerScale(rendererPtr); 137 | } 138 | 139 | export function SDL_RenderGetScale(renderPtr: any): { x: number, y: number } { 140 | const x = ref.alloc('float'); 141 | const y = ref.alloc('float'); 142 | SDL.SDL_RenderGetScale(renderPtr, x, y); 143 | 144 | return {x: x.deref(), y: y.deref()}; 145 | } 146 | 147 | export function SDL_RenderSetScale(renderPtr: any, x: number, y: number) { 148 | return SDL.SDL_RenderSetScale(renderPtr, x, y); 149 | } 150 | 151 | export function SDL_RenderSetLogicalSize(renderPtr: any, w: number, h: number) { 152 | return SDL.SDL_RenderSetLogicalSize(renderPtr, w, h); 153 | } 154 | 155 | export function SDL_UpdateTexture(texturePtr: any, rect: Rect, pixels: Buffer, pitch: number) { 156 | const rectPtr = (rect) ? createSDL_RectPtr(rect) : null; 157 | return SDL.SDL_UpdateTexture(texturePtr, rectPtr, pixels, pitch); 158 | } 159 | 160 | export function SDL_QueryTexture(texturePtr: any): { format: number, access: number, x: number, y: number, w: number, h: number } { 161 | const format = ref.alloc('uint32'); 162 | const access = ref.alloc('int'); 163 | const w = ref.alloc('int'); 164 | const h = ref.alloc('int'); 165 | 166 | SDL.SDL_QueryTexture(texturePtr, format, access, w, h); 167 | 168 | return { 169 | format: format.deref(), 170 | access: access.deref(), 171 | x: 0, 172 | y: 0, 173 | w: w.deref(), 174 | h: h.deref() 175 | }; 176 | } 177 | 178 | export function SDL_CreateTexture(rendererPtr: any, format: number, access: number, w: number, h: number) { 179 | return SDL.SDL_CreateTexture(rendererPtr, format, +access, +w, +h); 180 | } 181 | 182 | export const SDL_RendererInfo = Struct({ 183 | name: string, 184 | flags: Uint32, 185 | num_texture_formats: Uint32, 186 | texture_formats: ArrayType(Uint32, 16), 187 | max_texture_width: int32, 188 | max_texture_height: int32, 189 | }); 190 | 191 | export const SDL_Renderer = voit; 192 | 193 | export const SDL_Texture = voit; 194 | 195 | export const SDL_RendererInfo_ptr = ref.refType(SDL_RendererInfo); 196 | 197 | export const SDL_Window_ptr_ptr = ref.refType(SDL_Window_ptr); 198 | 199 | export const SDL_Renderer_ptr = ref.refType(SDL_Renderer); 200 | 201 | export const SDL_Renderer_ptr_ptr = ref.refType(SDL_Renderer_ptr); 202 | 203 | export const SDL_Texture_ptr = ref.refType(SDL_Texture); 204 | 205 | loadLibrary({ 206 | SDL_GetNumRenderDrivers: [int32, []], 207 | SDL_GetRenderDriverInfo: [int32, [int32, SDL_RendererInfo_ptr]], 208 | SDL_CreateWindowAndRenderer: [int32, [int32, int32, Uint32, SDL_Window_ptr_ptr, SDL_Renderer_ptr_ptr]], 209 | SDL_CreateRenderer: [SDL_Renderer_ptr, [SDL_Window_ptr, int32, Uint32]], 210 | SDL_CreateSoftwareRenderer: [SDL_Renderer_ptr, [SDL_Surface_ptr]], 211 | SDL_GetRenderer: [SDL_Renderer_ptr, [SDL_Window_ptr]], 212 | SDL_GetRendererInfo: [int32, [SDL_Renderer_ptr, SDL_RendererInfo_ptr]], 213 | SDL_RenderGetIntegerScale: [bool, [SDL_Renderer_ptr]], 214 | SDL_GetRendererOutputSize: [int32, [SDL_Renderer_ptr, int32_ptr, int32_ptr]], 215 | SDL_CreateTexture: [SDL_Texture_ptr, [SDL_Renderer_ptr, Uint32, int32, int32, int32]], 216 | SDL_CreateTextureFromSurface: [SDL_Texture_ptr, [SDL_Renderer_ptr, SDL_Surface_ptr]], 217 | SDL_QueryTexture: [int32, [SDL_Texture_ptr, Uint32_ptr, int32_ptr, int32_ptr, int32_ptr]], 218 | SDL_SetTextureColorMod: [int32, [SDL_Texture_ptr, Uint8, Uint8, Uint8]], 219 | SDL_GetTextureColorMod: [int32, [SDL_Texture_ptr, Uint8_ptr, Uint8_ptr, Uint8_ptr]], 220 | SDL_SetTextureAlphaMod: [int32, [SDL_Texture_ptr, Uint8]], 221 | SDL_GetTextureAlphaMod: [int32, [SDL_Texture_ptr, Uint8_ptr]], 222 | SDL_SetTextureBlendMode: [int32, [SDL_Texture_ptr, uint32]], 223 | SDL_GetTextureBlendMode: [int32, [SDL_Texture_ptr, uint32_ptr]], 224 | SDL_UpdateTexture: [int32, [SDL_Texture_ptr, SDL_Rect_ptr, voit_ptr, int32]], 225 | SDL_UpdateYUVTexture: [int32, [SDL_Texture_ptr, SDL_Rect_ptr, Uint8_ptr, int32, Uint8_ptr, int32, Uint8_ptr, int32]], 226 | SDL_LockTexture: [int32, [SDL_Texture_ptr, SDL_Rect_ptr, voit_ptr_ptr, int32_ptr]], 227 | SDL_UnlockTexture: [voit, [SDL_Texture_ptr]], 228 | SDL_RenderTargetSupported: [uint32, [SDL_Renderer_ptr]], 229 | SDL_SetRenderTarget: [int32, [SDL_Renderer_ptr, SDL_Texture_ptr]], 230 | SDL_GetRenderTarget: [SDL_Texture_ptr, [SDL_Renderer_ptr]], 231 | SDL_RenderSetLogicalSize: [int32, [SDL_Renderer_ptr, int32, int32]], 232 | SDL_RenderGetLogicalSize: [voit, [SDL_Renderer_ptr, int32_ptr, int32_ptr]], 233 | SDL_RenderSetViewport: [int32, [SDL_Renderer_ptr, SDL_Rect_ptr]], 234 | SDL_RenderGetViewport: [voit, [SDL_Renderer_ptr, SDL_Rect_ptr]], 235 | SDL_RenderSetClipRect: [int32, [SDL_Renderer_ptr, SDL_Rect_ptr]], 236 | SDL_RenderGetClipRect: [voit, [SDL_Renderer_ptr, SDL_Rect_ptr]], 237 | SDL_RenderIsClipEnabled: [uint32, [SDL_Renderer_ptr]], 238 | SDL_RenderSetScale: [int32, [SDL_Renderer_ptr, float, float]], 239 | SDL_RenderGetScale: [voit, [SDL_Renderer_ptr, float_ptr, float_ptr]], 240 | SDL_SetRenderDrawColor: [int32, [SDL_Renderer_ptr, Uint8, Uint8, Uint8, Uint8]], 241 | SDL_GetRenderDrawColor: [int32, [SDL_Renderer_ptr, Uint8_ptr, Uint8_ptr, Uint8_ptr, Uint8_ptr]], 242 | SDL_SetRenderDrawBlendMode: [int32, [SDL_Renderer_ptr, uint32]], 243 | SDL_GetRenderDrawBlendMode: [int32, [SDL_Renderer_ptr, uint32_ptr]], 244 | SDL_RenderClear: [int32, [SDL_Renderer_ptr]], 245 | SDL_RenderDrawPoint: [int32, [SDL_Renderer_ptr, int32, int32]], 246 | SDL_RenderDrawPoints: [int32, [SDL_Renderer_ptr, SDL_Point_ptr, int32]], 247 | SDL_RenderDrawLine: [int32, [SDL_Renderer_ptr, int32, int32, int32, int32]], 248 | SDL_RenderDrawLines: [int32, [SDL_Renderer_ptr, SDL_Point_ptr, int32]], 249 | SDL_RenderDrawRect: [int32, [SDL_Renderer_ptr, SDL_Rect_ptr]], 250 | SDL_RenderDrawRects: [int32, [SDL_Renderer_ptr, SDL_Rect_ptr, int32]], 251 | SDL_RenderFillRect: [int32, [SDL_Renderer_ptr, SDL_Rect_ptr]], 252 | SDL_RenderFillRects: [int32, [SDL_Renderer_ptr, SDL_Rect_ptr, int32]], 253 | SDL_RenderCopy: [int32, [SDL_Renderer_ptr, SDL_Texture_ptr, SDL_Rect_ptr, SDL_Rect_ptr]], 254 | SDL_RenderCopyEx: [int32, [SDL_Renderer_ptr, SDL_Texture_ptr, SDL_Rect_ptr, SDL_Rect_ptr, double, SDL_Point_ptr, uint32]], 255 | SDL_RenderReadPixels: [int32, [SDL_Renderer_ptr, SDL_Rect_ptr, Uint32, voit_ptr, int32]], 256 | SDL_RenderPresent: [voit, [SDL_Renderer_ptr]], 257 | SDL_DestroyTexture: [voit, [SDL_Texture_ptr]], 258 | SDL_DestroyRenderer: [voit, [SDL_Renderer_ptr]], 259 | SDL_GL_BindTexture: [int32, [SDL_Texture_ptr, float_ptr, float_ptr]], 260 | SDL_GL_UnbindTexture: [int32, [SDL_Texture_ptr]], 261 | }, SDL); 262 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-rwops.ts: -------------------------------------------------------------------------------- 1 | import {loadLibrary} from './lib-loader'; 2 | import {int32, size_t, string, Uint16, uint32, Uint32, Uint64, Uint8, Uint8_ptr, voit, voit_ptr} from './types'; 3 | 4 | const ref = require('ref-napi'); 5 | const Struct = require('ref-struct-di')(ref); 6 | const Union = require('ref-union-di')(ref); 7 | 8 | const SDL = {} as any; 9 | 10 | export const Mem_SDL_Rwops = Struct({ 11 | base: Uint8_ptr, 12 | here: Uint8_ptr, 13 | stop: Uint8_ptr, 14 | }); 15 | 16 | export const Unknown_SDL_Rwops = Struct({ 17 | data1: voit_ptr, 18 | data2: voit_ptr, 19 | }); 20 | 21 | export const SDL_RWops_U_SDL_rwops_h_3164 = Union({ 22 | mem: Mem_SDL_Rwops, 23 | unknown: Unknown_SDL_Rwops 24 | }); 25 | 26 | export const SDL_RWops = Struct({ 27 | size: voit_ptr, 28 | seek: voit_ptr, 29 | read: voit_ptr, 30 | write: voit_ptr, 31 | close: voit_ptr, 32 | type: Uint32, 33 | hidden: SDL_RWops_U_SDL_rwops_h_3164, 34 | }); 35 | 36 | export const SDL_RWops_ptr = ref.refType(SDL_RWops); 37 | 38 | loadLibrary({ 39 | SDL_RWFromFile: [SDL_RWops_ptr, [string, string]], 40 | SDL_RWFromFP: [SDL_RWops_ptr, [voit_ptr, uint32]], 41 | SDL_RWFromMem: [SDL_RWops_ptr, [voit_ptr, int32]], 42 | SDL_RWFromConstMem: [SDL_RWops_ptr, [voit_ptr, int32]], 43 | SDL_AllocRW: [SDL_RWops_ptr, []], 44 | SDL_FreeRW: [voit, [SDL_RWops_ptr]], 45 | SDL_ReadU8: [Uint8, [SDL_RWops_ptr]], 46 | SDL_ReadLE16: [Uint16, [SDL_RWops_ptr]], 47 | SDL_ReadBE16: [Uint16, [SDL_RWops_ptr]], 48 | SDL_ReadLE32: [Uint32, [SDL_RWops_ptr]], 49 | SDL_ReadBE32: [Uint32, [SDL_RWops_ptr]], 50 | SDL_ReadLE64: [Uint64, [SDL_RWops_ptr]], 51 | SDL_ReadBE64: [Uint64, [SDL_RWops_ptr]], 52 | SDL_WriteU8: [size_t, [SDL_RWops_ptr, Uint8]], 53 | SDL_WriteLE16: [size_t, [SDL_RWops_ptr, Uint16]], 54 | SDL_WriteBE16: [size_t, [SDL_RWops_ptr, Uint16]], 55 | SDL_WriteLE32: [size_t, [SDL_RWops_ptr, Uint32]], 56 | SDL_WriteBE32: [size_t, [SDL_RWops_ptr, Uint32]], 57 | SDL_WriteLE64: [size_t, [SDL_RWops_ptr, Uint64]], 58 | SDL_WriteBE64: [size_t, [SDL_RWops_ptr, Uint64]], 59 | }, SDL); 60 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-surface.ts: -------------------------------------------------------------------------------- 1 | import {Uint32_ptr, int32, uint32, Uint32, uint32_ptr, Uint8, Uint8_ptr, voit, voit_ptr} from './types'; 2 | import {loadLibrary} from './lib-loader'; 3 | import {SDL_Palette_ptr, SDL_PixelFormat_ptr} from './sdl-pixels'; 4 | import {SDL_Rect, SDL_Rect_ptr} from './sdl-rect'; 5 | 6 | const FFI = require('ffi-napi'); 7 | const ref = require('ref-napi'); 8 | const Struct = require('ref-struct-di')(ref); 9 | 10 | const SDL = {} as any; 11 | 12 | const SDL_Texture = voit; 13 | const SDL_Texture_ptr = ref.refType(SDL_Texture); 14 | const SDL_Renderer = voit; 15 | const SDL_Renderer_ptr = ref.refType(SDL_Renderer); 16 | 17 | export const SDL_BlitMap_ptr = ref.refType(voit); 18 | export const SDL_Surface = Struct({ 19 | flags: Uint32, 20 | format: SDL_PixelFormat_ptr, 21 | w: int32, 22 | h: int32, 23 | pitch: int32, 24 | pixels: voit_ptr, 25 | userdata: voit_ptr, 26 | locked: int32, 27 | lock_data: voit_ptr, 28 | clip_rect: SDL_Rect, 29 | map: SDL_BlitMap_ptr, 30 | refcount: int32, 31 | }); 32 | 33 | export const SDL_Surface_ptr = ref.refType(SDL_Surface); 34 | export const SDL_blit = FFI.Function(int32, [SDL_Surface_ptr, SDL_Rect_ptr, SDL_Surface_ptr, SDL_Rect_ptr]); 35 | 36 | export function SDL_CreateRGBSurfaceFrom(pixels: any, width: number, height: number, depth: number, pitch: number, Rmask: number, Gmask: number, Bmask: number, Amask: number) { 37 | return SDL.SDL_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask); 38 | } 39 | 40 | export function SDL_CreateTextureFromSurface(rendererPtr: any, sdlSurfacePtr: any) { 41 | return SDL.SDL_CreateTextureFromSurface(rendererPtr, sdlSurfacePtr); 42 | } 43 | 44 | export function SDL_FreeSurface(surfacePtr: any) { 45 | SDL.SDL_FreeSurface(surfacePtr); 46 | } 47 | 48 | loadLibrary({ 49 | SDL_CreateTextureFromSurface: [SDL_Texture_ptr, [SDL_Renderer_ptr, SDL_Surface_ptr]], 50 | SDL_CreateRGBSurface: [SDL_Surface_ptr, [Uint32, int32, int32, int32, Uint32, Uint32, Uint32, Uint32]], 51 | SDL_CreateRGBSurfaceFrom: [SDL_Surface_ptr, [voit_ptr, int32, int32, int32, int32, Uint32, Uint32, Uint32, Uint32]], 52 | SDL_FreeSurface: [voit, [SDL_Surface_ptr]], 53 | SDL_SetSurfacePalette: [int32, [SDL_Surface_ptr, SDL_Palette_ptr]], 54 | SDL_LockSurface: [int32, [SDL_Surface_ptr]], 55 | SDL_UnlockSurface: [voit, [SDL_Surface_ptr]], 56 | // SDL_LoadBMP_RW: [SDL_Surface_ptr, [SDL_RWops_ptr, int32]], 57 | // SDL_SaveBMP_RW: [int32, [SDL_Surface_ptr, SDL_RWops_ptr, int32]], 58 | SDL_SetSurfaceRLE: [int32, [SDL_Surface_ptr, int32]], 59 | SDL_SetColorKey: [int32, [SDL_Surface_ptr, int32, Uint32]], 60 | SDL_GetColorKey: [int32, [SDL_Surface_ptr, Uint32_ptr]], 61 | SDL_SetSurfaceColorMod: [int32, [SDL_Surface_ptr, Uint8, Uint8, Uint8]], 62 | SDL_GetSurfaceColorMod: [int32, [SDL_Surface_ptr, Uint8_ptr, Uint8_ptr, Uint8_ptr]], 63 | SDL_SetSurfaceAlphaMod: [int32, [SDL_Surface_ptr, Uint8]], 64 | SDL_GetSurfaceAlphaMod: [int32, [SDL_Surface_ptr, Uint8_ptr]], 65 | SDL_SetSurfaceBlendMode: [int32, [SDL_Surface_ptr, uint32]], 66 | SDL_GetSurfaceBlendMode: [int32, [SDL_Surface_ptr, uint32_ptr]], 67 | SDL_SetClipRect: [uint32, [SDL_Surface_ptr, SDL_Rect_ptr]], 68 | SDL_GetClipRect: [voit, [SDL_Surface_ptr, SDL_Rect_ptr]], 69 | SDL_ConvertSurface: [SDL_Surface_ptr, [SDL_Surface_ptr, SDL_PixelFormat_ptr, Uint32]], 70 | SDL_ConvertSurfaceFormat: [SDL_Surface_ptr, [SDL_Surface_ptr, Uint32, Uint32]], 71 | SDL_ConvertPixels: [int32, [int32, int32, Uint32, voit_ptr, int32, Uint32, voit_ptr, int32]], 72 | SDL_FillRect: [int32, [SDL_Surface_ptr, SDL_Rect_ptr, Uint32]], 73 | SDL_FillRects: [int32, [SDL_Surface_ptr, SDL_Rect_ptr, int32, Uint32]], 74 | SDL_UpperBlit: [int32, [SDL_Surface_ptr, SDL_Rect_ptr, SDL_Surface_ptr, SDL_Rect_ptr]], 75 | SDL_LowerBlit: [int32, [SDL_Surface_ptr, SDL_Rect_ptr, SDL_Surface_ptr, SDL_Rect_ptr]], 76 | SDL_SoftStretch: [int32, [SDL_Surface_ptr, SDL_Rect_ptr, SDL_Surface_ptr, SDL_Rect_ptr]], 77 | SDL_UpperBlitScaled: [int32, [SDL_Surface_ptr, SDL_Rect_ptr, SDL_Surface_ptr, SDL_Rect_ptr]], 78 | SDL_LowerBlitScaled: [int32, [SDL_Surface_ptr, SDL_Rect_ptr, SDL_Surface_ptr, SDL_Rect_ptr]], 79 | }, SDL); 80 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-thread.ts: -------------------------------------------------------------------------------- 1 | import {int32, int32_ptr, string, uint32, ulong, voit, voit_ptr} from './types'; 2 | import {loadLibrary} from './lib-loader'; 3 | 4 | const FFI = require('ffi-napi'); 5 | const ref = require('ref-napi'); 6 | const ArrayType = require('ref-array-di')(ref); 7 | const Struct = require('ref-struct-di')(ref); 8 | const Union = require('ref-union-di')(ref); 9 | 10 | const SDL = {} as any; 11 | 12 | const SDL_threadID = ulong; 13 | const SDL_TLSID = uint32; 14 | const SDL_ThreadFunction = FFI.Function(int32, [voit_ptr]); 15 | 16 | export function SDL_DetachThread(threadPtr: any) { 17 | return SDL.SDL_DetachThread(threadPtr); 18 | } 19 | 20 | export function SDL_WaitThread(threadPtr: any) { 21 | return SDL.SDL_WaitThread(threadPtr, null); 22 | } 23 | 24 | export function SDL_CreateThread(threadFunction: any, threadName: string, data: any) { 25 | return SDL.SDL_CreateThread(threadFunction, threadName, data); 26 | } 27 | 28 | export function createThreadFunction(func: (data?: any) => number) { 29 | return SDL_ThreadFunction.toPointer(func); 30 | } 31 | 32 | loadLibrary({ 33 | SDL_CreateThread: [voit_ptr, [SDL_ThreadFunction, string, voit_ptr]], 34 | SDL_GetThreadName: [string, [voit_ptr]], 35 | SDL_ThreadID: [SDL_threadID, []], 36 | SDL_GetThreadID: [SDL_threadID, [voit_ptr]], 37 | SDL_SetThreadPriority: [int32, [uint32]], 38 | SDL_WaitThread: [voit, [voit_ptr, int32_ptr]], 39 | SDL_DetachThread: [voit, [voit_ptr]], 40 | SDL_TLSCreate: [SDL_TLSID, []], 41 | SDL_TLSGet: [voit_ptr, [SDL_TLSID]], 42 | SDL_TLSSet: [int32, [SDL_TLSID, voit_ptr, voit_ptr]], 43 | }, SDL); 44 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-timer.ts: -------------------------------------------------------------------------------- 1 | import {int32, Uint32, voit} from './types'; 2 | import {loadLibrary} from './lib-loader'; 3 | 4 | const SDL = {} as any; 5 | 6 | export const SDL_QUERY = -1; 7 | // export const SDL_IGNORE = 0; 8 | // export const SDL_DISABLE = 0; 9 | export const SDL_ENABLE = 1; 10 | 11 | export function SDL_GetTicks(): number { 12 | return SDL.SDL_GetTicks(); 13 | } 14 | 15 | export function SDL_Delay(ms: number): void { 16 | SDL.SDL_Delay(ms); 17 | } 18 | 19 | loadLibrary({ 20 | SDL_GetTicks: [int32, []], 21 | SDL_Delay: [voit, [Uint32]], 22 | }, SDL); 23 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-touch.ts: -------------------------------------------------------------------------------- 1 | import {float, int32, longlong} from './types'; 2 | import {loadLibrary} from './lib-loader'; 3 | 4 | const ref = require('ref-napi'); 5 | const Struct = require('ref-struct-di')(ref); 6 | const SDL = {} as any; 7 | 8 | 9 | export const SDL_TouchID = longlong; 10 | 11 | export const SDL_FingerID = longlong; 12 | 13 | export const SDL_Finger = Struct({ 14 | id: SDL_FingerID, 15 | x: float, 16 | y: float, 17 | pressure: float, 18 | }); 19 | 20 | export const SDL_Finger_ptr = ref.refType(SDL_Finger); 21 | 22 | loadLibrary({ 23 | SDL_GetNumTouchDevices: [int32, []], 24 | SDL_GetTouchDevice: [SDL_TouchID, [int32]], 25 | SDL_GetNumTouchFingers: [int32, [SDL_TouchID]], 26 | SDL_GetTouchFinger: [SDL_Finger_ptr, [SDL_TouchID, int32]], 27 | }, SDL); 28 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl-video.ts: -------------------------------------------------------------------------------- 1 | import {int32, int32_ptr, string, uchar, Uint16_ptr, uint32, Uint32, voit, voit_ptr} from './types'; 2 | import {SDL_Point_ptr, SDL_Rect_ptr} from './sdl-rect'; 3 | import {SDL_Surface_ptr} from './sdl-surface'; 4 | import {loadLibrary} from './lib-loader'; 5 | 6 | const FFI = require('ffi-napi'); 7 | const ref = require('ref-napi'); 8 | const Struct = require('ref-struct-di')(ref); 9 | 10 | const SDL = {} as any; 11 | 12 | //SDL_video.SDL_SetWindowMinimumSize(this.windowPtr, w, h); 13 | //SDL_video.SDL_SetWindowResizable(this.windowPtr, value); 14 | //SDL_video.SDL_SetWindowPosition(this.windowPtr, x, y); 15 | // return SDL_video.SDL_GetWindowID(this.windowPtr); 16 | 17 | export function SDL_GetWindowID(windowPtr: any): number { 18 | return SDL.SDL_GetWindowID(windowPtr); 19 | } 20 | 21 | export function SDL_HideWindow(windowPtr: any): void { 22 | SDL.SDL_HideWindow(windowPtr); 23 | } 24 | 25 | export function SDL_ShowWindow(windowPtr: any): void { 26 | SDL.SDL_ShowWindow(windowPtr); 27 | } 28 | 29 | export function SDL_GetWindowBordersSize(windowPtr: any): { top: number, right: number, bottom: number, left: number } { 30 | const top = ref.alloc('int'); 31 | const left = ref.alloc('int'); 32 | const bottom = ref.alloc('int'); 33 | const right = ref.alloc('int'); 34 | 35 | SDL.SDL_GetWindowBordersSize(windowPtr, top, left, bottom, right); 36 | 37 | return { 38 | top: top.deref(), 39 | right: right.deref(), 40 | bottom: bottom.deref(), 41 | left: left.deref(), 42 | }; 43 | } 44 | 45 | export function SDL_SetWindowBordered(windowPtr: any, border: boolean): void { 46 | SDL.SDL_SetWindowBordered(windowPtr, border); 47 | } 48 | 49 | 50 | export function SDL_GetWindowTitle(windowPtr: any): string { 51 | return SDL.SDL_GetWindowTitle(windowPtr); 52 | } 53 | 54 | export function SDL_SetWindowTitle(windowPtr: any, title: string): void { 55 | SDL.SDL_SetWindowTitle(windowPtr, title); 56 | } 57 | 58 | export function SDL_GetWindowPosition(windowPtr: any): { x: number, y: number } { 59 | const x = ref.alloc('int'); 60 | const y = ref.alloc('int'); 61 | 62 | SDL.SDL_GetWindowPosition(windowPtr, x, y); 63 | 64 | return { 65 | x: x.deref(), 66 | y: y.deref() 67 | }; 68 | } 69 | 70 | export function SDL_SetWindowPosition(windowPtr: any, x: number, y: number): void { 71 | SDL.SDL_SetWindowPosition(windowPtr, x, y); 72 | } 73 | 74 | 75 | export function SDL_SetWindowResizable(windowPtr: any, bool: boolean): void { 76 | SDL.SDL_SetWindowResizable(windowPtr, bool); 77 | } 78 | 79 | export function SDL_GetWindowMaximumSize(windowPtr: any): { w: number, h: number } { 80 | const w = ref.alloc('int'); 81 | const h = ref.alloc('int'); 82 | 83 | SDL.SDL_GetWindowMaximumSize(windowPtr, w, h); 84 | 85 | return { 86 | w: w.deref(), 87 | h: h.deref() 88 | }; 89 | } 90 | 91 | export function SDL_SetWindowMaximumSize(windowPtr: any, w: number, h: number): void { 92 | SDL.SDL_SetWindowMaximumSize(windowPtr, w, h); 93 | } 94 | 95 | export function SDL_GetWindowMinimumSize(windowPtr: any): { w: number, h: number } { 96 | const w = ref.alloc('int'); 97 | const h = ref.alloc('int'); 98 | 99 | SDL.SDL_GetWindowMinimumSize(windowPtr, w, h); 100 | 101 | return { 102 | w: w.deref(), 103 | h: h.deref() 104 | }; 105 | } 106 | 107 | export function SDL_UpdateWindowSurface(windowPtr: any): void { 108 | SDL.SDL_UpdateWindowSurface(windowPtr); 109 | } 110 | 111 | export function SDL_SetWindowMinimumSize(windowPtr: any, w: number, h: number): void { 112 | SDL.SDL_SetWindowMinimumSize(windowPtr, w, h); 113 | } 114 | 115 | export function SDL_GetWindowSize(windowPtr: any): { w: number, h: number } { 116 | const w = ref.alloc('int'); 117 | const h = ref.alloc('int'); 118 | 119 | SDL.SDL_GetWindowSize(windowPtr, w, h); 120 | 121 | return { 122 | w: w.deref(), 123 | h: h.deref() 124 | }; 125 | } 126 | 127 | export function SDL_SetWindowSize(windowPtr: any, w: number, h: number): void { 128 | SDL.SDL_SetWindowSize(windowPtr, w, h); 129 | } 130 | 131 | 132 | export function SDL_SetWindowFullscreen(windowPtr: any, mode: number): void { 133 | SDL.SDL_SetWindowFullscreen(windowPtr, mode); 134 | } 135 | 136 | export function SDL_GetWindowFlags(windowPtr: any): number { 137 | return SDL.SDL_GetWindowFlags(windowPtr); 138 | } 139 | 140 | export function SDL_MinimizeWindow(windowPtr: any): void { 141 | SDL.SDL_MinimizeWindow(windowPtr); 142 | } 143 | 144 | 145 | export function SDL_MaximizeWindow(windowPtr: any): void { 146 | SDL.SDL_MaximizeWindow(windowPtr); 147 | } 148 | 149 | export function SDL_SetWindowModalFor(windowPtr: any, parentWindowPtr: any): void { 150 | SDL.SDL_SetWindowModalFor(windowPtr, parentWindowPtr); 151 | } 152 | 153 | export function SDL_RestoreWindow(windowPtr: any): void { 154 | SDL.SDL_RestoreWindow(windowPtr); 155 | } 156 | 157 | export function SDL_DestroyWindow(windowPtr: any): void { 158 | SDL.SDL_DestroyWindow(windowPtr); 159 | } 160 | 161 | 162 | export function SDL_RaiseWindow(windowPtr: any): void { 163 | SDL.SDL_RaiseWindow(windowPtr); 164 | } 165 | 166 | export function SDL_SetWindowGrab(windowPtr: any, show: boolean): void { 167 | SDL.SDL_SetWindowGrab(windowPtr, show); 168 | } 169 | 170 | export function SDL_CreateWindow(title: string, x: number, y: number, w: number, h: number, flags: number): any { 171 | return SDL.SDL_CreateWindow(title, x, y, w, h, flags); 172 | } 173 | 174 | export enum SDL_WindowFlags { 175 | SDL_WINDOW_FULLSCREEN = 1, 176 | SDL_WINDOW_OPENGL = 2, 177 | SDL_WINDOW_SHOWN = 4, 178 | SDL_WINDOW_HIDDEN = 8, 179 | SDL_WINDOW_BORDERLESS = 16, 180 | SDL_WINDOW_RESIZABLE = 32, 181 | SDL_WINDOW_MINIMIZED = 64, 182 | SDL_WINDOW_MAXIMIZED = 128, 183 | SDL_WINDOW_INPUT_GRABBED = 256, 184 | SDL_WINDOW_INPUT_FOCUS = 512, 185 | SDL_WINDOW_MOUSE_FOCUS = 1024, 186 | SDL_WINDOW_FULLSCREEN_DESKTOP = 4097, 187 | SDL_WINDOW_FOREIGN = 2048, 188 | SDL_WINDOW_ALLOW_HIGHDPI = 8192, 189 | SDL_WINDOW_MOUSE_CAPTURE = 16384, 190 | } 191 | 192 | export enum SDL_WindowEventID { 193 | SDL_WINDOWEVENT_NONE = 0, 194 | SDL_WINDOWEVENT_SHOWN = 1, 195 | SDL_WINDOWEVENT_HIDDEN = 2, 196 | SDL_WINDOWEVENT_EXPOSED = 3, 197 | SDL_WINDOWEVENT_MOVED = 4, 198 | SDL_WINDOWEVENT_RESIZED = 5, 199 | SDL_WINDOWEVENT_SIZE_CHANGED = 6, 200 | SDL_WINDOWEVENT_MINIMIZED = 7, 201 | SDL_WINDOWEVENT_MAXIMIZED = 8, 202 | SDL_WINDOWEVENT_RESTORED = 9, 203 | SDL_WINDOWEVENT_ENTER = 10, 204 | SDL_WINDOWEVENT_LEAVE = 11, 205 | SDL_WINDOWEVENT_FOCUS_GAINED = 12, 206 | SDL_WINDOWEVENT_FOCUS_LOST = 13, 207 | SDL_WINDOWEVENT_CLOSE = 14, 208 | } 209 | 210 | export const SDL_DisplayMode = Struct({ 211 | format: Uint32, 212 | w: int32, 213 | h: int32, 214 | refresh_rate: int32, 215 | driverdata: voit_ptr, 216 | }); 217 | export const SDL_Window = voit; 218 | export const SDL_GLContext = voit_ptr; 219 | 220 | export const float = exports.float = ref.types.float; 221 | export const float_ptr = exports.float_ptr = ref.refType(float); 222 | export const SDL_DisplayMode_ptr = exports.SDL_DisplayMode_ptr = ref.refType(SDL_DisplayMode); 223 | export const SDL_Window_ptr = exports.SDL_Window_ptr = ref.refType(SDL_Window); 224 | export const SDL_HitTest = exports.SDL_HitTest = FFI.Function(uint32, [SDL_Window_ptr, SDL_Point_ptr, voit_ptr]); 225 | 226 | export function SDL_GetWindowSurface(windowPtr: any) { 227 | return SDL.SDL_GetWindowSurface(windowPtr); 228 | } 229 | 230 | loadLibrary({ 231 | SDL_GetNumVideoDrivers: [int32, []], 232 | SDL_GetVideoDriver: [string, [int32]], 233 | SDL_VideoInit: [int32, [string]], 234 | SDL_VideoQuit: [voit, []], 235 | SDL_GetCurrentVideoDriver: [string, []], 236 | SDL_GetNumVideoDisplays: [int32, []], 237 | SDL_GetDisplayName: [string, [int32]], 238 | SDL_GetDisplayBounds: [int32, [int32, SDL_Rect_ptr]], 239 | SDL_GetDisplayDPI: [int32, [int32, float_ptr, float_ptr, float_ptr]], 240 | SDL_GetNumDisplayModes: [int32, [int32]], 241 | SDL_GetDisplayMode: [int32, [int32, int32, SDL_DisplayMode_ptr]], 242 | SDL_GetDesktopDisplayMode: [int32, [int32, SDL_DisplayMode_ptr]], 243 | SDL_GetCurrentDisplayMode: [int32, [int32, SDL_DisplayMode_ptr]], 244 | SDL_GetClosestDisplayMode: [SDL_DisplayMode_ptr, [int32, SDL_DisplayMode_ptr, SDL_DisplayMode_ptr]], 245 | SDL_GetWindowDisplayIndex: [int32, [SDL_Window_ptr]], 246 | SDL_SetWindowDisplayMode: [int32, [SDL_Window_ptr, SDL_DisplayMode_ptr]], 247 | SDL_GetWindowDisplayMode: [int32, [SDL_Window_ptr, SDL_DisplayMode_ptr]], 248 | SDL_GetWindowPixelFormat: [Uint32, [SDL_Window_ptr]], 249 | SDL_CreateWindow: [SDL_Window_ptr, [string, int32, int32, int32, int32, Uint32]], 250 | SDL_CreateWindowFrom: [SDL_Window_ptr, [voit_ptr]], 251 | SDL_GetWindowID: [Uint32, [SDL_Window_ptr]], 252 | SDL_GetWindowFromID: [SDL_Window_ptr, [Uint32]], 253 | SDL_GetWindowFlags: [Uint32, [SDL_Window_ptr]], 254 | SDL_SetWindowTitle: [voit, [SDL_Window_ptr, string]], 255 | SDL_GetWindowTitle: [string, [SDL_Window_ptr]], 256 | SDL_SetWindowIcon: [voit, [SDL_Window_ptr, SDL_Surface_ptr]], 257 | SDL_SetWindowData: [voit_ptr, [SDL_Window_ptr, string, voit_ptr]], 258 | SDL_GetWindowData: [voit_ptr, [SDL_Window_ptr, string]], 259 | SDL_SetWindowPosition: [voit, [SDL_Window_ptr, int32, int32]], 260 | SDL_GetWindowPosition: [voit, [SDL_Window_ptr, int32_ptr, int32_ptr]], 261 | SDL_SetWindowSize: [voit, [SDL_Window_ptr, int32, int32]], 262 | SDL_GetWindowSize: [voit, [SDL_Window_ptr, int32_ptr, int32_ptr]], 263 | SDL_SetWindowResizable: [voit, [SDL_Window_ptr, uchar]], 264 | SDL_SetWindowMinimumSize: [voit, [SDL_Window_ptr, int32, int32]], 265 | SDL_GetWindowMinimumSize: [voit, [SDL_Window_ptr, int32_ptr, int32_ptr]], 266 | SDL_SetWindowMaximumSize: [voit, [SDL_Window_ptr, int32, int32]], 267 | SDL_GetWindowMaximumSize: [voit, [SDL_Window_ptr, int32_ptr, int32_ptr]], 268 | SDL_SetWindowBordered: [voit, [SDL_Window_ptr, uint32]], 269 | SDL_ShowWindow: [voit, [SDL_Window_ptr]], 270 | SDL_HideWindow: [voit, [SDL_Window_ptr]], 271 | SDL_RaiseWindow: [voit, [SDL_Window_ptr]], 272 | SDL_MaximizeWindow: [voit, [SDL_Window_ptr]], 273 | SDL_MinimizeWindow: [voit, [SDL_Window_ptr]], 274 | SDL_RestoreWindow: [voit, [SDL_Window_ptr]], 275 | SDL_SetWindowFullscreen: [int32, [SDL_Window_ptr, Uint32]], 276 | SDL_GetWindowSurface: [SDL_Surface_ptr, [SDL_Window_ptr]], 277 | SDL_UpdateWindowSurface: [int32, [SDL_Window_ptr]], 278 | SDL_UpdateWindowSurfaceRects: [int32, [SDL_Window_ptr, SDL_Rect_ptr, int32]], 279 | SDL_SetWindowGrab: [voit, [SDL_Window_ptr, uint32]], 280 | SDL_GetWindowGrab: [uint32, [SDL_Window_ptr]], 281 | SDL_GetGrabbedWindow: [SDL_Window_ptr, []], 282 | SDL_SetWindowBrightness: [int32, [SDL_Window_ptr, float]], 283 | SDL_GetWindowBrightness: [float, [SDL_Window_ptr]], 284 | SDL_SetWindowGammaRamp: [int32, [SDL_Window_ptr, Uint16_ptr, Uint16_ptr, Uint16_ptr]], 285 | SDL_GetWindowGammaRamp: [int32, [SDL_Window_ptr, Uint16_ptr, Uint16_ptr, Uint16_ptr]], 286 | SDL_SetWindowHitTest: [int32, [SDL_Window_ptr, SDL_HitTest, voit_ptr]], 287 | SDL_DestroyWindow: [voit, [SDL_Window_ptr]], 288 | SDL_IsScreenSaverEnabled: [uint32, []], 289 | SDL_EnableScreenSaver: [voit, []], 290 | SDL_DisableScreenSaver: [voit, []], 291 | SDL_GL_LoadLibrary: [int32, [string]], 292 | SDL_GL_GetProcAddress: [voit_ptr, [string]], 293 | SDL_GL_UnloadLibrary: [voit, []], 294 | SDL_GL_ExtensionSupported: [uint32, [string]], 295 | SDL_GL_ResetAttributes: [voit, []], 296 | SDL_GL_SetAttribute: [int32, [uint32, int32]], 297 | SDL_GL_GetAttribute: [int32, [uint32, int32_ptr]], 298 | SDL_GL_CreateContext: [SDL_GLContext, [SDL_Window_ptr]], 299 | SDL_GL_MakeCurrent: [int32, [SDL_Window_ptr, SDL_GLContext]], 300 | SDL_GL_GetCurrentWindow: [SDL_Window_ptr, []], 301 | SDL_GL_GetCurrentContext: [SDL_GLContext, []], 302 | SDL_GL_GetDrawableSize: [voit, [SDL_Window_ptr, int32_ptr, int32_ptr]], 303 | SDL_GL_SetSwapInterval: [int32, [int32]], 304 | SDL_GL_GetSwapInterval: [int32, []], 305 | SDL_GL_SwapWindow: [voit, [SDL_Window_ptr]], 306 | SDL_GL_DeleteContext: [voit, [SDL_GLContext]], 307 | }, SDL); 308 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/sdl.ts: -------------------------------------------------------------------------------- 1 | import {int32, Uint32, voit} from './types'; 2 | import {loadLibrary} from './lib-loader'; 3 | 4 | const SDL = {} as any; 5 | 6 | export const SDL_QUERY = -1; 7 | // export const SDL_IGNORE = 0; 8 | // export const SDL_DISABLE = 0; 9 | export const SDL_ENABLE = 1; 10 | 11 | 12 | export function SDL_Init(flags: number): number { 13 | return SDL.SDL_Init(flags); 14 | } 15 | 16 | export function SDL_Quit(): void { 17 | SDL.SDL_Quit(); 18 | } 19 | 20 | loadLibrary({ 21 | SDL_Init: [int32, [Uint32]], 22 | SDL_InitSubSystem: [int32, [Uint32]], 23 | SDL_QuitSubSystem: [voit, [Uint32]], 24 | SDL_WasInit: [Uint32, [Uint32]], 25 | SDL_Delay: [voit, [Uint32]], 26 | SDL_Quit: [voit, []] 27 | }, SDL); 28 | -------------------------------------------------------------------------------- /src/engine/sdl/sdl/types.ts: -------------------------------------------------------------------------------- 1 | const ref = require('ref-napi'); 2 | const ArrayType = require('ref-array-di')(ref); 3 | 4 | // const ref = require('ref-napi'); 5 | export const voit = ref.types.void; 6 | export const int32 = ref.types.int32; 7 | export const uint32 = ref.types.uint32; 8 | export const char = ref.types.char; 9 | export const Sint8 = char; 10 | export const uchar = ref.types.uchar; 11 | export const Uint8 = uchar; 12 | export const short = ref.types.short; 13 | export const Sint16 = short; 14 | export const ushort = ref.types.ushort; 15 | export const ulong = ref.types.ulong; 16 | export const size_t = ulong; 17 | export const string = ref.types.CString; 18 | export const wchar_t = int32; 19 | export const wchar_t_ptr = ref.refType(wchar_t); 20 | export const long = ref.types.long; 21 | export const double = ref.types.double; 22 | export const string_ptr = ref.refType(string); 23 | export const Uint16 = ushort; 24 | export const Sint32 = int32; 25 | export const Uint32 = uint32; 26 | export const longlong = ref.types.longlong; 27 | export const Sint64 = longlong; 28 | export const ulonglong = ref.types.ulonglong; 29 | export const Uint64 = ulonglong; 30 | export const c_SDL_stdinc_h_T_SDL_dummy_uint8_arr = ArrayType(int32, 1); 31 | export const SDL_dummy_uint8 = c_SDL_stdinc_h_T_SDL_dummy_uint8_arr; 32 | export const c_SDL_stdinc_h_T_SDL_dummy_sint8_arr = ArrayType(int32, 1); 33 | export const SDL_dummy_sint8 = c_SDL_stdinc_h_T_SDL_dummy_sint8_arr; 34 | export const c_SDL_stdinc_h_T_SDL_dummy_uint16_arr = ArrayType(int32, 1); 35 | export const SDL_dummy_uint16 = c_SDL_stdinc_h_T_SDL_dummy_uint16_arr; 36 | export const c_SDL_stdinc_h_T_SDL_dummy_sint16_arr = ArrayType(int32, 1); 37 | export const SDL_dummy_sint16 = c_SDL_stdinc_h_T_SDL_dummy_sint16_arr; 38 | export const c_SDL_stdinc_h_T_SDL_dummy_uint32_arr = ArrayType(int32, 1); 39 | export const SDL_dummy_uint32 = c_SDL_stdinc_h_T_SDL_dummy_uint32_arr; 40 | export const c_SDL_stdinc_h_T_SDL_dummy_sint32_arr = ArrayType(int32, 1); 41 | export const SDL_dummy_sint32 = c_SDL_stdinc_h_T_SDL_dummy_sint32_arr; 42 | export const c_SDL_stdinc_h_T_SDL_dummy_uint64_arr = ArrayType(int32, 1); 43 | export const SDL_dummy_uint64 = c_SDL_stdinc_h_T_SDL_dummy_uint64_arr; 44 | export const c_SDL_stdinc_h_T_SDL_dummy_sint64_arr = ArrayType(int32, 1); 45 | export const SDL_dummy_sint64 = c_SDL_stdinc_h_T_SDL_dummy_sint64_arr; 46 | export const c_SDL_stdinc_h_T_SDL_dummy_enum_arr = ArrayType(int32, 1); 47 | export const SDL_dummy_enum = c_SDL_stdinc_h_T_SDL_dummy_enum_arr; 48 | export const voit_ptr = ref.refType(voit); 49 | export const float = ref.types.float; 50 | export const float_ptr = ref.refType(float); 51 | export const int32_ptr = ref.refType(int32); 52 | export const Uint16_ptr = ref.refType(Uint16); 53 | export const Uint32_ptr = ref.refType(Uint32); 54 | export const Uint8_ptr = ref.refType(Uint8); 55 | export const SDL_FALSE = 0; 56 | export const SDL_TRUE = 0; 57 | export const voit_ptr_ptr = ref.refType(voit_ptr); 58 | export const uint32_ptr = ref.refType(uint32); 59 | export const bool = ref.types.bool; 60 | -------------------------------------------------------------------------------- /src/engine/sdl/shape/point.ts: -------------------------------------------------------------------------------- 1 | export interface Point { 2 | x: number; 3 | y: number; 4 | } 5 | 6 | -------------------------------------------------------------------------------- /src/engine/sdl/shape/rect.ts: -------------------------------------------------------------------------------- 1 | export interface Rect { 2 | x: number; 3 | y: number; 4 | w: number; 5 | h: number; 6 | } 7 | -------------------------------------------------------------------------------- /src/engine/sdl/thread/thread.ts: -------------------------------------------------------------------------------- 1 | import {createThreadFunction, SDL_CreateThread, SDL_DetachThread} from '../sdl/sdl-thread'; 2 | 3 | export const threadFunctions: any = {}; 4 | 5 | function runThread(threadName: string, procedure: () => void): any { 6 | const func = threadFunctions[threadName] = createThreadFunction(() => { 7 | procedure(); 8 | return 0; 9 | }); 10 | 11 | return SDL_CreateThread(func, threadName, null); 12 | } 13 | 14 | export type Runnable = () => void; 15 | 16 | export class Thread { 17 | private threadPtr: any; 18 | 19 | constructor(private name: string, private runnable: Runnable) { 20 | this.threadPtr = null; 21 | } 22 | 23 | start(): void { 24 | if (this.threadPtr === null) { 25 | this.threadPtr = runThread(this.name, () => this.runnable()); 26 | } 27 | } 28 | 29 | stop(): void { 30 | if (this.threadPtr !== null) { 31 | SDL_DetachThread(this.threadPtr); 32 | this.threadPtr = null; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './nodejs'; 2 | export * from './nodejs/global'; 3 | -------------------------------------------------------------------------------- /src/nodejs/global.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createWindow, 3 | requestAnimationFrame, 4 | Image, 5 | cancelAnimationFrame, 6 | alert, 7 | confirm, SdlCanvas, SdlContext 8 | } from '.'; 9 | 10 | import {NativeWindow} from '../window/native-window'; 11 | import Global = NodeJS.Global; 12 | 13 | const globalCtx = (global as any); 14 | let internalWindow; 15 | 16 | if (globalCtx.GLOAL_WINDOW_OPTS) { 17 | internalWindow = createWindow(globalCtx.GLOAL_WINDOW_OPTS); 18 | } else { 19 | 20 | internalWindow = createWindow(); 21 | } 22 | 23 | export const window = internalWindow; 24 | export const document: Document = internalWindow.document; 25 | 26 | /* tslint:disable*/ 27 | const dontOverride = new Set(Object.getOwnPropertyNames(globalCtx)); 28 | const windowObj = window as any; 29 | 30 | windowObj.Image = Image; 31 | windowObj.HTMLCanvasElement = SdlCanvas; 32 | windowObj.CanvasRenderingContext2D = SdlContext; 33 | dontOverride.add('Image'); 34 | dontOverride.add('HTMLCanvasElement'); 35 | dontOverride.add('CanvasRenderingContext2D'); 36 | dontOverride.add('XMLHttpRequest'); 37 | 38 | for (const prop in windowObj) { 39 | if (!dontOverride.has(prop) && !prop.startsWith('_') && !prop.startsWith('constructor') && !prop.startsWith('console')) { 40 | const descriptor = Object.getOwnPropertyDescriptor(windowObj.__proto__, prop); 41 | if (descriptor) { 42 | if (descriptor.value) { 43 | globalCtx[prop] = function () { 44 | const args = Array.from(arguments); 45 | return windowObj[prop].apply(windowObj, args); 46 | }; 47 | 48 | } else { 49 | Object.defineProperty(globalCtx, prop, { 50 | get: function () { 51 | return windowObj[prop]; 52 | }, 53 | set: function (val: any) { 54 | windowObj[prop] = val; 55 | } 56 | }); 57 | } 58 | 59 | } else if (typeof(windowObj[prop]) === 'function') { 60 | globalCtx[prop] = function () { 61 | const args = Array.from(arguments); 62 | return windowObj[prop](); 63 | }; 64 | } else { 65 | globalCtx[prop] = windowObj[prop]; 66 | } 67 | } 68 | } 69 | /* tslint:enable*/ 70 | 71 | 72 | globalCtx.window = window; 73 | globalCtx.document = document; 74 | globalCtx.Image = Image; 75 | globalCtx.HTMLCanvasElement = SdlCanvas; 76 | globalCtx.CanvasRenderingContext2D = SdlContext; 77 | 78 | -------------------------------------------------------------------------------- /src/nodejs/index.ts: -------------------------------------------------------------------------------- 1 | import {NativeWindow} from '../window/native-window'; 2 | import {WindowOptions} from '../window/window-options'; 3 | import * as engine from '../engine'; 4 | 5 | const NodeCanvasImage = require('canvas').Image; 6 | 7 | const ENGINE_NAME = 'sdl'; 8 | 9 | export * from '../engine/sdl/image/image'; 10 | 11 | export * from '../engine/sdl/canvas/sdl-context'; 12 | export * from '../engine/sdl/canvas/sdl-canvas'; 13 | 14 | export function confirm(message?: string): boolean { 15 | return engine.confirm(ENGINE_NAME, message); 16 | } 17 | 18 | export function cancelAnimationFrame(request: number): void { 19 | engine.cancelAnimationFrame(ENGINE_NAME, request); 20 | } 21 | 22 | export function requestAnimationFrame(callback: FrameRequestCallback): void { 23 | engine.requestAnimationFrame(ENGINE_NAME, callback); 24 | } 25 | 26 | export function alert(message?: string): void { 27 | engine.alert(ENGINE_NAME, message); 28 | } 29 | 30 | export function createWindow(opts?: WindowOptions): NativeWindow { 31 | return engine.createWindow(ENGINE_NAME, opts); 32 | } 33 | -------------------------------------------------------------------------------- /src/window/native-window.ts: -------------------------------------------------------------------------------- 1 | import {WindowOptions} from './window-options'; 2 | 3 | export interface NativeWindow extends Window { 4 | canvasX: number; 5 | 6 | canvasY: number; 7 | 8 | title: string; 9 | 10 | canvas: HTMLCanvasElement; 11 | 12 | renderFrame(ms: number): void; 13 | 14 | enableFullScreen(): void; 15 | 16 | disableFullScreen(): void; 17 | 18 | windowImplementation(): any; 19 | 20 | loadImage(src: string): Promise; 21 | 22 | newCanvas(window?: (NativeWindow | string), windowOptions?: WindowOptions): HTMLCanvasElement; 23 | } 24 | -------------------------------------------------------------------------------- /src/window/window-options.ts: -------------------------------------------------------------------------------- 1 | export interface WindowOptions { 2 | title?: string; 3 | x?: number; 4 | y?: number; 5 | width?: number; 6 | height?: number; 7 | fullscreen?: boolean; 8 | show?: boolean; 9 | closable?: boolean; 10 | resizable?: boolean; 11 | borderless?: boolean; 12 | minimized?: boolean; 13 | maximized?: boolean; 14 | allowHighDPI?: boolean; 15 | grabInputFocus?: boolean; 16 | fitCanvasInWindow: boolean; 17 | scaleCanvasToWindowSize: boolean; 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "lib": [ 5 | "es6", 6 | "dom", 7 | "esnext" 8 | ], 9 | "sourceMap": true, 10 | "module": "commonjs", 11 | "declaration": true, 12 | "noImplicitAny": true, 13 | "target": "es5", 14 | "downlevelIteration": true, 15 | "experimentalDecorators": true, 16 | "allowJs": false, 17 | "types": [ 18 | "node" 19 | ], 20 | "typeRoots": [ 21 | "node_modules/@types" 22 | ] 23 | }, 24 | "include": [ 25 | "src/**/*.ts" 26 | ], 27 | "exclude": [ 28 | "node_modules" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "arrow-return-shorthand": true, 4 | "callable-types": true, 5 | "class-name": true, 6 | "comment-format": [ 7 | true 8 | ], 9 | "curly": true, 10 | "deprecation": { 11 | "severity": "warn" 12 | }, 13 | "eofline": true, 14 | "forin": true, 15 | "import-spacing": true, 16 | "indent": [ 17 | true, 18 | "spaces" 19 | ], 20 | "interface-over-type-literal": true, 21 | "label-position": true, 22 | "max-line-length": [ 23 | false, 24 | 140 25 | ], 26 | "member-access": false, 27 | "member-ordering": [ 28 | true, 29 | { 30 | "order": [ 31 | "instance-field", 32 | "instance-method", 33 | "static-method", 34 | "static-field" 35 | ] 36 | } 37 | ], 38 | "no-arg": true, 39 | "no-bitwise": true, 40 | "no-console": [ 41 | true, 42 | "debug", 43 | "info", 44 | "time", 45 | "timeEnd", 46 | "trace" 47 | ], 48 | "no-construct": true, 49 | "no-debugger": true, 50 | "no-duplicate-super": true, 51 | "no-empty": false, 52 | "no-empty-interface": true, 53 | "no-eval": false, 54 | "no-inferrable-types": [ 55 | true, 56 | "ignore-params" 57 | ], 58 | "no-misused-new": true, 59 | "no-non-null-assertion": true, 60 | "no-shadowed-variable": true, 61 | "no-string-literal": false, 62 | "no-string-throw": true, 63 | "no-switch-case-fall-through": true, 64 | "no-trailing-whitespace": true, 65 | "no-unnecessary-initializer": true, 66 | "no-unused-expression": true, 67 | "no-use-before-declare": true, 68 | "no-var-keyword": true, 69 | "object-literal-sort-keys": false, 70 | "one-line": [ 71 | true, 72 | "check-open-brace", 73 | "check-catch", 74 | "check-else", 75 | "check-whitespace" 76 | ], 77 | "prefer-const": true, 78 | "quotemark": [ 79 | true, 80 | "single" 81 | ], 82 | "radix": true, 83 | "semicolon": [ 84 | true, 85 | "always" 86 | ], 87 | "triple-equals": [ 88 | true, 89 | "allow-null-check" 90 | ], 91 | "typedef-whitespace": [ 92 | true, 93 | { 94 | "call-signature": "nospace", 95 | "index-signature": "nospace", 96 | "parameter": "nospace", 97 | "property-declaration": "nospace", 98 | "variable-declaration": "nospace" 99 | } 100 | ], 101 | "unified-signatures": true, 102 | "variable-name": false, 103 | "whitespace": [ 104 | true, 105 | "check-branch", 106 | "check-decl", 107 | "check-operator", 108 | "check-separator", 109 | "check-type" 110 | ] 111 | } 112 | } 113 | --------------------------------------------------------------------------------