1 /*
2  *  Copyright (c) 2012-2016, Bruno Levy
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *
8  *  * Redistributions of source code must retain the above copyright notice,
9  *  this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright notice,
11  *  this list of conditions and the following disclaimer in the documentation
12  *  and/or other materials provided with the distribution.
13  *  * Neither the name of the ALICE Project-Team nor the names of its
14  *  contributors may be used to endorse or promote products derived from this
15  *  software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  *  POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  If you modify this software, you should include a notice giving the
30  *  name of the person performing the modification, the date of modification,
31  *  and the reason for such modification.
32  *
33  *  Contact: Bruno Levy
34  *
35  *     Bruno.Levy@inria.fr
36  *     http://www.loria.fr/~levy
37  *
38  *     ALICE Project
39  *     LORIA, INRIA Lorraine,
40  *     Campus Scientifique, BP 239
41  *     54506 VANDOEUVRE LES NANCY CEDEX
42  *     FRANCE
43  *
44  */
45 
46 #include <geogram_gfx/lua/lua_imgui.h>
47 #include <geogram_gfx/ImGui_ext/imgui_ext.h>
48 #include <geogram_gfx/ImGui_ext/icon_font.h>
49 #include <geogram/lua/lua_wrap.h>
50 #include <geogram/basic/string.h>
51 #include <geogram/basic/logger.h>
52 #include <map>
53 
54 extern void LoadImguiBindings();
55 extern lua_State* lState;
56 
57 namespace {
58     using namespace GEO;
59 
60 
wrapper_TextInput(lua_State * L)61     int wrapper_TextInput(lua_State* L) {
62 
63 	if(
64 	    lua_gettop(L) != 2 &&
65 	    lua_gettop(L) != 3
66 	) {
67 	    return luaL_error(
68 		L, "'imgui.TextInput()' invalid number of arguments"
69 	    );
70 	}
71 
72 	if(!lua_isstring(L,1)) {
73 	    return luaL_error(
74 		L, "'imgui.TextInput()' argument 1 should be a string"
75 	    );
76 	}
77 
78 	if(!lua_isstring(L,2)) {
79 	    return luaL_error(
80 		L, "'imgui.TextInput()' argument 2 should be a string"
81 	    );
82 	}
83 
84 	ImGuiInputTextFlags flags = 0;
85 
86 	if(lua_gettop(L) == 3) {
87 	    if(!lua_isnumber(L,3)) {
88 		return luaL_error(
89 		    L, "'imgui.TextInput()' argument 3 should be a number"
90 		);
91 	    }
92 	    flags = ImGuiInputTextFlags(lua_tonumber(L,3));
93 	}
94 
95 	const char* label  = lua_tostring(L,1);
96 	const char* str = lua_tostring(L,2);
97 	static char buff[geo_imgui_string_length];
98 	strcpy(buff,str);
99 	bool result = ImGui::InputText(
100 	    label, buff, geo_imgui_string_length, flags
101 	);
102 	lua_pushboolean(L,result);
103 	lua_pushstring(L,buff);
104 
105 
106 	return 2;
107     }
108 
109 
wrapper_Combo(lua_State * L)110     int wrapper_Combo(lua_State* L) {
111 	if(lua_gettop(L) != 3) {
112 	    return luaL_error(
113 		L, "'imgui.Combo()' invalid number of arguments"
114 	    );
115 	}
116 
117 	if(!lua_isstring(L,1)) {
118 	    return luaL_error(
119 		L, "'imgui.Combo()' argument should be a string"
120 	    );
121 	}
122 
123 	if(!lua_isstring(L,2)) {
124 	    return luaL_error(
125 		L, "'imgui.Combo()' argument should be a string"
126 	    );
127 	}
128 
129 	if(!lua_isstring(L,3)) {
130 	    return luaL_error(
131 		L, "'imgui.Combo()' argument should be a string"
132 	    );
133 	}
134 
135 	const char* label = lua_tostring(L,1);
136 	const char* current_item = lua_tostring(L,2);
137 	const char* items = lua_tostring(L,3);
138 
139 	char* lua_items = (char*)alloca(strlen(items)+2);
140 	strcpy(lua_items,items);
141 	{
142 	    size_t n = strlen(lua_items);
143 	    lua_items[n] = ';';
144 	    lua_items[n+1] = '\0';
145 	}
146 
147 	int lua_current_item=0;
148 
149 	const char* prev_item = lua_items;
150 	int nb_items = 0;
151 
152 	char* p = lua_items;
153 	while(*p != '\0') {
154 	    if(*p == ';') {
155 		*p = '\0';
156 		if(!strcmp(prev_item, current_item)) {
157 		    lua_current_item = nb_items;
158 		}
159 		prev_item = p+1;
160 		++nb_items;
161 	    }
162 	    ++p;
163 	}
164 	*p = '\0'; // Double '\0' to indicate end of item list to lua.
165 
166 	bool result = ImGui::Combo(label, &lua_current_item, lua_items);
167 
168 	current_item = lua_items;
169 	while(lua_current_item > 0) {
170 	    while(*current_item) {
171 		++current_item;
172 	    }
173 	    ++current_item;
174 	    --lua_current_item;
175 	}
176 
177 	lua_pushboolean(L, result);
178 	lua_pushstring(L, current_item);
179 
180 	return 2;
181     }
182 
wrapper_ColorEdit3WithPalette(lua_State * L)183     int wrapper_ColorEdit3WithPalette(
184 	lua_State* L
185     ) {
186 	if(lua_gettop(L) != 4) {
187 	    return luaL_error(
188 		L, "'imgui.ColorEdit3WithPalette()' invalid number of arguments"
189 	    );
190 	}
191 
192 	if(!lua_isstring(L,1)) {
193 	    return luaL_error(
194 		L, "'imgui.ColorEdit3WithPalette()' argument 1 should be a string"
195 	    );
196 	}
197 
198 	if(!lua_isnumber(L,2)) {
199 	    return luaL_error(
200 		L, "'imgui.ColorEdit3WithPalette()' argument 2 should be a number"
201 	    );
202 	}
203 
204 	if(!lua_isnumber(L,3)) {
205 	    return luaL_error(
206 		L, "'imgui.ColorEdit3WithPalette()' argument 3 should be a number"
207 	    );
208 	}
209 
210 	if(!lua_isnumber(L,4)) {
211 	    return luaL_error(
212 		L, "'imgui.ColorEdit3WithPalette()' argument 4 should be a number"
213 	    );
214 	}
215 
216 	const char* label = lua_tostring(L,1);
217 
218 	float rgb[3];
219 	rgb[0] = float(lua_tonumber(L,2));
220 	rgb[1] = float(lua_tonumber(L,3));
221 	rgb[2] = float(lua_tonumber(L,4));
222 
223 	bool sel = ImGui::ColorEdit3WithPalette(
224 	    label, rgb
225 	);
226 
227 	lua_pushboolean(L,sel);
228 	lua_pushnumber(L,double(rgb[0]));
229 	lua_pushnumber(L,double(rgb[1]));
230 	lua_pushnumber(L,double(rgb[2]));
231 
232 	return 4;
233     }
234 
wrapper_ColorEdit4WithPalette(lua_State * L)235     int wrapper_ColorEdit4WithPalette(
236 	lua_State* L
237     ) {
238 	if(lua_gettop(L) != 5) {
239 	    return luaL_error(
240 		L, "'imgui.ColorEdit3WithPalette()' invalid number of arguments"
241 	    );
242 	}
243 
244 	if(!lua_isstring(L,1)) {
245 	    return luaL_error(
246 		L, "'imgui.ColorEdit3WithPalette()' argument 1 should be a string"
247 	    );
248 	}
249 
250 	if(!lua_isnumber(L,2)) {
251 	    return luaL_error(
252 		L, "'imgui.ColorEdit3WithPalette()' argument 2 should be a number"
253 	    );
254 	}
255 
256 	if(!lua_isnumber(L,3)) {
257 	    return luaL_error(
258 		L, "'imgui.ColorEdit3WithPalette()' argument 3 should be a number"
259 	    );
260 	}
261 
262 	if(!lua_isnumber(L,4)) {
263 	    return luaL_error(
264 		L, "'imgui.ColorEdit3WithPalette()' argument 4 should be a number"
265 	    );
266 	}
267 
268 	if(!lua_isnumber(L,5)) {
269 	    return luaL_error(
270 		L, "'imgui.ColorEdit3WithPalette()' argument 5 should be a number"
271 	    );
272 	}
273 
274 	const char* label = lua_tostring(L,1);
275 
276 	float rgb[4];
277 	rgb[0] = float(lua_tonumber(L,2));
278 	rgb[1] = float(lua_tonumber(L,3));
279 	rgb[2] = float(lua_tonumber(L,4));
280 	rgb[3] = float(lua_tonumber(L,5));
281 
282 	bool sel = ImGui::ColorEdit4WithPalette(
283 	    label, rgb
284 	);
285 
286 	lua_pushboolean(L,sel);
287 	lua_pushnumber(L,double(rgb[0]));
288 	lua_pushnumber(L,double(rgb[1]));
289 	lua_pushnumber(L,double(rgb[2]));
290 	lua_pushnumber(L,double(rgb[3]));
291 
292 	return 5;
293     }
294 
295 
wrapper_OpenFileDialog(lua_State * L)296     int wrapper_OpenFileDialog(
297 	lua_State* L
298     ) {
299 	if(lua_gettop(L) != 4) {
300 	    return luaL_error(
301 		L, "'imgui.OpenFileDialog()' invalid number of arguments"
302 	    );
303 	}
304 
305 	if(!lua_isstring(L,1)) {
306 	    return luaL_error(
307 		L, "'imgui.OpenFileDialog()' argument 1 should be a string"
308 	    );
309 	}
310 
311 	if(!lua_isstring(L,2)) {
312 	    return luaL_error(
313 		L, "'imgui.OpenFileDialog()' argument 2 should be a string"
314 	    );
315 	}
316 
317 	if(!lua_isstring(L,3)) {
318 	    return luaL_error(
319 		L, "'imgui.OpenFileDialog()' argument 3 should be a string"
320 	    );
321 	}
322 
323 	if(!lua_isnumber(L,4)) {
324 	    return luaL_error(
325 		L, "'imgui.OpenFileDialog()' argument 4 should be a number"
326 	    );
327 	}
328 
329 	const char* label      = lua_tostring(L,1);
330 	const char* extensions = lua_tostring(L,2);
331 	const char* filename   = lua_tostring(L,3);
332 	ImGuiExtFileDialogFlags flags =
333 	    ImGuiExtFileDialogFlags(lua_tonumber(L,4));
334 
335 	ImGui::OpenFileDialog(label, extensions, filename, flags);
336 
337 	return 0;
338     }
339 
wrapper_FileDialog(lua_State * L)340     int wrapper_FileDialog(
341 	lua_State* L
342     ) {
343 	if(lua_gettop(L) != 2) {
344 	    return luaL_error(
345 		L, "'imgui.FileDialog()' invalid number of arguments"
346 	    );
347 	}
348 
349 	if(!lua_isstring(L,1)) {
350 	    return luaL_error(
351 		L, "'imgui.OpenFileDialog()' argument 1 should be a string"
352 	    );
353 	}
354 
355 	if(!lua_isstring(L,2)) {
356 	    return luaL_error(
357 		L, "'imgui.OpenFileDialog()' argument 2 should be a string"
358 	    );
359 	}
360 
361 	const char* label      = lua_tostring(L,1);
362 	char filename[geo_imgui_string_length];
363 
364 	const char* filename_in = lua_tostring(L,2);
365 	if(filename_in != nullptr) {
366 	    if(strlen(filename_in) > geo_imgui_string_length + 1) {
367 		Logger::err("ImGui") << "Max file name length exceeded"
368 				     << std::endl;
369 		return false;
370 	    }
371 	    strcpy(filename, filename_in);
372 	} else {
373 	    filename[0] = '\0';
374 	}
375 
376 	bool result =
377 	    ImGui::FileDialog(label, filename, geo_imgui_string_length);
378 
379 	lua_pushboolean(L,result);
380 	lua_pushstring(L, result ? filename : filename_in);
381 
382 	return 2;
383     }
384 
wrapper_SetNextWindowPos(lua_State * L)385     int wrapper_SetNextWindowPos(lua_State* L) {
386 	if(
387 	    lua_gettop(L) != 2 &&
388 	    lua_gettop(L) != 3
389 	) {
390 	    return luaL_error(
391 		L, "'imgui.SetNextWindowPos()' invalid number of arguments"
392 	    );
393 	}
394 
395 	if(!lua_isnumber(L,1)) {
396 	    return luaL_error(
397 		L, "'imgui.SetNextWindowPos()' argument 1 should be a number"
398 	    );
399 	}
400 
401 	if(!lua_isnumber(L,2)) {
402 	    return luaL_error(
403 		L, "'imgui.SetNextWindowPos()' argument 2 should be a number"
404 	    );
405 	}
406 
407 	ImGuiCond cond = 0;
408 	if(lua_gettop(L) == 3) {
409 	    if(!lua_isnumber(L,3)) {
410 		return luaL_error(
411 		    L,
412 		    "'imgui.SetNextWindowPos()' argument 3 should be a number"
413 		);
414 	    }
415 	    cond = ImGuiCond(lua_tonumber(L,3));
416 	}
417 
418 
419 	ImGui::SetNextWindowPos(
420 	    ImVec2(float(lua_tonumber(L,1)), float(lua_tonumber(L,2))),
421 	    cond
422 	);
423 
424 	return 0;
425     }
426 
wrapper_SetNextWindowSize(lua_State * L)427     int wrapper_SetNextWindowSize(lua_State* L) {
428 	if(
429 	    lua_gettop(L) != 2 &&
430 	    lua_gettop(L) != 3
431 	) {
432 	    return luaL_error(
433 		L, "'imgui.SetNextWindowSize()' invalid number of arguments"
434 	    );
435 	}
436 
437 	if(!lua_isnumber(L,1)) {
438 	    return luaL_error(
439 		L, "'imgui.SetNextWindowSize()' argument 1 should be a number"
440 	    );
441 	}
442 
443 	if(!lua_isnumber(L,2)) {
444 	    return luaL_error(
445 		L, "'imgui.SetNextWindowSize()' argument 2 should be a number"
446 	    );
447 	}
448 
449 	ImGuiCond cond = 0;
450 	if(lua_gettop(L) == 3) {
451 	    if(!lua_isnumber(L,3)) {
452 		return luaL_error(
453 		    L,
454 		    "'imgui.SetNextWindowSize()' argument 3 should be a number"
455 		);
456 	    }
457 	    cond = ImGuiCond(lua_tonumber(L,3));
458 	}
459 
460 
461 	ImGui::SetNextWindowSize(
462 	    ImVec2(float(lua_tonumber(L,1)), float(lua_tonumber(L,2))),
463 	    cond
464 	);
465 
466 	return 0;
467     }
468 
469 
wrapper_IsItemHovered(lua_State * L)470     int wrapper_IsItemHovered(lua_State* L) {
471 	if(lua_gettop(L) != 0) {
472 	    return luaL_error(
473 		L, "'imgui.IsItemHovered()' invalid number of arguments"
474 	    );
475 	}
476 	lua_pushboolean(L,ImGui::IsItemHovered());
477 	return 1;
478     }
479 
wrapper_Text(lua_State * L)480     int wrapper_Text(lua_State* L) {
481 	if(lua_gettop(L) < 1) {
482 	    return luaL_error(
483 		L, "'imgui.Text()' invalid number of arguments"
484 	    );
485 	}
486 	const char* str = lua_tostring(L,1);
487 	ImGui::Text("%s",str);
488 	return 0;
489     }
490 
wrapper_SetTooltip(lua_State * L)491     int wrapper_SetTooltip(lua_State* L) {
492 	if(lua_gettop(L) != 1) {
493 	    return luaL_error(
494 		L, "'imgui.SetTooltip()' invalid number of arguments"
495 	    );
496 	}
497 	const char* str = lua_tostring(L,1);
498 	ImGui::SetTooltip("%s",str);
499 	return 0;
500     }
501 
wrapper_ShowStyleEditor(lua_State * L)502     int wrapper_ShowStyleEditor(lua_State* L) {
503 	if(lua_gettop(L) != 0) {
504 	    return luaL_error(
505 		L, "'imgui.ShowStyleEditor()' invalid number of arguments"
506 	    );
507 	}
508 	ImGui::ShowStyleEditor(nullptr);
509 	return 0;
510     }
511 
wrapper_PushFont(lua_State * L)512     int wrapper_PushFont(lua_State* L) {
513 	if(lua_gettop(L) != 1) {
514 	    return luaL_error(
515 		L, "'imgui.PushFont()' invalid number of arguments"
516 	    );
517 	}
518 	if(!lua_isinteger(L,1)) {
519 	    return luaL_error(
520 		L, "'imgui.PushFont()' argument is not an integer"
521 	    );
522 	}
523 	int idx = int(lua_tointeger(L,1));
524 	if(idx < 0 || idx >= ImGui::GetIO().Fonts->Fonts.size()) {
525 	    return luaL_error(
526 		L, "'imgui.PushFont()' invalid font index"
527 	    );
528 	}
529 	ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[idx]);
530 	return 0;
531     }
532 
wrapper_font_icon(lua_State * L)533     int wrapper_font_icon(lua_State* L) {
534 	if(lua_gettop(L) != 1) {
535 	    return luaL_error(
536 		L, "'imgui.font_icon()' invalid number of arguments"
537 	    );
538 	}
539 	if(!lua_isstring(L,1)) {
540 	    return luaL_error(
541 		L, "'imgui.font_icon()' argument is not a string"
542 	    );
543 	}
544 	const char* K = lua_tostring(L,1);
545 	wchar_t result[2];
546 	result[0] = icon_wchar(K);
547 	result[1] = '\0';
548 	std::string result_str = String::wchar_to_UTF8(result);
549 	lua_pushstring(L, result_str.c_str());
550 	return 1;
551     }
552 
wrapper_BeginTabBar(lua_State * L)553     int wrapper_BeginTabBar(lua_State* L) {
554 	if(lua_gettop(L) != 1) {
555 	    return luaL_error(
556 		L, "'imgui.BeginTabBar()' invalid number of arguments"
557 	    );
558 	}
559 	if(!lua_isstring(L,1)) {
560 	    return luaL_error(
561 		L, "'imgui.BeinTabBar()' argument is not a string"
562 	    );
563 	}
564 	const char* K = lua_tostring(L,1);
565 	ImGui::BeginTabBar(K);
566 	return 0;
567     }
568 
wrapper_BeginTabItem(lua_State * L)569     int wrapper_BeginTabItem(lua_State* L) {
570 	if(lua_gettop(L) != 1) {
571 	    return luaL_error(
572 		L, "'imgui.BeginTabItem()' invalid number of arguments"
573 	    );
574 	}
575 	if(!lua_isstring(L,1)) {
576 	    return luaL_error(
577 		L, "'imgui.BeginTabItem()' argument is not a string"
578 	    );
579 	}
580 	const char* K = lua_tostring(L,1);
581 	lua_pushboolean(L,ImGui::BeginTabItem(K));
582 	return 1;
583     }
584 
wrapper_SimpleButton(lua_State * L)585     int wrapper_SimpleButton(lua_State* L) {
586 	if(lua_gettop(L) != 1) {
587 	    return luaL_error(
588 		L, "'imgui.SimpleButton()' invalid number of arguments"
589 	    );
590 	}
591 	if(!lua_isstring(L,1)) {
592 	    return luaL_error(
593 		L, "'imgui.SimpleButton()' argument is not a string"
594 	    );
595 	}
596 	const char* K = lua_tostring(L,1);
597 	lua_pushboolean(L,ImGui::SimpleButton(K));
598 	return 1;
599     }
600 
wrapper_GetMousePos(lua_State * L)601     int wrapper_GetMousePos(lua_State* L) {
602 	if(lua_gettop(L) != 0) {
603 	    return luaL_error(
604 		L, "'imgui.GetMousePos()' invalid number of arguments"
605 	    );
606 	}
607 	lua_pushnumber(L,double(ImGui::GetIO().MousePos.x));
608 	lua_pushnumber(L,double(ImGui::GetIO().MousePos.y));
609 	return 2;
610     }
611 
612 }
613 
614 namespace GEO {
615 
616     /**
617      * \brief Specialization of lua_push() for ImDrawList*
618      */
lua_push(lua_State * L,ImDrawList * x)619     template<> inline void lua_push(
620 	lua_State* L, ImDrawList* x
621     ) {
622 	lua_pushlightuserdata(L,(void*)x);
623     }
624 
625     /**
626      * \brief lua_to specialization for ImDrawList*
627      */
628     template<> class lua_to<ImDrawList*> {
629       public:
lua_to(lua_State * L,int idx)630 	lua_to(lua_State* L, int idx) {
631 	    x_ = (ImDrawList*)(lua_touserdata(L,idx));
632 	}
can_convert(lua_State * L,int idx)633 	static bool can_convert(lua_State* L, int idx) {
634 	    return lua_check_type(L, idx, my_lua_islightuserdata);
635 	}
operator ImDrawList*() const636 	operator ImDrawList*() const {
637 	    return x_;
638 	}
639       private:
640 	ImDrawList* x_;
641     };
642 
643 }
644 
645 // WIP: export all ImGuiDrawList functions to LUA
646 
647 namespace ImGuiDrawAdapters {
648 
649     // Needed by lua_bindwrapper because ImGui::GetBackgroundDrawList()
650     // takes an ImViewport (default = nullptr) as an argunemt.
GetBackgroundDrawList()651     static ImDrawList* GetBackgroundDrawList() {
652 	return ImGui::GetBackgroundDrawList();
653     }
654 
655     // Needed by lua_bindwrapper because ImGui::GetForegroundDrawList()
656     // takes an ImViewport (default = nullptr) as an argunemt.
GetForegroundDrawList()657     static ImDrawList* GetForegroundDrawList() {
658 	return ImGui::GetForegroundDrawList();
659     }
660 
PushClipRect(ImDrawList * list,float xmin,float ymin,float xmax,float ymax,bool intersect)661     static void PushClipRect(
662 	ImDrawList* list,
663 	float xmin, float ymin,
664 	float xmax, float ymax,
665 	bool intersect
666     ) {
667 	list->PushClipRect(
668 	    ImVec2(xmin, ymin),
669 	    ImVec2(xmax, ymax),
670 	    intersect
671 	);
672     }
673 
PushClipRectFullScreen(ImDrawList * list)674     static void PushClipRectFullScreen(ImDrawList* list) {
675 	list->PushClipRectFullScreen();
676     }
677 
PopClipRect(ImDrawList * list)678     static void PopClipRect(ImDrawList* list) {
679 	list->PopClipRect();
680     }
681 
PushTextureID(ImDrawList * list,index_t id)682     static void PushTextureID(ImDrawList* list, index_t id) {
683 	union {
684 	    ImTextureID im_texture_id;
685 	    index_t gl_texture_id;
686 	};
687 	gl_texture_id = id;
688 	list->PushTextureID(im_texture_id);
689     }
690 
PopTextureID(ImDrawList * list)691     static void PopTextureID(ImDrawList* list) {
692 	list->PopClipRect();
693     }
694 
AddLine(ImDrawList * list,float x1,float y1,float x2,float y2,Numeric::uint32 color,float thickness)695     static void AddLine(
696 	ImDrawList* list, float x1, float y1, float x2, float y2,
697 	Numeric::uint32 color, float thickness
698     ) {
699 	list->AddLine(
700 	    ImVec2(x1,y1), ImVec2(x2,y2),
701 	    color, thickness
702 	);
703     }
704 
AddRect(ImDrawList * list,float x1,float y1,float x2,float y2,Numeric::uint32 color,float rounding,int rounding_corners,float thickness)705     static void AddRect(
706 	ImDrawList* list,
707 	float x1, float y1, float x2, float y2,
708 	Numeric::uint32 color, float rounding, int rounding_corners,
709 	float thickness
710     ) {
711 	list->AddRect(
712 	    ImVec2(x1,y1), ImVec2(x2,y2), color, rounding,
713 	    ImDrawCornerFlags(rounding_corners), thickness
714 	);
715     }
716 
AddRectFilled(ImDrawList * list,float x1,float y1,float x2,float y2,Numeric::uint32 color,float rounding,int rounding_corners)717     static void AddRectFilled(
718 	ImDrawList* list,
719 	float x1, float y1, float x2, float y2,
720 	Numeric::uint32 color, float rounding, int rounding_corners
721     ) {
722 	list->AddRectFilled(
723 	    ImVec2(x1,y1), ImVec2(x2,y2), color, rounding,
724 	    ImDrawCornerFlags(rounding_corners)
725 	);
726     }
727 
AddRectFilledMultiColor(ImDrawList * list,float x1,float y1,float x2,float y2,Numeric::uint32 color1,Numeric::uint32 color2,Numeric::uint32 color3,Numeric::uint32 color4)728     static void AddRectFilledMultiColor(
729 	ImDrawList* list,
730 	float x1, float y1, float x2, float y2,
731 	Numeric::uint32 color1,	Numeric::uint32 color2,
732 	Numeric::uint32 color3,	Numeric::uint32 color4
733     ) {
734 	list->AddRectFilledMultiColor(
735 	    ImVec2(x1,y1), ImVec2(x2,y2),
736 	    color1, color2, color3, color4
737 	);
738     }
739 
AddQuad(ImDrawList * list,float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4,Numeric::uint32 color,float thickness)740     static void AddQuad(
741 	ImDrawList* list,
742 	float x1, float y1, float x2, float y2,
743 	float x3, float y3, float x4, float y4,
744 	Numeric::uint32 color,
745 	float thickness
746     ) {
747 	list->AddQuad(
748 	    ImVec2(x1,y1), ImVec2(x2,y2), ImVec2(x3,y3), ImVec2(x4,y4),
749 	    color, thickness
750 	);
751     }
752 
AddQuadFilled(ImDrawList * list,float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4,Numeric::uint32 color)753     static void AddQuadFilled(
754 	ImDrawList* list, float x1, float y1, float x2, float y2,
755 	float x3, float y3, float x4, float y4,	Numeric::uint32 color
756     ) {
757 	list->AddQuad(
758 	    ImVec2(x1,y1), ImVec2(x2,y2), ImVec2(x3,y3), ImVec2(x4,y4), color
759 	);
760     }
761 
AddTriangle(ImDrawList * list,float x1,float y1,float x2,float y2,float x3,float y3,Numeric::uint32 color,float thickness)762     static void AddTriangle(
763 	ImDrawList* list, float x1, float y1, float x2, float y2,
764 	float x3, float y3, Numeric::uint32 color, float thickness
765     ) {
766 	list->AddTriangle(
767 	    ImVec2(x1,y1), ImVec2(x2,y2), ImVec2(x3,y3), color, thickness
768 	);
769     }
770 
AddTriangleFilled(ImDrawList * list,float x1,float y1,float x2,float y2,float x3,float y3,Numeric::uint32 color)771     static void AddTriangleFilled(
772 	ImDrawList* list, float x1, float y1, float x2, float y2,
773 	float x3, float y3, Numeric::uint32 color
774     ) {
775 	list->AddTriangleFilled(ImVec2(x1,y1), ImVec2(x2,y2), ImVec2(x3,y3), color);
776     }
777 
AddCircle(ImDrawList * list,float x,float y,float radius,Numeric::uint32 color,int num_segments,float thickness)778     static void AddCircle(
779 	ImDrawList* list, float x, float y, float radius, Numeric::uint32 color,
780 	int num_segments, float thickness
781     ) {
782 	list->AddCircle(ImVec2(x,y), radius, color, num_segments, thickness);
783     }
784 
AddCircleFilled(ImDrawList * list,float x,float y,float radius,Numeric::uint32 color,int num_segments)785     static void AddCircleFilled(
786 	ImDrawList* list, float x, float y, float radius, Numeric::uint32 color,
787 	int num_segments
788     ) {
789 	list->AddCircleFilled(ImVec2(x,y), radius, color, num_segments);
790     }
791 
AddText(ImDrawList * list,float x,float y,index_t color,const char * text)792     static void AddText(
793 	ImDrawList* list, float x, float y, index_t color, const char* text
794     ) {
795 	list->AddText(ImVec2(x,y), color, text);
796     }
797 
AddText2(ImDrawList * list,index_t font,float font_size,float x,float y,index_t color,const char * text)798     static void AddText2(
799 	ImDrawList* list, index_t font, float font_size, float x, float y,
800 	index_t color, const char* text
801     ) {
802 	if(int(font) >= ImGui::GetIO().Fonts->Fonts.size()) {
803 	    return;
804 	}
805 	ImFont* imfont = ImGui::GetIO().Fonts->Fonts[int(font)];
806 	list->AddText(imfont, font_size, ImVec2(x,y), color, text);
807     }
808 
AddBezierCurve(ImDrawList * list,float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4,index_t color,float thickness,int num_segments)809     static void AddBezierCurve(
810 	ImDrawList* list, float x1, float y1, float x2, float y2,
811 	float x3, float y3, float x4, float y4, index_t color,
812 	float thickness, int num_segments
813     ) {
814 	list->AddBezierCurve(
815 	    ImVec2(x1,y1), ImVec2(x2,y2), ImVec2(x3,y3), ImVec2(x4,y4),
816 	    color, thickness, num_segments
817 	);
818     }
819 
AddImage(ImDrawList * list,index_t id,float x1,float y1,float x2,float y2,float u1,float v1,float u2,float v2,index_t color)820     static void AddImage(
821 	ImDrawList* list, index_t id,
822 	float x1, float y1, float x2, float y2,
823 	float u1, float v1, float u2, float v2,
824 	index_t color
825     ) {
826 	union {
827 	    ImTextureID im_texture_id;
828 	    index_t gl_texture_id;
829 	};
830 	gl_texture_id = id;
831 	list->AddImage(
832 	    im_texture_id,
833 	    ImVec2(x1,y1), ImVec2(x2,y2),
834 	    ImVec2(u1,v1), ImVec2(u2,v2),
835 	    color
836 	);
837     }
838 
AddImageRounded(ImDrawList * list,index_t id,float x1,float y1,float x2,float y2,float u1,float v1,float u2,float v2,index_t color,float rounding,int rounding_corners)839     static void AddImageRounded(
840 	ImDrawList* list, index_t id,
841 	float x1, float y1, float x2, float y2,
842 	float u1, float v1, float u2, float v2,
843 	index_t color, float rounding, int rounding_corners
844     ) {
845 	union {
846 	    ImTextureID im_texture_id;
847 	    index_t gl_texture_id;
848 	};
849 	gl_texture_id = id;
850 	list->AddImageRounded(
851 	    im_texture_id,
852 	    ImVec2(x1,y1), ImVec2(x2,y2),
853 	    ImVec2(u1,v1), ImVec2(u2,v2),
854 	    color, rounding, ImDrawCornerFlags(rounding_corners)
855 	);
856     }
857 
PathClear(ImDrawList * list)858     static void PathClear(ImDrawList* list) {
859 	list->PathClear();
860     }
861 
PathLineTo(ImDrawList * list,float x,float y)862     static void PathLineTo(ImDrawList* list, float x, float y) {
863 	list->PathLineTo(ImVec2(x,y));
864     }
865 
PathLineToMergeDuplicate(ImDrawList * list,float x,float y)866     static void PathLineToMergeDuplicate(ImDrawList* list, float x, float y) {
867 	list->PathLineToMergeDuplicate(ImVec2(x,y));
868     }
869 
PathFillConvex(ImDrawList * list,index_t color)870     static void PathFillConvex(ImDrawList* list, index_t color) {
871 	list->PathFillConvex(color);
872     }
873 
PathStroke(ImDrawList * list,index_t color,bool closed,float thickness)874     static void PathStroke(
875 	ImDrawList* list, index_t color, bool closed, float thickness
876     ) {
877 	list->PathStroke(color, closed, thickness);
878     }
879 
PathArcTo(ImDrawList * list,float cx,float cy,float radius,float a1,float a2,int num_segments)880     static void PathArcTo(
881 	ImDrawList* list, float cx, float cy, float radius, float a1, float a2,
882 	int num_segments
883     ) {
884 	list->PathArcTo(ImVec2(cx,cy), radius, a1, a2, num_segments);
885     }
886 
PathArcToFast(ImDrawList * list,float cx,float cy,float radius,int a1,int a2)887     static void PathArcToFast(
888 	ImDrawList* list, float cx, float cy, float radius, int a1, int a2
889     ) {
890 	list->PathArcToFast(ImVec2(cx,cy), radius, a1, a2);
891     }
892 
PathBezierCurveTo(ImDrawList * list,float x1,float y1,float x2,float y2,float x3,float y3,int num_segments)893     static void PathBezierCurveTo(
894 	ImDrawList* list,
895 	float x1, float y1, float x2, float y2, float x3, float y3,
896 	int num_segments
897     ) {
898 	list->PathBezierCurveTo(
899 	    ImVec2(x1,y1), ImVec2(x2,y2), ImVec2(x3,y3), num_segments
900 	);
901     }
902 
PathRect(ImDrawList * list,float x1,float y1,float x2,float y2,float rounding,int rounding_corners)903     static void PathRect(
904 	ImDrawList* list,
905 	float x1, float y1, float x2, float y2,
906 	float rounding, int rounding_corners
907     ) {
908 	list->PathRect(
909 	    ImVec2(x1,y1), ImVec2(x2,y2),
910 	    rounding, ImDrawCornerFlags(rounding_corners)
911 	);
912     }
913 }
914 
915 
916 #define DECLARE_IMGUI_CONSTANT(C) \
917 	lua_pushinteger(L,C);     \
918 	lua_setglobal(L,#C)
919 
920 
init_lua_imgui(lua_State * L)921 void init_lua_imgui(lua_State* L) {
922     lState = L;
923     LoadImguiBindings();
924 
925     DECLARE_IMGUI_CONSTANT(ImGuiExtFileDialogFlags_Load);
926     DECLARE_IMGUI_CONSTANT(ImGuiExtFileDialogFlags_Save);
927     DECLARE_IMGUI_CONSTANT(ImGuiCond_Always);
928     DECLARE_IMGUI_CONSTANT(ImGuiCond_Once);
929     DECLARE_IMGUI_CONSTANT(ImGuiCond_FirstUseEver);
930     DECLARE_IMGUI_CONSTANT(ImGuiCond_Appearing);
931     DECLARE_IMGUI_CONSTANT(ImGuiSelectableFlags_AllowDoubleClick);
932 
933     DECLARE_IMGUI_CONSTANT(ImGuiCol_Text);
934     DECLARE_IMGUI_CONSTANT(ImGuiCol_TextDisabled);
935     DECLARE_IMGUI_CONSTANT(ImGuiCol_WindowBg);
936     DECLARE_IMGUI_CONSTANT(ImGuiCol_ChildBg);
937     DECLARE_IMGUI_CONSTANT(ImGuiCol_PopupBg);
938     DECLARE_IMGUI_CONSTANT(ImGuiCol_Border);
939     DECLARE_IMGUI_CONSTANT(ImGuiCol_BorderShadow);
940     DECLARE_IMGUI_CONSTANT(ImGuiCol_FrameBg);
941     DECLARE_IMGUI_CONSTANT(ImGuiCol_FrameBgHovered);
942     DECLARE_IMGUI_CONSTANT(ImGuiCol_FrameBgActive);
943     DECLARE_IMGUI_CONSTANT(ImGuiCol_TitleBg);
944     DECLARE_IMGUI_CONSTANT(ImGuiCol_TitleBgActive);
945     DECLARE_IMGUI_CONSTANT(ImGuiCol_TitleBgCollapsed);
946     DECLARE_IMGUI_CONSTANT(ImGuiCol_MenuBarBg);
947     DECLARE_IMGUI_CONSTANT(ImGuiCol_ScrollbarBg);
948     DECLARE_IMGUI_CONSTANT(ImGuiCol_ScrollbarGrab);
949     DECLARE_IMGUI_CONSTANT(ImGuiCol_ScrollbarGrabHovered);
950     DECLARE_IMGUI_CONSTANT(ImGuiCol_ScrollbarGrabActive);
951     DECLARE_IMGUI_CONSTANT(ImGuiCol_CheckMark);
952     DECLARE_IMGUI_CONSTANT(ImGuiCol_SliderGrab);
953     DECLARE_IMGUI_CONSTANT(ImGuiCol_SliderGrabActive);
954     DECLARE_IMGUI_CONSTANT(ImGuiCol_Button);
955     DECLARE_IMGUI_CONSTANT(ImGuiCol_ButtonHovered);
956     DECLARE_IMGUI_CONSTANT(ImGuiCol_ButtonActive);
957     DECLARE_IMGUI_CONSTANT(ImGuiCol_Header);
958     DECLARE_IMGUI_CONSTANT(ImGuiCol_HeaderHovered);
959     DECLARE_IMGUI_CONSTANT(ImGuiCol_HeaderActive);
960     DECLARE_IMGUI_CONSTANT(ImGuiCol_Separator);
961     DECLARE_IMGUI_CONSTANT(ImGuiCol_SeparatorHovered);
962     DECLARE_IMGUI_CONSTANT(ImGuiCol_SeparatorActive);
963     DECLARE_IMGUI_CONSTANT(ImGuiCol_ResizeGrip);
964     DECLARE_IMGUI_CONSTANT(ImGuiCol_ResizeGripHovered);
965     DECLARE_IMGUI_CONSTANT(ImGuiCol_ResizeGripActive);
966     DECLARE_IMGUI_CONSTANT(ImGuiCol_Tab);
967     DECLARE_IMGUI_CONSTANT(ImGuiCol_TabHovered);
968     DECLARE_IMGUI_CONSTANT(ImGuiCol_TabActive);
969     DECLARE_IMGUI_CONSTANT(ImGuiCol_TabUnfocused);
970     DECLARE_IMGUI_CONSTANT(ImGuiCol_TabUnfocusedActive);
971     DECLARE_IMGUI_CONSTANT(ImGuiCol_DockingPreview);
972     DECLARE_IMGUI_CONSTANT(ImGuiCol_DockingEmptyBg);
973     DECLARE_IMGUI_CONSTANT(ImGuiCol_PlotLines);
974     DECLARE_IMGUI_CONSTANT(ImGuiCol_PlotLinesHovered);
975     DECLARE_IMGUI_CONSTANT(ImGuiCol_PlotHistogram);
976     DECLARE_IMGUI_CONSTANT(ImGuiCol_PlotHistogramHovered);
977     DECLARE_IMGUI_CONSTANT(ImGuiCol_TextSelectedBg);
978     DECLARE_IMGUI_CONSTANT(ImGuiCol_DragDropTarget);
979     DECLARE_IMGUI_CONSTANT(ImGuiCol_NavHighlight);
980     DECLARE_IMGUI_CONSTANT(ImGuiCol_NavWindowingHighlight);
981     DECLARE_IMGUI_CONSTANT(ImGuiCol_NavWindowingDimBg);
982     DECLARE_IMGUI_CONSTANT(ImGuiCol_ModalWindowDimBg);
983 
984     lua_getglobal(L, "imgui");
985 
986     lua_pushliteral(L,"TextInput");
987     lua_pushcfunction(L,wrapper_TextInput);
988     lua_settable(L,-3);
989 
990     lua_pushliteral(L,"Combo");
991     lua_pushcfunction(L,wrapper_Combo);
992     lua_settable(L,-3);
993 
994     lua_pushliteral(L,"ColorEdit3WithPalette");
995     lua_pushcfunction(L,wrapper_ColorEdit3WithPalette);
996     lua_settable(L,-3);
997 
998     lua_pushliteral(L,"ColorEdit4WithPalette");
999     lua_pushcfunction(L,wrapper_ColorEdit4WithPalette);
1000     lua_settable(L,-3);
1001 
1002     lua_pushliteral(L,"OpenFileDialog");
1003     lua_pushcfunction(L,wrapper_OpenFileDialog);
1004     lua_settable(L,-3);
1005 
1006     lua_pushliteral(L,"FileDialog");
1007     lua_pushcfunction(L,wrapper_FileDialog);
1008     lua_settable(L,-3);
1009 
1010     lua_pushliteral(L,"SetNextWindowPos");
1011     lua_pushcfunction(L,wrapper_SetNextWindowPos);
1012     lua_settable(L,-3);
1013 
1014     lua_pushliteral(L,"SetNextWindowSize");
1015     lua_pushcfunction(L,wrapper_SetNextWindowSize);
1016     lua_settable(L,-3);
1017 
1018     lua_pushliteral(L,"IsItemHovered");
1019     lua_pushcfunction(L,wrapper_IsItemHovered);
1020     lua_settable(L,-3);
1021 
1022     lua_pushliteral(L,"Text");
1023     lua_pushcfunction(L,wrapper_Text);
1024     lua_settable(L,-3);
1025 
1026     lua_pushliteral(L,"SetTooltip");
1027     lua_pushcfunction(L,wrapper_SetTooltip);
1028     lua_settable(L,-3);
1029 
1030     lua_pushliteral(L,"ShowStyleEditor");
1031     lua_pushcfunction(L,wrapper_ShowStyleEditor);
1032     lua_settable(L,-3);
1033 
1034     lua_pushliteral(L,"PushFont");
1035     lua_pushcfunction(L,wrapper_PushFont);
1036     lua_settable(L,-3);
1037 
1038     lua_pushliteral(L,"font_icon");
1039     lua_pushcfunction(L,wrapper_font_icon);
1040     lua_settable(L,-3);
1041 
1042     lua_pushliteral(L,"BeginTabBar");
1043     lua_pushcfunction(L,wrapper_BeginTabBar);
1044     lua_settable(L,-3);
1045 
1046     lua_pushliteral(L,"BeginTabItem");
1047     lua_pushcfunction(L,wrapper_BeginTabItem);
1048     lua_settable(L,-3);
1049 
1050     lua_pushliteral(L,"SimpleButton");
1051     lua_pushcfunction(L,wrapper_SimpleButton);
1052     lua_settable(L,-3);
1053 
1054     lua_pushliteral(L,"GetMousePos");
1055     lua_pushcfunction(L,wrapper_GetMousePos);
1056     lua_settable(L,-3);
1057 
1058     /*****************************************************************/
1059 
1060     lua_bindwrapper(L,ImGui::GetWindowDrawList);
1061     lua_bindwrapper(L,ImGuiDrawAdapters::GetBackgroundDrawList);
1062     lua_bindwrapper(L,ImGuiDrawAdapters::GetForegroundDrawList);
1063 
1064     lua_bindwrapper(L,ImGuiDrawAdapters::PushClipRect);
1065     lua_bindwrapper(L,ImGuiDrawAdapters::PushClipRectFullScreen);
1066     lua_bindwrapper(L,ImGuiDrawAdapters::PopClipRect);
1067 
1068     lua_bindwrapper(L,ImGuiDrawAdapters::PushTextureID);
1069     lua_bindwrapper(L,ImGuiDrawAdapters::PopTextureID);
1070 
1071     lua_bindwrapper(L,ImGuiDrawAdapters::AddLine);
1072     lua_bindwrapper(L,ImGuiDrawAdapters::AddRect);
1073     lua_bindwrapper(L,ImGuiDrawAdapters::AddRectFilled);
1074     lua_bindwrapper(L,ImGuiDrawAdapters::AddRectFilledMultiColor);
1075     lua_bindwrapper(L,ImGuiDrawAdapters::AddQuad);
1076     lua_bindwrapper(L,ImGuiDrawAdapters::AddQuadFilled);
1077     lua_bindwrapper(L,ImGuiDrawAdapters::AddTriangle);
1078     lua_bindwrapper(L,ImGuiDrawAdapters::AddTriangleFilled);
1079     lua_bindwrapper(L,ImGuiDrawAdapters::AddCircle);
1080     lua_bindwrapper(L,ImGuiDrawAdapters::AddCircleFilled);
1081     lua_bindwrapper(L,ImGuiDrawAdapters::AddText);
1082     lua_bindwrapper(L,ImGuiDrawAdapters::AddText2);
1083     lua_bindwrapper(L,ImGuiDrawAdapters::AddBezierCurve);
1084     lua_bindwrapper(L,ImGuiDrawAdapters::AddImage);
1085     lua_bindwrapper(L,ImGuiDrawAdapters::AddImageRounded);
1086     lua_bindwrapper(L,ImGuiDrawAdapters::PathClear);
1087     lua_bindwrapper(L,ImGuiDrawAdapters::PathLineTo);
1088     lua_bindwrapper(L,ImGuiDrawAdapters::PathLineToMergeDuplicate);
1089     lua_bindwrapper(L,ImGuiDrawAdapters::PathFillConvex);
1090     lua_bindwrapper(L,ImGuiDrawAdapters::PathStroke);
1091     lua_bindwrapper(L,ImGuiDrawAdapters::PathArcTo);
1092     lua_bindwrapper(L,ImGuiDrawAdapters::PathArcToFast);
1093     lua_bindwrapper(L,ImGuiDrawAdapters::PathBezierCurveTo);
1094     lua_bindwrapper(L,ImGuiDrawAdapters::PathRect);
1095 
1096     lua_pop(L,1);
1097 
1098     DECLARE_IMGUI_CONSTANT(ImDrawCornerFlags_None);
1099     DECLARE_IMGUI_CONSTANT(ImDrawCornerFlags_TopLeft);
1100     DECLARE_IMGUI_CONSTANT(ImDrawCornerFlags_TopRight);
1101     DECLARE_IMGUI_CONSTANT(ImDrawCornerFlags_BotLeft);
1102     DECLARE_IMGUI_CONSTANT(ImDrawCornerFlags_BotRight);
1103     DECLARE_IMGUI_CONSTANT(ImDrawCornerFlags_Top);
1104     DECLARE_IMGUI_CONSTANT(ImDrawCornerFlags_Bot);
1105     DECLARE_IMGUI_CONSTANT(ImDrawCornerFlags_Left);
1106     DECLARE_IMGUI_CONSTANT(ImDrawCornerFlags_Right);
1107     DECLARE_IMGUI_CONSTANT(ImDrawCornerFlags_All);
1108 
1109 }
1110 
1111