Skip to content

Commit 59b4dc6

Browse files
feat: add combo imgui widget
1 parent 0056f1c commit 59b4dc6

6 files changed

Lines changed: 235 additions & 43 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pilotlight/imgui_d.pyd
1717
pilotlight/*.pdb
1818
pilotlight/*.dll
1919
pilotlight/*.so
20+
pilotlight/*.rdi
2021
pilotlight/*.dSYM
2122
pilotlight/shaders/
2223

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"program": "${workspaceFolder}/out/pilotlight_python.exe",
88
"console": "integratedTerminal",
99
"request": "launch",
10-
"args": [],
10+
"args": ["../sandbox/demo.py"],
1111
"stopAtEntry": false,
1212
"cwd": "${workspaceFolder}/out/",
1313
"environment": []

extensions/pl_dearimgui_ext_m.cpp

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Index of this file:
3636
#include "pl_math.h"
3737

3838
#include "pl_graphics_ext.h"
39+
#include "pl_ds.h"
3940

4041
bool pl_parse(const char* formatstring, const char** keywords, PyObject* args, PyObject* kwargs, const char* message, ...);
4142
static ImVec2 pl__get_vec2_from_python(PyObject* ptValue);
@@ -315,19 +316,19 @@ ImGui_MenuItem(PyObject* self, PyObject* args, PyObject* kwargs)
315316
const char* pcLabel = nullptr;
316317
const char* pcShortcut = nullptr;
317318
int bEnabled = true;
318-
int bSelected = true;
319+
int bSelected = false;
319320
PyObject* ptPointer = Py_None;
320321
if (!pl_parse("s|spp$O", (const char**)apcKeywords, args, kwargs, __FUNCTION__,
321322
&pcLabel, &pcShortcut, &bSelected, &bEnabled, &ptPointer))
322323
return nullptr;
323324

324-
bool* pbSelected = nullptr;
325+
bool bbSelected = (bool)bSelected;
326+
bool* pbSelected = &bbSelected;
325327
if(!Py_IsNone(ptPointer))
326328
pbSelected = (bool*)PyCapsule_GetPointer(ptPointer, "plBoolPointer");
327329

328-
if(pbSelected)
329-
return PyBool_FromLong(ImGui::MenuItem(pcLabel, pcShortcut, pbSelected, bEnabled));
330-
return PyBool_FromLong(ImGui::MenuItem(pcLabel, pcShortcut, bSelected, bEnabled));
330+
bool bActivated = ImGui::MenuItem(pcLabel, pcShortcut, pbSelected, bEnabled);
331+
return Py_BuildValue("(pp)", bActivated, bbSelected);
331332
}
332333

333334
PyObject*
@@ -2992,6 +2993,42 @@ ImGui_EndCombo(PyObject* self)
29922993
Py_RETURN_NONE;
29932994
}
29942995

2996+
PyObject*
2997+
ImGui_Combo(PyObject* self, PyObject* args, PyObject* kwargs)
2998+
{
2999+
static const char* apcKeywords[] = {
3000+
"label",
3001+
"current_item",
3002+
"items",
3003+
"popup_max_height_in_items",
3004+
nullptr,
3005+
};
3006+
static const char** sbtEntries = nullptr;
3007+
3008+
const char* pcLabel = nullptr;
3009+
PyObject* ptCurrentItem = nullptr;
3010+
PyObject* ptItems = nullptr;
3011+
int popup_max_height_in_items = -1;
3012+
if (!pl_parse("sOO|i", (const char**)apcKeywords, args, kwargs, __FUNCTION__,
3013+
&pcLabel, &ptCurrentItem, &ptItems, &popup_max_height_in_items))
3014+
return nullptr;
3015+
3016+
int* ptCurrentItemInt = (int*)PyCapsule_GetPointer(ptCurrentItem, "plIntPointer");
3017+
3018+
Py_ssize_t pySize = PyList_Size(ptItems);
3019+
pl_sb_resize(sbtEntries, (uint32_t)pySize);
3020+
for(Py_ssize_t i = 0; i < pySize; i++)
3021+
{
3022+
PyObject* item = PyList_GetItem(ptItems, i);
3023+
sbtEntries[i] = PyUnicode_AsUTF8(item);
3024+
}
3025+
3026+
bool bActivated = ImGui::Combo(pcLabel, ptCurrentItemInt, sbtEntries, (int)pySize, popup_max_height_in_items);
3027+
pl_sb_reset(sbtEntries);
3028+
return Py_BuildValue("p", bActivated);
3029+
}
3030+
3031+
29953032
PyObject*
29963033
ImGui_BeginListBox(PyObject* self, PyObject* args, PyObject* kwargs)
29973034
{
@@ -3398,6 +3435,7 @@ static PyMethodDef gatCommands[] =
33983435
PL_PYTHON_COMMAND(ImGui_SetKeyboardFocusHere, METH_VARARGS | METH_KEYWORDS, NULL),
33993436

34003437
// imgui combo box/dropdown widgets
3438+
PL_PYTHON_COMMAND(ImGui_Combo, METH_VARARGS | METH_KEYWORDS, NULL),
34013439
PL_PYTHON_COMMAND(ImGui_BeginCombo, METH_VARARGS | METH_KEYWORDS, NULL),
34023440
PL_PYTHON_COMMAND(ImGui_EndCombo, METH_NOARGS, NULL),
34033441

pilotlight/imgui.pyi

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import List, NewType
1+
from typing import List, NewType, Tuple
22
from pilotlight.types import *
33
from pilotlight.enums import *
44

@@ -80,33 +80,12 @@ def ImGui_StyleColorsLight():
8080
def ImGui_StyleColorsClassic():
8181
...
8282

83-
def ImGui_Begin(name, bool_pointer: plBoolPointer = None, flags: ImGuiWindowFlags = 0) -> None:
83+
def ImGui_Begin(name: str, bool_pointer: plBoolPointer = None, flags: ImGuiWindowFlags = 0) -> bool:
8484
...
8585

8686
def ImGui_End():
8787
...
8888

89-
def ImGui_BeginMenuBar():
90-
...
91-
92-
def ImGui_BeginMainMenuBar():
93-
...
94-
95-
def ImGui_EndMenuBar():
96-
...
97-
98-
def ImGui_EndMainMenuBar():
99-
...
100-
101-
def ImGui_BeginMenu(label, enabled=True):
102-
...
103-
104-
def ImGui_EndMenu():
105-
...
106-
107-
def ImGui_MenuItem(label, shortcut="", selected=False, enabled=True, selected_pointer: plBoolPointer = None):
108-
...
109-
11089
########################################################################################################################
11190
# [SECTION] imgui window utilities
11291
########################################################################################################################
@@ -178,6 +157,41 @@ def ImGui_SetWindowCollapsed(collapsed: bool, cond: ImGuiCond = 0, name: str = N
178157
def ImGui_SetWindowFocus(name: str = None) -> None:
179158
...
180159

160+
########################################################################################################################
161+
# [SECTION] imgui menu stuff
162+
########################################################################################################################
163+
164+
def ImGui_BeginMenuBar() -> bool:
165+
...
166+
167+
def ImGui_BeginMainMenuBar() -> bool:
168+
...
169+
170+
def ImGui_EndMenuBar() -> None:
171+
...
172+
173+
def ImGui_EndMainMenuBar() -> None:
174+
...
175+
176+
def ImGui_BeginMenu(label:str, enabled:bool=True) -> bool:
177+
...
178+
179+
def ImGui_EndMenu() -> None:
180+
...
181+
182+
def ImGui_MenuItem(label:str, shortcut:str="", selected:bool=False, enabled:bool=True, selected_pointer: plBoolPointer = None) -> Tuple[bool, bool]:
183+
...
184+
185+
########################################################################################################################
186+
# [SECTION] imgui child windows
187+
########################################################################################################################
188+
189+
def ImGui_BeginChild(str_id: str, size:List[int, int]=None, child_flags: ImGuiChildFlags = 0, window_flags: ImGuiWindowFlags = 0) -> bool:
190+
...
191+
192+
def ImGui_EndChild() -> None:
193+
...
194+
181195
########################################################################################################################
182196
# [SECTION] imgui input utilities mouse
183197
########################################################################################################################
@@ -257,16 +271,6 @@ def ImGui_SaveIniSettingsToDisk(ini_filename: str) -> None:
257271
def ImGui_SaveIniSettingsToMemory() -> str | None:
258272
...
259273

260-
########################################################################################################################
261-
# [SECTION] imgui child windows
262-
########################################################################################################################
263-
264-
def ImGui_BeginChild(str_id: str, size=None, child_flags: ImGuiChildFlags = 0, window_flags: ImGuiWindowFlags = 0) -> bool:
265-
...
266-
267-
def ImGui_EndChild() -> None:
268-
...
269-
270274
########################################################################################################################
271275
# [SECTION] imgui id stack/scopes
272276
########################################################################################################################
@@ -327,6 +331,9 @@ def ImGui_BeginCombo(label: str, preview_value: str, flags: ImGuiComboFlags = 0)
327331
def ImGui_EndCombo() -> None:
328332
...
329333

334+
def ImGui_Combo(label: str, current_item: plIntPointer, items: List[str], popup_max_height_in_items: int = -1) -> bool:
335+
...
336+
330337
########################################################################################################################
331338
# [SECTION] imgui list boxes
332339
########################################################################################################################

sandbox/demo.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import os
2+
3+
# core
4+
import pilotlight.pilotlight as pl
5+
from pilotlight.pilotlight import *
6+
from pilotlight.imgui import *
7+
from pilotlight.enums import *
8+
from pilotlight.types import *
9+
10+
def show_example_menu_file():
11+
static = show_example_menu_file
12+
13+
ImGui_MenuItem("(demo menu)", "", False, False)
14+
if ImGui_MenuItem("New"):
15+
pass
16+
if ImGui_MenuItem("Open", "Ctrl+O"):
17+
pass
18+
if ImGui_BeginMenu("Open Recent"):
19+
ImGui_MenuItem("Hello")
20+
ImGui_MenuItem("Sailor")
21+
if ImGui_BeginMenu("Recurse.."):
22+
show_example_menu_file()
23+
ImGui_EndMenu()
24+
ImGui_EndMenu()
25+
if ImGui_MenuItem("Save", "Ctrl+S"):
26+
pass
27+
if ImGui_MenuItem("Save As.."):
28+
pass
29+
ImGui_Separator()
30+
if ImGui_BeginMenu("Options"):
31+
if not hasattr(static, "enabled"):
32+
static.enabled = True
33+
_, static.enabled = ImGui_MenuItem("Enabled", "", static.enabled)
34+
ImGui_BeginChild("child", (0, 60), ImGuiChildFlags.Borders)
35+
for i in range(0, 10):
36+
ImGui_Text("Scrolling Text %d" % i)
37+
ImGui_EndChild()
38+
if not hasattr(static, "f"):
39+
static.f = pl_create_float_pointer()
40+
static.n = pl_create_int_pointer()
41+
ImGui_SliderFloat("Value", static.f, 0.0, 1.0)
42+
ImGui_InputFloat("Input", static.f, 0.1)
43+
items = ["Yes", "No", "Maybe"]
44+
ImGui_Combo("Combo", static.n, items)
45+
ImGui_EndMenu()
46+
47+
class App:
48+
49+
def __init__(self):
50+
self.ptWindow = None
51+
self.show_imgui_demo = None
52+
self.show_implot_demo = None
53+
self.some_string_array = bytearray("pizza", 'utf-8')
54+
self.some_string_array.resize(256)
55+
56+
def pl_app_load(self):
57+
58+
self.show_imgui_demo = pl_create_bool_pointer()
59+
self.show_implot_demo = pl_create_bool_pointer()
60+
61+
pl_vfs_mount_directory("/cache", "cache")
62+
pl_vfs_mount_directory("/shaders", os.path.dirname(os.path.abspath(pl.__file__)) + "/shaders")
63+
pl_vfs_mount_directory("/shader-temp", "shader-temp")
64+
65+
self.ptWindow = pl_window_create("Demo", 200, 200, 500, 500, 0)
66+
pl_window_show(self.ptWindow)
67+
68+
starter_flags = plStarterFlag.PL_STARTER_FLAGS_ALL_EXTENSIONS
69+
starter_flags |= plStarterFlag.PL_STARTER_FLAGS_MSAA
70+
starter_flags &= ~plStarterFlag.PL_STARTER_FLAGS_SHADER_EXT
71+
pl_starter_initialize(self.ptWindow, starter_flags)
72+
73+
shader_options = plShaderOptions()
74+
shader_options.pcCacheOutputDirectory = "/shader-temp/"
75+
shader_options.apcDirectories = ["/shaders/"]
76+
shader_options.apcIncludeDirectories = ["/shaders/"]
77+
shader_options.tFlags = plShaderFlags.PL_SHADER_FLAGS_AUTO_OUTPUT | plShaderFlags.PL_SHADER_FLAGS_INCLUDE_DEBUG | plShaderFlags.PL_SHADER_FLAGS_ALWAYS_COMPILE
78+
pl_shader_initialize(shader_options)
79+
80+
pl_starter_finalize()
81+
pl_dear_imgui_initialize(pl_starter_get_device(), pl_starter_get_swapchain(), pl_starter_get_render_pass())
82+
pl_shader_variant_initialize(pl_starter_get_device())
83+
84+
ImGui_StyleColorsDark()
85+
86+
87+
def pl_app_shutdown(self):
88+
pl_graphics_flush_device(pl_starter_get_device())
89+
pl_dear_imgui_cleanup()
90+
pl_starter_cleanup()
91+
pl_window_destroy(self.ptWindow)
92+
93+
def pl_app_resize(self):
94+
pl_starter_resize()
95+
96+
def pl_app_update(self):
97+
98+
99+
if not pl_starter_begin_frame():
100+
return
101+
102+
pl_dear_imgui_new_frame(pl_starter_get_device(), pl_starter_get_render_pass())
103+
104+
if pl_get_pointer_value(self.show_imgui_demo):
105+
ImGui_ShowDemoWindow(self.show_imgui_demo)
106+
107+
if pl_get_pointer_value(self.show_implot_demo):
108+
ImPlot_ShowDemoWindow(self.show_implot_demo)
109+
110+
# dear imgui API
111+
if ImGui_BeginMainMenuBar():
112+
if ImGui_BeginMenu("File"):
113+
ImGui_EndMenu()
114+
if ImGui_BeginMenu("Edit", False):
115+
ImGui_EndMenu()
116+
if ImGui_BeginMenu("Tools"):
117+
ImGui_MenuItem("Show ImGui Demo", selected_pointer=self.show_imgui_demo)
118+
ImGui_MenuItem("Show ImPlot Demo", selected_pointer=self.show_implot_demo)
119+
ImGui_EndMenu()
120+
if ImGui_BeginMenu("Help"):
121+
ImGui_MenuItem("Check For Update")
122+
ImGui_MenuItem("About", "-a")
123+
ImGui_EndMenu()
124+
ImGui_EndMainMenuBar()
125+
126+
127+
if ImGui_Begin("Dear ImGui Demo", None, ImGuiWindowFlags.MenuBar):
128+
if ImGui_BeginMenuBar():
129+
if ImGui_BeginMenu("Menu"):
130+
show_example_menu_file()
131+
ImGui_EndMenu()
132+
ImGui_EndMenuBar()
133+
ImGui_End()
134+
135+
136+
render_encoder = pl_starter_begin_main_pass()
137+
138+
pl_dear_imgui_render(render_encoder)
139+
140+
pl_starter_end_main_pass()
141+
142+
pl_starter_end_frame()
143+
144+
# run app
145+
pl_run(App())

src/pl_py_math.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,11 @@ static PyType_Slot pl_vec2_slots[] = {
123123
};
124124

125125
static PyType_Spec pl_vec2_spec = {
126-
.name = "pilotlight.Vec2",
127-
.basicsize = sizeof(plPyVec2),
128-
.flags = Py_TPFLAGS_DEFAULT,
129-
.slots = pl_vec2_slots
126+
"pilotlight.Vec2",
127+
sizeof(plPyVec2),
128+
0,
129+
Py_TPFLAGS_DEFAULT,
130+
pl_vec2_slots
130131
};
131132

132133
static bool

0 commit comments

Comments
 (0)