1 /* FAudio - XAudio Reimplementation for FNA
2  *
3  * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team
4  *
5  * This software is provided 'as-is', without any express or implied warranty.
6  * In no event will the authors be held liable for any damages arising from
7  * the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software in a
15  * product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  *
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  * misrepresented as being the original software.
20  *
21  * 3. This notice may not be removed or altered from any source distribution.
22  *
23  * Ethan "flibitijibibo" Lee <flibitijibibo@flibitijibibo.com>
24  *
25  */
26 
27 /* Unless you're trying to do ImGui interop work, you probably don't want this!
28  * Go to the other folders to look at the actual tools.
29  * -flibit
30  */
31 
32 #include <stdint.h>
33 #include "imgui.h"
34 
35 /* FAudioUI_main.cpp */
36 
37 extern const char* main_getclipboardtext(void* userdata);
38 extern void main_setclipboardtext(void* userdata, const char *text);
39 extern void main_setupviewport(int fbw, int fbh, float dw, float dh);
40 extern void main_setupvertexattribs(
41 	int stride,
42 	const void *vtx,
43 	const void *txc,
44 	const void *clr
45 );
46 extern void main_draw(
47 	void *texture,
48 	int sx,
49 	int sy,
50 	int sw,
51 	int sh,
52 	int count,
53 	int idxSize,
54 	const void *idx
55 );
56 
57 /* ImGui Callbacks */
58 
UI_RenderDrawLists(ImDrawData * draw_data)59 void UI_RenderDrawLists(ImDrawData *draw_data)
60 {
61 	ImGuiIO& io = ImGui::GetIO();
62 
63 	/* Set up viewport/scissor rects (based on display size/scale */
64 	int fb_width = (int) (io.DisplaySize.x * io.DisplayFramebufferScale.x);
65 	int fb_height = (int) (io.DisplaySize.y * io.DisplayFramebufferScale.y);
66 	if (fb_width == 0 || fb_height == 0)
67 	{
68 		/* No point in rendering to nowhere... */
69 		return;
70 	}
71 	draw_data->ScaleClipRects(io.DisplayFramebufferScale);
72 	main_setupviewport(
73 		fb_width,
74 		fb_height,
75 		io.DisplaySize.x,
76 		io.DisplaySize.y
77 	);
78 
79 	/* Submit draw commands */
80 	#define OFFSETOF(TYPE, ELEMENT) ((size_t) &(((TYPE*) NULL)->ELEMENT))
81 	for (int cmd_l = 0; cmd_l < draw_data->CmdListsCount; cmd_l += 1)
82 	{
83 		const ImDrawList* cmd_list = draw_data->CmdLists[cmd_l];
84 		const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
85 		const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
86 
87 		main_setupvertexattribs(
88 			sizeof(ImDrawVert),
89 			((const char*) vtx_buffer + OFFSETOF(ImDrawVert, pos)),
90 			((const char*) vtx_buffer + OFFSETOF(ImDrawVert, uv)),
91 			((const char*) vtx_buffer + OFFSETOF(ImDrawVert, col))
92 		);
93 
94 		for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i += 1)
95 		{
96 			const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
97 			main_draw(
98 				pcmd->TextureId,
99 				(int) pcmd->ClipRect.x,
100 				(int) (fb_height - pcmd->ClipRect.w),
101 				(int) (pcmd->ClipRect.z - pcmd->ClipRect.x),
102 				(int) (pcmd->ClipRect.w - pcmd->ClipRect.y),
103 				pcmd->ElemCount,
104 				sizeof(ImDrawIdx),
105 				idx_buffer
106 			);
107 			idx_buffer += pcmd->ElemCount;
108 		}
109 	}
110 	#undef OFFSETOF
111 }
112 
113 /* Public API */
114 
115 static ImGuiContext *imContext = NULL;
116 
UI_Init(int tab,int left,int right,int up,int down,int pgup,int pgdown,int home,int end,int del,int backspace,int enter,int escape,int a,int c,int v,int x,int y,int z,unsigned char ** pixels,int * tw,int * th)117 void UI_Init(
118 	int tab,
119 	int left,
120 	int right,
121 	int up,
122 	int down,
123 	int pgup,
124 	int pgdown,
125 	int home,
126 	int end,
127 	int del,
128 	int backspace,
129 	int enter,
130 	int escape,
131 	int a,
132 	int c,
133 	int v,
134 	int x,
135 	int y,
136 	int z,
137 	unsigned char **pixels,
138 	int *tw,
139 	int *th
140 ) {
141 	imContext = ImGui::CreateContext(NULL);
142 	ImGui::SetCurrentContext(imContext);
143 
144 	ImGuiIO& io = ImGui::GetIO();
145 
146 	/* Keyboard */
147 	io.KeyMap[ImGuiKey_Tab] = tab;
148 	io.KeyMap[ImGuiKey_LeftArrow] = left;
149 	io.KeyMap[ImGuiKey_RightArrow] = right;
150 	io.KeyMap[ImGuiKey_UpArrow] = up;
151 	io.KeyMap[ImGuiKey_DownArrow] = down;
152 	io.KeyMap[ImGuiKey_PageUp] = pgup;
153 	io.KeyMap[ImGuiKey_PageDown] = pgdown;
154 	io.KeyMap[ImGuiKey_Home] = home;
155 	io.KeyMap[ImGuiKey_End] = end;
156 	io.KeyMap[ImGuiKey_Delete] = del;
157 	io.KeyMap[ImGuiKey_Backspace] = backspace;
158 	io.KeyMap[ImGuiKey_Enter] = enter;
159 	io.KeyMap[ImGuiKey_Escape] = escape;
160 	io.KeyMap[ImGuiKey_A] = a;
161 	io.KeyMap[ImGuiKey_C] = c;
162 	io.KeyMap[ImGuiKey_V] = v;
163 	io.KeyMap[ImGuiKey_X] = x;
164 	io.KeyMap[ImGuiKey_Y] = y;
165 	io.KeyMap[ImGuiKey_Z] = z;
166 
167 	/* Callbacks */
168 	io.RenderDrawListsFn = UI_RenderDrawLists;
169 	io.GetClipboardTextFn = main_getclipboardtext;
170 	io.SetClipboardTextFn = main_setclipboardtext;
171 
172 	/* Create texture for text rendering */
173 	io.Fonts->GetTexDataAsAlpha8(pixels, tw, th);
174 }
175 
UI_Update(int ww,int wh,int dw,int dh,int mx,int my,uint8_t mouse1,uint8_t mouse2,uint8_t mouse3,int8_t wheel,float deltaTime)176 uint8_t UI_Update(
177 	int ww,
178 	int wh,
179 	int dw,
180 	int dh,
181 	int mx,
182 	int my,
183 	uint8_t mouse1,
184 	uint8_t mouse2,
185 	uint8_t mouse3,
186 	int8_t wheel,
187 	float deltaTime
188 ) {
189 	ImGuiIO& io = ImGui::GetIO();
190 
191 	/* Set these every frame, we have a resizable window! */
192 	io.DisplaySize = ImVec2((float) ww, (float) wh);
193 	io.DisplayFramebufferScale = ImVec2(
194 		ww > 0 ? ((float) dw / ww) : 0,
195 		wh > 0 ? ((float) dh / wh) : 0
196 	);
197 
198 	/* Time update */
199 	io.DeltaTime = deltaTime;
200 	if (io.DeltaTime == 0.0f)
201 	{
202 		io.DeltaTime = 0.01f;
203 	}
204 
205 	/* Input updates not done via UI_Submit*() */
206 	io.MousePos = ImVec2((float) mx, (float) my);
207 	io.MouseDown[0] = mouse1;
208 	io.MouseDown[1] = mouse2;
209 	io.MouseDown[2] = mouse3;
210 	io.MouseWheel = wheel;
211 
212 	/* BEGIN */
213 	ImGui::NewFrame();
214 	return io.MouseDrawCursor;
215 }
216 
UI_Quit()217 void UI_Quit()
218 {
219 	ImGui::DestroyContext(imContext);
220 }
221 
UI_Render()222 void UI_Render()
223 {
224 	ImGui::Render();
225 }
226 
UI_SubmitKey(int key,uint8_t down,uint8_t shift,uint8_t ctrl,uint8_t alt,uint8_t gui)227 void UI_SubmitKey(
228 	int key,
229 	uint8_t down,
230 	uint8_t shift,
231 	uint8_t ctrl,
232 	uint8_t alt,
233 	uint8_t gui
234 ) {
235 	ImGuiIO& io = ImGui::GetIO();
236 	io.KeysDown[key] = down;
237 	io.KeyShift = shift;
238 	io.KeyCtrl = ctrl;
239 	io.KeyAlt = alt;
240 	io.KeySuper = gui;
241 }
242 
UI_SubmitText(char * text)243 void UI_SubmitText(char *text)
244 {
245 	ImGui::GetIO().AddInputCharactersUTF8(text);
246 }
247 
UI_SetFontTexture(void * texture)248 void UI_SetFontTexture(void *texture)
249 {
250 	ImGui::GetIO().Fonts->TexID = texture;
251 }
252