1 module main; 2 3 import std.stdio; 4 import std.path; 5 import std.file; 6 import std.container.array; 7 import std.conv; 8 import core.memory; 9 10 import rpui.application; 11 import rpui.events; 12 import rpui.widget_events; 13 import rpui.view; 14 import rpui.view_component; 15 import rpui.widget; 16 import rpui.widgets.button.widget; 17 import rpui.widgets.panel.widget; 18 import rpui.widgets.dialog.widget; 19 import rpui.widgets.canvas.widget; 20 import rpui.widgets.list_menu.widget; 21 import rpui.widgets.list_menu_item.widget; 22 23 import gapi.vec; 24 import gapi.camera; 25 import gapi.geometry; 26 import gapi.geometry_quad; 27 import gapi.shader; 28 import gapi.texture; 29 import gapi.transform; 30 import gapi.shader_uniform; 31 import gapi.opengl; 32 33 void main() { 34 auto app = new TestApplication(); 35 app.run(); 36 } 37 38 final class TestApplication : Application { 39 private View rootView; 40 private MyViewComponent viewComponent; 41 42 override void onProgress(in ProgressEvent event) { 43 viewComponent.onProgress(event); 44 rootView.onProgress(event); 45 } 46 47 override void onRender() { 48 rootView.onRender(); 49 } 50 51 override void onCreate() { 52 auto viewResources = createViewResources("light"); 53 viewResources.strings.setLocale("en"); 54 viewResources.strings.addStrings("test_view.rdl"); 55 56 rootView = new View(windowData.window, "light", cursorManager, viewResources); 57 events.join(rootView.events); 58 events.subscribe(rootView); 59 60 viewComponent = ViewComponent.createFromFileWithShortcuts!(MyViewComponent)(rootView, "test.rdl"); 61 } 62 } 63 64 final class MyViewComponent : ViewComponent { 65 @bindWidget Button okButton; 66 @bindWidget Panel testPanel; 67 @bindWidget("cancelButton") Button myButton; 68 @bindWidget Dialog testDialog; 69 @bindGroupWidgets Button[3] buttons; 70 @bindWidget Canvas openglCanvas; 71 @bindWidget ListMenu listWithData; 72 73 struct ItemData { 74 dstring title; 75 int payload; 76 } 77 78 Array!ItemData listData; 79 80 int a = 0; 81 82 this(View view, in string laytoutFileName, in string shortcutsFileName) { 83 super(view, laytoutFileName, shortcutsFileName); 84 } 85 86 override void onCreate() { 87 okButton.events.subscribe!KeyPressedEvent(delegate(in event) { 88 writeln("Handle OkButton Key Pressed Event", event.key); 89 }); 90 91 okButton.isEnabled = true; 92 openglCanvas.canvasRenderer = new OpenGLRenderer(); 93 } 94 95 private void bindData() { 96 listWithData.bindData(listData, function(ItemData data) { 97 auto listItem = new ListMenuItem(); 98 listItem.caption = data.title; 99 listItem.events.subscribe!ClickEvent(delegate(in event) { 100 writeln("List item clicked; payload is: ", data.payload); 101 }); 102 return listItem; 103 }); 104 } 105 106 @onClickListener("addListItemButton") 107 void onAddListItemButton() { 108 listData.insert(ItemData("Item index: " ~ to!dstring(listData.length), a)); 109 bindData(); 110 } 111 112 @onClickListener("removeListItemButton") 113 void onRemoveListItemButton() { 114 if (!listData.empty) { 115 listData.removeBack(1); 116 bindData(); 117 } 118 } 119 120 @onClickListener("okButton") 121 void onOkButtonClick() { 122 writeln("Hello world! a = ", a); 123 a += 1; 124 } 125 126 @onClickListener("okButton") 127 void onOkButtonClick2() { 128 okButton.caption = "YAY!"; 129 myButton.caption = "WORKS!"; 130 buttons[2].caption = "YES!"; 131 } 132 133 @shortcut("TestGroup.cancel") 134 void someShortcutAction() { 135 writeln("Wow! shortcut was executed!"); 136 } 137 138 @onClickListener("closeButton") 139 @onClickListener("cancelButton") 140 void onCancelButtonClick() { 141 writeln("Close!"); 142 } 143 144 @onClickListener("testMenuItem") 145 @onClickListener("testMenuItem2") 146 @onClickListener("openDialogButton") 147 void onOpenDialogButtonClick() { 148 testDialog.open(); 149 } 150 151 @onClickListener("closeDialogButton") 152 void onCloseDialogButtonClick() { 153 testDialog.close(); 154 } 155 } 156 157 final class OpenGLRenderer : CanvasRenderer { 158 struct Geometry { 159 Buffer indicesBuffer; 160 Buffer verticesBuffer; 161 Buffer texCoordsBuffer; 162 163 VAO vao; 164 } 165 166 private Geometry sprite; 167 private Texture2D spriteTexture; 168 private ShaderProgram transformShader; 169 private Transform2D spriteTransform; 170 private mat4 spriteModelMatrix; 171 private mat4 spriteMVPMatrix; 172 private Widget widget; 173 174 override void onCreate(Widget widget) { 175 createSprite(); 176 createTexture(); 177 createShaders(); 178 179 this.widget = widget; 180 } 181 182 override void onDestroy() { 183 deleteBuffer(sprite.indicesBuffer); 184 deleteBuffer(sprite.verticesBuffer); 185 deleteBuffer(sprite.texCoordsBuffer); 186 deleteTexture2D(spriteTexture); 187 deleteShaderProgram(transformShader); 188 } 189 190 private void createSprite() { 191 sprite.indicesBuffer = createIndicesBuffer(quadIndices); 192 sprite.verticesBuffer = createVector2fBuffer(centeredQuadVertices); 193 sprite.texCoordsBuffer = createVector2fBuffer(quadTexCoords); 194 195 sprite.vao = createVAO(); 196 bindVAO(sprite.vao); 197 createVector2fVAO(sprite.verticesBuffer, inAttrPosition); 198 createVector2fVAO(sprite.texCoordsBuffer, inAttrTextCoords); 199 } 200 201 private void createTexture() { 202 const Texture2DParameters params = { 203 minFilter: true, 204 magFilter: true 205 }; 206 spriteTexture = createTexture2DFromFile(buildPath("res", "test.jpg"), params); 207 } 208 209 private void createShaders() { 210 const vertexSource = readText(buildPath("res", "shaders", "transform_vertex.glsl")); 211 const vertexShader = createShader("transform vertex shader", ShaderType.vertex, vertexSource); 212 213 const fragmentSource = readText(buildPath("res", "shaders", "texture_fragment.glsl")); 214 const fragmentShader = createShader("transform fragment shader", ShaderType.fragment, fragmentSource); 215 216 transformShader = createShaderProgram("transform program", [vertexShader, fragmentShader]); 217 } 218 219 override void onRender() { 220 bindShaderProgram(transformShader); 221 setShaderProgramUniformMatrix(transformShader, "MVP", spriteMVPMatrix); 222 setShaderProgramUniformTexture(transformShader, "texture", spriteTexture, 0); 223 224 bindVAO(sprite.vao); 225 bindIndices(sprite.indicesBuffer); 226 renderIndexedGeometry(cast(uint) quadIndices.length, GL_TRIANGLE_STRIP); 227 } 228 229 override void onProgress(in ProgressEvent event) { 230 assert(widget !is null); 231 assert(widget.view !is null); 232 233 const screenCameraView = widget.view.cameraView; 234 spriteTransform.position = vec2( 235 screenCameraView.viewportWidth / 2, 236 screenCameraView.viewportHeight / 2 237 ); 238 spriteTransform.scaling = vec2(430.0f, 600.0f); 239 spriteTransform.rotation += 0.025f * event.deltaTime; 240 241 spriteModelMatrix = create2DModelMatrix(spriteTransform); 242 spriteMVPMatrix = screenCameraView.mvpMatrix * spriteModelMatrix; 243 } 244 }