1 module armos.app.runner; 2 3 import armos.app; 4 import armos.utils; 5 import armos.events; 6 import armos.graphics; 7 8 import std.algorithm; 9 import std.array; 10 11 /++ 12 armosのアプリケーションの更新を行うclassです. 13 +/ 14 15 16 class Runner { 17 public{ 18 /++ 19 +/ 20 this(){ 21 _fpsCounter = new FpsCounter; 22 } 23 24 /++ 25 イベントループに入ります. 26 Params: 27 app = 更新されるアプリケーションです. 28 +/ 29 Runner register(Application app, Window window){ 30 window.initEvents(app); 31 _appsCollection.add(app, window); 32 return this; 33 }; 34 35 /++ 36 現在のFPS(Frame Per Second)の使用率を返します. 37 +/ 38 double fpsUseRate(){ 39 return _fpsCounter.fpsUseRate; 40 } 41 42 /++ 43 FPS(Frame Per Second)を指定します. 44 +/ 45 void targetFps(in double fps){ 46 _fpsCounter.targetFps = fps; 47 } 48 49 /// 50 double targetFps()const{ 51 return _fpsCounter.targetFps; 52 } 53 54 /// 55 double currentFps()const{ 56 return _fpsCounter.currentFps; 57 } 58 59 /// 60 Renderer renderer()out(renderer){ 61 assert(renderer); 62 }body{ 63 return currentWindow.renderer; 64 } 65 66 /// 67 Window currentWindow()out(window){ 68 assert(window); 69 }body{ 70 return _currentWindow; 71 } 72 73 CoreObservables currentObservables(){ 74 return currentWindow.observables; 75 } 76 77 /// 78 Runner loop(){ 79 foreach (winapp; _appsCollection.byPair) { 80 auto window = winapp[0]; 81 auto app = winapp[1]; 82 select(window); 83 window.setup; 84 } 85 86 bool isLoop = true; 87 while(isLoop){ 88 loopOnce(); 89 _fpsCounter.adjust(); 90 _fpsCounter.newFrame(); 91 import std.functional; 92 isLoop = _appsCollection.keys.length > 0; 93 } 94 95 foreach (winapp; _appsCollection.byPair) { 96 auto window = winapp[0]; 97 auto app = winapp[1]; 98 select(window); 99 } 100 return this; 101 } 102 103 void select(Window window){ 104 window.select; 105 _currentWindow = window; 106 } 107 }//public 108 109 private{ 110 AppCollection _appsCollection; 111 Window _currentWindow; 112 113 FpsCounter _fpsCounter; 114 115 116 117 void loopOnce(){ 118 foreach (winapp; _appsCollection.byPair) { 119 auto window = winapp[0]; 120 auto app = winapp[1]; 121 select(window); 122 window.update(); 123 window.draw(); 124 } 125 _appsCollection.keys.each!(w => w.pollEvents()); 126 127 Window[] shouldRemoves; 128 foreach (winapp; _appsCollection.byPair) { 129 auto window = winapp[0]; 130 auto app = winapp[1]; 131 132 if(window.shouldClose||app.shouldClose){ 133 window.close; 134 shouldRemoves ~= window; 135 } 136 } 137 shouldRemoves.each!(w => _appsCollection.remove(w)); 138 } 139 140 }//private 141 } 142 143 Runner mainLoop() @property { 144 static __gshared Runner instance; 145 import std.concurrency : initOnce; 146 return initOnce!instance(new Runner); 147 } 148 149 /++ 150 armosのアプリケーションを実行します. 151 Params: 152 WindowType = 立ち上げるWindowの型を指定します.省略可能です. 153 app = 立ち上げるアプリケーションを指定します. 154 +/ 155 void run(WindowType = GLFWWindow)(Application app, WindowConfig config = null){ 156 // mainLoop_ = new Runner; 157 if(!config){ 158 config = new WindowConfig(); 159 with(config){ 160 glVersion = SemVer(3, 3, 0); 161 width = 640; 162 height = 480; 163 } 164 } 165 166 Window window = new WindowType(config); 167 mainLoop.register(app, window); 168 mainLoop.loop; 169 } 170 171 /++ 172 現在のFPS(Frame Per Second)の使用率を返します. 173 +/ 174 double fpsUseRate(){ 175 return mainLoop.fpsUseRate; 176 } 177 178 /++ 179 FPS(Frame Per Second)を指定します. 180 +/ 181 void targetFps(in double fps){ 182 mainLoop.targetFps(fps); 183 } 184 185 double targetFps(){ 186 return mainLoop.targetFps; 187 } 188 189 CoreObservables currentObservables(){ 190 return mainLoop.currentObservables; 191 } 192 193 double currentFps(){ 194 return mainLoop.currentFps; 195 } 196 197 ulong currentFrames(){ 198 return mainLoop._fpsCounter.currentFrames(); 199 }