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