Skip to content

Commit 6af0f30

Browse files
committed
Added helpers for GetWindowPos/GetWindowSize/GetWindowFramebufferScale/GetWindowWorkAreaInsets (#92)
1 parent e16d293 commit 6af0f30

6 files changed

Lines changed: 231 additions & 6 deletions

File tree

dear_bindings.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Dear Bindings Version v0.12 WIP
1+
# Dear Bindings Version v0.12
22
# Generates C-language headers for Dear ImGui
33
# Developed by Ben Carter (e-mail: ben AT shironekolabs.com, github: @ShironekoBen)
44

@@ -112,6 +112,12 @@ def convert_header(
112112
main_src_root = parse_single_header(src_file, context)
113113
dom_root.add_child(main_src_root)
114114

115+
# Check if the version of ImGui we are dealing with has docking support
116+
have_docking_support = False
117+
for define in dom_root.list_all_children_of_type(code_dom.DOMDefine):
118+
if define.name == 'IMGUI_HAS_DOCK':
119+
have_docking_support = True
120+
115121
# Assign a destination filename based on the output file
116122
dest_file_name_only = os.path.basename(dest_file_no_ext)
117123
_, main_src_root.dest_filename = os.path.split(dest_file_no_ext)
@@ -221,6 +227,37 @@ def convert_header(
221227
"(ImVector_Construct()/ImVector_Destruct() can be used to safely "
222228
"construct out_ranges)")
223229

230+
# If we have docking support, add some functions to allow overriding platform IO functions that return structures
231+
if have_docking_support:
232+
# Implementation for these is in templates/imgui-header-template.cpp
233+
mod_add_manual_helper_functions.apply(dom_root,
234+
[
235+
"void ImGuiPlatformIO_SetPlatform_GetWindowPos(void(*getWindowPosFunc)(ImGuiViewport* vp, ImVec2* result)); "
236+
"// Set ImGuiPlatformIO::Platform_GetWindowPos in a C-compatible mannner",
237+
"void ImGuiPlatformIO_SetPlatform_GetWindowSize(void(*getWindowPosFunc)(ImGuiViewport* vp, ImVec2* result)); "
238+
"// Set ImGuiPlatformIO::Platform_GetWindowSize in a C-compatible mannner",
239+
"void ImGuiPlatformIO_SetPlatform_GetWindowFramebufferScale(void(*getWindowPosFunc)(ImGuiViewport* vp, ImVec2* result)); "
240+
"// Set ImGuiPlatformIO::Platform_GetWindowFramebufferScale in a C-compatible mannner",
241+
"void ImGuiPlatformIO_SetPlatform_GetWindowWorkAreaInsets(void(*getWindowPosFunc)(ImGuiViewport* vp, ImVec4* result)); "
242+
"// Set ImGuiPlatformIO::Platform_GetWindowWorkAreaInsets in a C-compatible mannner"
243+
])
244+
# Add comments to try and point people at the helpers
245+
mod_add_field_comment.apply(dom_root,
246+
"ImGuiPlatformIO::Platform_GetWindowPos",
247+
"(Use ImGuiPlatformIO_SetPlatform_GetWindowPos() to set this from C)")
248+
249+
mod_add_field_comment.apply(dom_root,
250+
"ImGuiPlatformIO::Platform_GetWindowSize",
251+
"(Use ImGuiPlatformIO_SetPlatform_GetWindowSize() to set this from C)")
252+
253+
mod_add_field_comment.apply(dom_root,
254+
"ImGuiPlatformIO::Platform_GetWindowFramebufferScale",
255+
"(Use ImGuiPlatformIO_SetPlatform_GetWindowFramebufferScale() to set this from C)")
256+
257+
mod_add_field_comment.apply(dom_root,
258+
"ImGuiPlatformIO::Platform_GetWindowWorkAreaInsets",
259+
"(Use ImGuiPlatformIO_SetPlatform_GetWindowWorkAreaInsets() to set this from C)")
260+
224261
mod_set_arguments_as_nullable.apply(dom_root, ["fmt"], False) # All arguments called "fmt" are non-nullable
225262
mod_remove_operators.apply(dom_root)
226263
mod_remove_heap_constructors_and_destructors.apply(dom_root)

docs/Changelog.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
--- v0.12 WIP
1+
--- v0.12
22

33
* Copy the returned value to a temporary variable when the stub function needs to call to va_end (thanks to tanoxyz)
4+
* Added helpers for GetWindowPos/GetWindowSize/GetWindowFramebufferScale/GetWindowWorkAreaInsets in PlatformIO
5+
(in the Docking branch) so that a C function can be set as a callback despite the return value being a structure
6+
(#92)
47

58
--- v0.11
69

docs/Readme.md

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ intended for easy integration with automated build pipelines.
2828

2929
# Recent changes
3030

31+
* v0.12 adds support for setting certain `PlatformIO` callbacks in the docking branch that were previously not usable from C due to their return types. See the `PlatformIO callbacks` section below for full details.
3132
* v0.11 introduces a small-but-significant breaking change as the output file names are now `dcimgui` instead of `cimgui` (to disambiguate in cases where people are using multiple binding generators)
3233
* v0.10 adds (somewhat experimental) support for comverting `imgui_internal.h`.
3334
* v0.08 adds structure default values to metadata, and fixes a few bugs.
3435
* v0.07 adds some new metadata elements, new examples and fixes a number of bugs (especially around metadata and backends).
3536
* v0.06 fixes a small issue with ImGui v1.90.0 WIP where `ListBox()` and `ComboBox()` have deprecated variants that cause name clashes. Those variants are now renamed to `ImGui_ListBoxObsolete()` and `ImGui_ComboBoxObsolete()` respectively.
36-
* v0.05 introduced significantly enhanced type information in the JSON output, and experimental support for generating bindings for ImGui backends
37-
* Note that there are a number of small changes in the JSON format related to this that will require modification to code that consumes the JSON files - search [Changelog.txt](Changelog.txt) for `BREAKING CHANGE` for full details
38-
* v0.04 introduced a number of bugfixes and other tweaks
37+
* v0.05 introduced significantly enhanced type information in the JSON output, and experimental support for generating bindings for ImGui backends.
38+
* Note that there are a number of small changes in the JSON format related to this that will require modification to code that consumes the JSON files - search [Changelog.txt](Changelog.txt) for `BREAKING CHANGE` for full details.
39+
* v0.04 introduced a number of bugfixes and other tweaks.
3940

4041
You can see a full list of recent changes [here](Changelog.txt).
4142

@@ -284,6 +285,30 @@ Templates are expanded into their concrete instantiations, so for example `ImVec
284285
285286
> See the note above about `ImVector_Construct` for an exception to this rule.
286287
288+
### PlatformIO callbacks
289+
290+
Some of the PlatformIO callbacks (at present only in the Docking branch of Dear ImGui) return structures, which means that they cannot be directly set to C functions - notably these four:
291+
292+
```cpp
293+
ImVec2 (*Platform_GetWindowPos)(ImGuiViewport* vp);
294+
ImVec2 (*Platform_GetWindowSize)(ImGuiViewport* vp);
295+
ImVec2 (*Platform_GetWindowFramebufferScale)(ImGuiViewport* vp);
296+
ImVec4 (*Platform_GetWindowWorkAreaInsets)(ImGuiViewport* vp);
297+
```
298+
299+
To avoid this issue, Dear Bindings provides corresponding setter functions that take a C function and automatically insert a C++ thunk that converts the return value appropriately.
300+
301+
```cpp
302+
void ImGuiPlatformIO_SetPlatform_GetWindowPos(void (*getWindowPosFunc)(ImGuiViewport* vp, ImVec2* result));
303+
void ImGuiPlatformIO_SetPlatform_GetWindowSize(void (*getWindowPosFunc)(ImGuiViewport* vp, ImVec2* result));
304+
void ImGuiPlatformIO_SetPlatform_GetWindowFramebufferScale(void (*getWindowPosFunc)(ImGuiViewport* vp, ImVec2* result));
305+
void ImGuiPlatformIO_SetPlatform_GetWindowWorkAreaInsets(void (*getWindowPosFunc)(ImGuiViewport* vp, ImVec4* result));
306+
```
307+
308+
Note that internally these functions have to allocate a small structure to store the thunk information. This gets stored in the `BackendLanguageUserData` member of `ImGuiIO`, so if you application is using that for other purposes you will not be able to use these functions (in that case, you'll need to either implement your own thunk with the data stored elsewhere, or get in touch to see if we can find another place to store this data).
309+
310+
Also, there is a (small) dynamic allocation associated with this, so if you need to ensure absolutely all memory is freed then when you finish with the ImGui context you should use the helper functions to set the callbacks to `null` - once all the callbacks are removed the allocated memory will be freed.
311+
287312
### Removed functionality
288313
289314
These minor features are removed, mostly because they either rely on C++ language features to function correctly or are helpers that don't make sense as part of the bindings.

src/modifiers/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,5 @@
6262
from . import mod_replace_typedef_with_opaque_buffer
6363
from . import mod_change_class_field_type
6464
from . import mod_rename_prefix
65-
from . import mod_mark_structs_as_single_line_definition
65+
from . import mod_mark_structs_as_single_line_definition
66+
from . import mod_add_field_comment
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from src import code_dom
2+
from src import utils
3+
4+
5+
# This modifier adds a comment to the field with the fully-qualified name given
6+
# If a comment already exists the comment text will be appended to it with a space
7+
def apply(dom_root, field_name, comment):
8+
for function in dom_root.list_all_children_of_type(code_dom.DOMFieldDeclaration):
9+
if function.get_fully_qualified_name() == field_name:
10+
utils.append_comment_text(function, comment)

src/templates/imgui-header-template.cpp

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,152 @@ static inline ::ImStr MarshalToCPP_ImStr_FromCharStr(const char* b)
5151
}
5252
#endif // IMGUI_HAS_IMSTR
5353
#endif // defined(IMGUI_HAS_IMSTR)
54+
55+
// Helpers for setting callbacks that return complex structures in PlatformIO
56+
// These require a thunk in C++-land to work correctly, which is implemented here
57+
58+
#if defined(IMGUI_HAS_DOCK)
59+
60+
namespace
61+
{
62+
// Data we use in the thunk to convert these from C++-style callbacks to C-style callbacks
63+
struct ImGui_DearBindingsThunkData
64+
{
65+
void(*PlatformIO_GetWindowPos_ThunkTarget)(cimgui::ImGuiViewport* vp, cimgui::ImVec2* result);
66+
void(*PlatformIO_GetWindowSize_ThunkTarget)(cimgui::ImGuiViewport* vp, cimgui::ImVec2* result);
67+
void(*PlatformIO_GetWindowFramebufferScale_ThunkTarget)(cimgui::ImGuiViewport* vp, cimgui::ImVec2* result);
68+
void(*PlatformIO_GetWindowWorkAreaInsets_ThunkTarget)(cimgui::ImGuiViewport* vp, cimgui::ImVec4* result);
69+
};
70+
71+
// Get our thunk data for the current ImGui context, creating it if necessary
72+
ImGui_DearBindingsThunkData* ImGui_GetDearBindingsThunkData()
73+
{
74+
ImGuiIO& io = ImGui::GetIO();
75+
if (!io.BackendLanguageUserData)
76+
{
77+
io.BackendLanguageUserData = IM_NEW(ImGui_DearBindingsThunkData);
78+
memset(io.BackendLanguageUserData, 0, sizeof(ImGui_DearBindingsThunkData));
79+
}
80+
return reinterpret_cast<ImGui_DearBindingsThunkData*>(io.BackendLanguageUserData);
81+
}
82+
83+
// Tidy up our thunk data, deleting it if all the target pointers are null (i.e. it is unused)
84+
void ImGui_TidyDearBindingsThunkData()
85+
{
86+
ImGuiIO& io = ImGui::GetIO();
87+
if (io.BackendLanguageUserData)
88+
{
89+
ImGui_DearBindingsThunkData* thunkData = reinterpret_cast<ImGui_DearBindingsThunkData*>(io.BackendLanguageUserData);
90+
if ((!thunkData->PlatformIO_GetWindowPos_ThunkTarget) &&
91+
(!thunkData->PlatformIO_GetWindowSize_ThunkTarget) &&
92+
(!thunkData->PlatformIO_GetWindowFramebufferScale_ThunkTarget) &&
93+
(!thunkData->PlatformIO_GetWindowWorkAreaInsets_ThunkTarget))
94+
{
95+
// Thunk data is unused and can be freed
96+
io.BackendLanguageUserData = nullptr;
97+
IM_DELETE(thunkData);
98+
}
99+
}
100+
}
101+
102+
// Copies of the conversion stubs in order to deal with the fact that they are declared later in the file
103+
// Fixme: This is a little messy, but reordering things is also fiddly to do
104+
105+
static inline ::ImVec2 ConvertToCPP_ImVec2_ForThunks(const cimgui::ImVec2& src)
106+
{
107+
::ImVec2 dest;
108+
dest.x = src.x;
109+
dest.y = src.y;
110+
return dest;
111+
}
112+
113+
static inline ::ImVec4 ConvertToCPP_ImVec4_ForThunks(const cimgui::ImVec4& src)
114+
{
115+
::ImVec4 dest;
116+
dest.x = src.x;
117+
dest.y = src.y;
118+
dest.z = src.z;
119+
dest.w = src.w;
120+
return dest;
121+
}
122+
123+
// Thunks for callbacks that need them
124+
125+
ImVec2 ImGuiPlatformIO_GetWindowPos_Thunk(ImGuiViewport* vp)
126+
{
127+
ImGui_DearBindingsThunkData* thunkData = ImGui_GetDearBindingsThunkData();
128+
cimgui::ImVec2 result;
129+
thunkData->PlatformIO_GetWindowPos_ThunkTarget(reinterpret_cast<cimgui::ImGuiViewport*>(vp), &result);
130+
return ConvertToCPP_ImVec2_ForThunks(result);
131+
}
132+
133+
ImVec2 ImGuiPlatformIO_GetWindowSize_Thunk(ImGuiViewport* vp)
134+
{
135+
ImGui_DearBindingsThunkData* thunkData = ImGui_GetDearBindingsThunkData();
136+
cimgui::ImVec2 result;
137+
thunkData->PlatformIO_GetWindowSize_ThunkTarget(reinterpret_cast<cimgui::ImGuiViewport*>(vp), &result);
138+
return ConvertToCPP_ImVec2_ForThunks(result);
139+
}
140+
141+
ImVec2 ImGuiPlatformIO_GetWindowFramebufferScale_Thunk(ImGuiViewport* vp)
142+
{
143+
ImGui_DearBindingsThunkData* thunkData = ImGui_GetDearBindingsThunkData();
144+
cimgui::ImVec2 result;
145+
thunkData->PlatformIO_GetWindowFramebufferScale_ThunkTarget(reinterpret_cast<cimgui::ImGuiViewport*>(vp), &result);
146+
return ConvertToCPP_ImVec2_ForThunks(result);
147+
}
148+
149+
ImVec4 ImGuiPlatformIO_GetWindowWorkAreaInsets_Thunk(ImGuiViewport* vp)
150+
{
151+
ImGui_DearBindingsThunkData* thunkData = ImGui_GetDearBindingsThunkData();
152+
cimgui::ImVec4 result;
153+
thunkData->PlatformIO_GetWindowWorkAreaInsets_ThunkTarget(reinterpret_cast<cimgui::ImGuiViewport*>(vp), &result);
154+
return ConvertToCPP_ImVec4_ForThunks(result);
155+
}
156+
} // Anonymous namespace
157+
158+
CIMGUI_API void cimgui::ImGuiPlatformIO_SetPlatform_GetWindowPos(void(*func)(cimgui::ImGuiViewport* vp, cimgui::ImVec2* result))
159+
{
160+
ImGui_DearBindingsThunkData* thunkData = ImGui_GetDearBindingsThunkData();
161+
thunkData->PlatformIO_GetWindowPos_ThunkTarget = func;
162+
::ImGui::GetPlatformIO().Platform_GetWindowPos = (func != nullptr) ? ImGuiPlatformIO_GetWindowPos_Thunk : nullptr;
163+
if (!func)
164+
{
165+
ImGui_TidyDearBindingsThunkData(); // Try to release thunk data if no longer required
166+
}
167+
}
168+
169+
CIMGUI_API void cimgui::ImGuiPlatformIO_SetPlatform_GetWindowSize(void(*func)(cimgui::ImGuiViewport* vp, cimgui::ImVec2* result))
170+
{
171+
ImGui_DearBindingsThunkData* thunkData = ImGui_GetDearBindingsThunkData();
172+
thunkData->PlatformIO_GetWindowSize_ThunkTarget = func;
173+
::ImGui::GetPlatformIO().Platform_GetWindowSize = (func != nullptr) ? ImGuiPlatformIO_GetWindowSize_Thunk : nullptr;
174+
if (!func)
175+
{
176+
ImGui_TidyDearBindingsThunkData(); // Try to release thunk data if no longer required
177+
}
178+
}
179+
180+
CIMGUI_API void cimgui::ImGuiPlatformIO_SetPlatform_GetWindowFramebufferScale(void(*func)(cimgui::ImGuiViewport* vp, cimgui::ImVec2* result))
181+
{
182+
ImGui_DearBindingsThunkData* thunkData = ImGui_GetDearBindingsThunkData();
183+
thunkData->PlatformIO_GetWindowFramebufferScale_ThunkTarget = func;
184+
::ImGui::GetPlatformIO().Platform_GetWindowFramebufferScale = (func != nullptr) ? ImGuiPlatformIO_GetWindowFramebufferScale_Thunk : nullptr;
185+
if (!func)
186+
{
187+
ImGui_TidyDearBindingsThunkData(); // Try to release thunk data if no longer required
188+
}
189+
}
190+
191+
CIMGUI_API void cimgui::ImGuiPlatformIO_SetPlatform_GetWindowWorkAreaInsets(void(*func)(cimgui::ImGuiViewport* vp, cimgui::ImVec4* result))
192+
{
193+
ImGui_DearBindingsThunkData* thunkData = ImGui_GetDearBindingsThunkData();
194+
thunkData->PlatformIO_GetWindowWorkAreaInsets_ThunkTarget = func;
195+
::ImGui::GetPlatformIO().Platform_GetWindowWorkAreaInsets = (func != nullptr) ? ImGuiPlatformIO_GetWindowWorkAreaInsets_Thunk : nullptr;
196+
if (!func)
197+
{
198+
ImGui_TidyDearBindingsThunkData(); // Try to release thunk data if no longer required
199+
}
200+
}
201+
202+
#endif // defined(IMGUI_HAS_DOCK)

0 commit comments

Comments
 (0)