1 /** 2 * ae.demo.inputtiming.main 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <vladimir@thecybershadow.net> 12 */ 13 14 module ae.demo.inputtiming.main; 15 16 import core.time; 17 18 import ae.ui.app.application; 19 import ae.ui.app.main; 20 import ae.ui.shell.shell; 21 import ae.ui.shell.sdl2.shell; 22 import ae.ui.video.renderer; 23 import ae.ui.video.sdl2.video; 24 import ae.utils.fps; 25 import ae.utils.math; 26 import ae.utils.graphics.image; 27 28 alias ae.utils.math.abs abs; // Issue 314? 29 30 final class MyApplication : Application 31 { 32 override string getName() { return "Demo/Input"; } 33 override string getCompanyName() { return "CyberShadow"; } 34 35 Shell shell; 36 37 enum BAND_WIDTH = 800; 38 enum BAND_INTERVAL = 100; 39 enum BAND_TOP = 50; 40 enum BAND_HEIGHT = 30; 41 enum BAND_HNSECS_PER_PIXEL = 200_000; 42 enum HISTORY_TOP = 200; 43 enum HISTORY_HEIGHT = 50; 44 45 enum Device : int { keyboard, joypad, mouse, max } 46 enum SampleType : int { precision, duration, max } 47 48 int[] history[Device.max][SampleType.max]; 49 enum SAMPLE_COLORS = [BGRX(0, 0, 255), BGRX(0, 255, 0)]; 50 51 /// Some (precise) time value of the moment, in hnsecs. 52 @property long now() { return TickDuration.currSystemTick.to!("hnsecs", long); } 53 54 override void render(Renderer s) 55 { 56 auto x = now / BAND_HNSECS_PER_PIXEL; 57 58 s.clear(); 59 s.line(BAND_WIDTH/2, BAND_TOP, BAND_WIDTH/2, BAND_TOP + BAND_HEIGHT, BGRX(0, 0, 255)); 60 foreach (lx; 0..BAND_WIDTH) 61 if ((lx+x)%BAND_INTERVAL == 0) 62 s.line(lx, BAND_TOP+BAND_HEIGHT, lx, BAND_TOP+BAND_HEIGHT*2, BGRX(0, 255, 0)); 63 64 foreach (device, deviceSamples; history) 65 foreach (sampleType, samples; deviceSamples) 66 { 67 auto y = HISTORY_TOP + HISTORY_HEIGHT * (device*2 + sampleType + 1); 68 foreach (index, sample; samples) 69 { 70 if (sample > HISTORY_HEIGHT) 71 sample = HISTORY_HEIGHT; 72 s.line(index, y - sample, index, y, SAMPLE_COLORS[sampleType]); 73 } 74 } 75 } 76 77 override int run(string[] args) 78 { 79 shell = new SDL2Shell(this); 80 shell.video = new SDL2Video(); 81 shell.run(); 82 shell.video.shutdown(); 83 return 0; 84 } 85 86 long pressed; 87 88 void keyDown(Device device) 89 { 90 pressed = now; 91 auto x = cast(int)(pressed / BAND_HNSECS_PER_PIXEL + BAND_WIDTH/2) % BAND_INTERVAL; 92 if (x > BAND_INTERVAL/2) 93 x -= BAND_INTERVAL; 94 history[device][SampleType.precision] ~= abs(x); 95 } 96 97 void keyUp(Device device) 98 { 99 auto duration = now - pressed; 100 history[device][SampleType.duration] ~= cast(int)(duration / BAND_HNSECS_PER_PIXEL); 101 } 102 103 override void handleKeyDown(Key key, dchar character) 104 { 105 if (key == Key.esc) 106 shell.quit(); 107 else 108 keyDown(Device.keyboard); 109 } 110 111 override void handleKeyUp(Key key) 112 { 113 keyUp (Device.keyboard); 114 } 115 116 override bool needJoystick() { return true; } 117 118 override void handleJoyButtonDown(int button) 119 { 120 keyDown(Device.joypad); 121 } 122 123 override void handleJoyButtonUp (int button) 124 { 125 keyUp (Device.joypad); 126 } 127 128 override void handleMouseDown(uint x, uint y, MouseButton button) 129 { 130 keyDown(Device.mouse); 131 } 132 133 override void handleMouseUp(uint x, uint y, MouseButton button) 134 { 135 keyUp (Device.mouse); 136 } 137 138 override void handleQuit() 139 { 140 shell.quit(); 141 } 142 } 143 144 shared static this() 145 { 146 createApplication!MyApplication(); 147 }