<Guide du Rootard GeeXLab/>

ImGui


Dernière mise à jour: 2018.12.10 par JeGX

>> Retour <<



ImGui est une librairie très populaire parmi les développeurs graphiques à la recherche d'une façon efficace de dessiner des widgets (fenêtres, sliders, checkboxes, etc.) sur leurs scènes 3D. ImGui répond à merveille à ce besoin très précis et ce pour toutes les APIs 3D (OpenGL, Vulkan et Direct3D).

Les fonctions d'ImGui sont accessibles dans GeeXLab via la librairie gh_imgui.

ImGui fonctionne selon un mode immédiat. Tous les widgets de l'interface graphique sont totalement reconstruits et rendus à chaque frame. Les fenêtres n'ont pas besoin d'être créées et initialisées avant d'être rendue comme c'est le cas avec les librairies de widgets classiques. Les widgets existent uniquement au moment où ils sont rendus. Pas avant ni après. La conséquence directe est une interface graphhique totalement dynamique qui peut évoluer et se métamorphoser de frame en frame.



La première chose à faire pour utiliser ImGui est de l'initialiser (en général dans un script INIT):

gh_imgui.init()


Et la dernière chose à faire (en général dans un script TERMINATE) avant de quitter la demo:

gh_imgui.terminate()


Maintenant, tout le reste du code concerne le script FRAME.

Voilà le gabarit général pour un rendu ImGui: un appel à frame_begin() ou frame_begin_v2(), suivi de tous les rendus des widgets et terminé par un appel à frame_end().

local win_w, win_h = gh_window.getsize(0)

local LEFT_BUTTON = 1
local mouse_left_button = gh_input.mouse_get_button_state(LEFT_BUTTON) 
local RIGHT_BUTTON = 2
local mouse_right_button = gh_input.mouse_get_button_state(RIGHT_BUTTON) 


local mouse_wheel = 0

local mouse_wheel_delta = gh_input.mouse_get_wheel_delta()
if (mouse_wheel_delta ~= 0) then
  if (mouse_wheel_delta > 0) then
    mouse_wheel = mouse_wheel + 1
  elseif (mouse_wheel_delta < 0) then
    mouse_wheel = mouse_wheel - 1
  end  
end
gh_input.mouse_reset_wheel_delta()


local dt = gh_utils.get_time_step()
gh_imgui.frame_begin_v2(win_w, win_h, mouse_x, mouse_y, mouse_left_button, mouse_right_button, mouse_wheel, dt)



...
...




gh_imgui.frame_end()


Voilà, le template d'un rendu ImGui est posé. Globalement, ce template sera toujours le même, quelque soit la démo.

Attaquons maintenant les choses intéressantes, celles qui produisent du visuel. L'API de scripting ImGui est très riche, aussi je vais me contenter de vous donner quelques examples simples de widgets. Il y a une interface ImGui dans pratiquement toutes les démos GeeXLab récentes, il suffit de les passer en revue pour avoir une idée des possibilités.



Fenêtre + Texte


ImGuiWindowFlags_Default = 0 
ImGuiWindowFlags_NoTitleBar = 1 -- Disable title-bar
ImGuiWindowFlags_NoResize = 2 -- Disable user resizing with the lower-right grip
ImGuiWindowFlags_NoMove = 4 -- Disable user moving the window
ImGuiWindowFlags_NoScrollbar = 8 -- Disable scrollbars (window can still scroll with mouse or programatically)
ImGuiWindowFlags_NoScrollWithMouse = 16 -- Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set.
ImGuiWindowFlags_NoCollapse = 32 -- Disable user collapsing window by double-clicking on it
ImGuiWindowFlags_AlwaysAutoResize = 64 -- Resize every window to its content every frame
ImGuiWindowFlags_NoBackground = 128 -- Disable drawing background color (WindowBg, etc.) and outside border. Similar as using SetNextWindowBgAlpha(0.0f).
ImGuiWindowFlags_NoSavedSettings = 256 -- Never load/save settings in .ini file

pos_size_flag_always = 1 -- Always set the pos and/or size
pos_size_flag_once = 2 -- Set the pos and/or size once per runtime session (only the first call with succeed)
pos_size_flag_first_use_ever = 4  -- Set the pos and/or size if the window has no saved data (if doesn't exist in the .ini file)

width = 300
height = 200
pos_x = 20
pos_y = 20
window_flags = ImGuiWindowFlags_Default
pos_flags = pos_size_flag_first_use_ever
size_flags = pos_size_flag_first_use_ever

local opened = gh_imgui.window_begin("Test Window", width, height, pos_x, pos_y, window_flags, pos_flags, size_flags)

if (opened == 1) then
  gh_imgui.text("Hello (with default color)")

  gh_imgui.text_rgba("Hello (yellow color)", 1.0, 1.0, 0.0, 1.0)
end
 
gh_imgui.window_end()




Bouton


if (gh_imgui.button("Click me") == 1) then
  -- do something if pressed.
end


Barre de Progression


fraction = 0.35
size_x = 0 -- for automatic width
size_y = 0 -- for automatic height
gh_imgui.progress_bar(fraction, size_x, size_y, "A progress bar set to 35 %")


Checkbox


initial_state = 0
if (gh_imgui.checkbox("Checkbox", initial_state) == 1) then
  -- do something if checked.
end


1D Slider


initial_state = 0
local min_value = 0.0
local max_value = 1.0
local power = 1.0 -- Use power!=1.0 for logarithmic sliders.
local initial_value = 0.5
slider_value = gh_imgui.slider_1f("Slider 1f", initial_value,   min_value, max_value,   power)



Police TTF


Il est possible de changer la police (ou font) par défaut d'ImGui par n'imnporte quelle autre police disponible au format TTF (True Type Font). En réalité, il est possible d'avoir plusieurs polices et de les activer dès que nécessaire (une police pour les titres, une autre pour les sous titres, etc...).

L'ajout de polices additionnelles se fait après gh_imgui.init() en utilisant la fonction gh_imgui.add_font_from_file() (ou gh_imgui.add_font_from_zip_file() ou gh_imgui.add_font_from_buffer()). Une fois toutes les polices chargées, il faut appeller gh_imgui.rebuild_all_fonts(). Obligatoire, c'est tout.

gh_imgui.init()

local demo_dir = gh_utils.get_demo_dir()
font_RobotoBlack = gh_imgui.add_font_from_file(demo_dir .. "data/Roboto-Black.ttf", 24)
font_RobotoRegular = gh_imgui.add_font_from_file(demo_dir .. "data/Roboto-Regular.ttf", 16)

gh_imgui.rebuild_all_fonts()

Les polices TTF peuvent aussi être chargées depuis un fichier zip. L'exemple suivant nous montre comment utiliser les fonctions gh_imgui.add_font_from_zip_file() et gh_utils.get_demo_zip_filename().

gh_utils.get_demo_zip_filename() est utile pour gérer le cas où toute la démo est archivé dans un fichier zip: souhaite t'on charger la police depuis le fichier zip de la demo (qui peut avoir n'importe quel nom) ou plutot depuis un fichier externe situé quelque part sur le disque (une police TTF utilisateur)?

dofile(lib_dir .. "lua/imgui.lua")

imgui_init("dark")

font_HACKED = 0
font_RobotoRegular = 0

local demo_zip_filename = gh_utils.get_demo_zip_filename()

if (demo_zip_filename == "") then
	font_HACKED = gh_imgui.add_font_from_file(demo_dir .. "data/HACKED.ttf", 26)
	font_RobotoRegular = gh_imgui.add_font_from_file(demo_dir .. "data/Roboto-Regular.ttf", 20)

else
	font_HACKED = gh_imgui.add_font_from_zip_file(demo_zip_filename, "data/HACKED.ttf", 26)
	font_RobotoRegular = gh_imgui.add_font_from_zip_file(demo_zip_filename, "data/Roboto-Regular.ttf", 20)

end	

gh_imgui.rebuild_all_fonts()

Maintenant que nous avons plusieurs polices, comment sélectionner la police courante?

D'abord il y a la fonction gh_imgui.set_default_font() qui permet de changer la police par défaut:

gh_imgui.set_default_font(font_RobotoRegular)

Ensuite ponctuellement, comme pour un titre, on peut changer de police avec gh_imgui.push_font() et gh_imgui.pop_font():

gh_imgui.push_font(font_RobotoBlack)
gh_imgui.text("Font RobotoBlack!!!")
gh_imgui.pop_font()



Primitives


ImGui offre la possibilité de dessiner, dans les fenêtres, quelques primitives très utiles: des lignes, des quads, cercles, disques ainsi que des courbes de Bezier. Les fonctions de rendu des primitives sont: add_line_to_drawlist(), add_quad_to_drawlist(), add_circle_to_drawlist() et add_bezier_curve_to_drawlist().

Le code suivant montre l'utilisation de ces primitives:

local wx, wy = gh_imgui.get_window_pos()

local mouse_x, mouse_y = gh_input.mouse_get_position()

local p0 = {x=wx+300, y=wy+50}
--local cp0 = {x=wx+200, y=wy+200}
local cp0 = {x=mouse_x, y=mouse_y}
local cp1 = {x=wx+460, y=wy+100}
local p1 = {x=wx+400, y=wy+200}
local color = {r=200, g=200, b=200, a=255}
local line_thickness = 2.0
local num_segments = 20


gh_imgui.add_quad_to_drawlist(wx+180, wy+35,    wx+250, wy+35,  wx+250, wy+45,  wx+180, wy+45,   100,255,100,255,    2.0,   1)


gh_imgui.add_line_to_drawlist(p0.x, p0.y,   cp0.x,cp0.y,   250,250,100,255,    1.0)
gh_imgui.add_line_to_drawlist(p1.x, p1.y,   cp1.x,cp1.y,   250,250,100,255,    1.0)

gh_imgui.add_bezier_curve_to_drawlist(p0.x,p0.y,   cp0.x,cp0.y,    cp1.x,cp1.y,  p1.x,p1.y,  color.r, color.g, color.b, color.a,  line_thickness, num_segments)

gh_imgui.add_circle_to_drawlist(p0.x, p0.y,   10,  200,200,200,255,    2.0,  20,    1)
gh_imgui.add_circle_to_drawlist(cp0.x, cp0.y,   10,  100,200,255,255,    2.0,  20,    1)
gh_imgui.add_circle_to_drawlist(cp1.x, cp1.y,   10,  100,200,255,255,    2.0,  20,    1)
gh_imgui.add_circle_to_drawlist(p1.x, p1.y,   10,  200,200,200,255,    2.0,  20,    1)


GeeXLab - ImGui, primitives: quad, bezier curves, lines and circles




Guide du Rootard GeeXLab | Téléchargements | Contact | Newsletter