view: render map entities
[d2df-maped.git] / src / thirdparty / imgui.nim
blobec2049de4ff2249b60314b70923d27fdc912441e
1 import
2   std/logging, std/sequtils, std/strutils,
3   sdl2, opengl
5 import
6   imgui/base, imgui/backend_sdl2, imgui/backend_gl2
8 export
9   base
11 var
12   imguiCtx*: ptr ImGuiContext = nil
14 proc init*(window: WindowPtr): bool =
15   var context = igCreateContext()
16   igStyleColorsDark()
17   if not igSDL2Init(window):
18     error("Could not init SDL2 backend for ImGui: ", sdl2.getError())
19     context.igDestroyContext()
20     return false
21   if not igGL2Init():
22     error("Could not init GL2 backend for ImGui")
23     context.igDestroyContext()
24     return false
25   imguiCtx = context
26   result = true
28 proc shutdown*() =
29   if imguiCtx != nil:
30     igGL2Shutdown()
31     igSDL2Shutdown()
32     imguiCtx.igDestroyContext()
33     imguiCtx = nil
35 proc beginFrame*() =
36   igGL2NewFrame()
37   igSDL2NewFrame()
38   igNewFrame()
40 proc endFrame*() =
41   igRender()
42   igGL2EndFrame()
43   igGL2RenderDrawData(igGetDrawData())
45 proc event*(event: var Event): bool =
46   result = igSDL2ProcessEvent(nil, event)
48 # operators on ImVec2
50 proc `+`*(a, b: ImVec2): ImVec2 = ImVec2(x: a.x + b.x, y: a.y + b.y)
51 proc `-`*(a, b: ImVec2): ImVec2 = ImVec2(x: a.x - b.x, y: a.y - b.y)
52 proc `*`*(a: ImVec2, b: float32): ImVec2 = ImVec2(x: a.x * b, y: a.y * b)
53 proc `/`*(a: ImVec2, b: float32): ImVec2 = ImVec2(x: a.x / b, y: a.y / b)
55 # operators on flags
57 proc `or`*(a, b: ImGuiWindowFlags): ImGuiWindowFlags = ImGuiWindowFlags(a.int32 or b.int32)
58 proc `or`*(a, b: ImGuiItemFlags): ImGuiItemFlags = ImGuiItemFlags(a.int32 or b.int32)
60 # extra helper functions
62 proc rgba*(r, g, b, a: float32): ImVec4 =
63   ImVec4(x: r, y: g, z: b, w: a)
65 proc pushInactive*() =
66   igPushItemFlag(ImGuiItemFlags.Disabled, true)
67   igPushStyleVar(ImGuiStyleVar.Alpha, igGetStyle().alpha * 0.5f)
69 proc popInactive*() =
70   igPopStyleVar()
71   igPopItemFlag()
73 # control wrappers; need these mostly because of a weird fucking header error and also for type checking convenience
75 proc showStackToolWindow*() =
76   igShowStackToolWindow()
78 proc beginWindow*(label: string, pOpen: ptr bool = nil, flags: ImGuiWindowFlags = ImGuiWindowFlags.None): bool =
79   igBegin(label.cstring, pOpen, flags)
81 proc endWindow*() =
82   igEnd()
84 proc openPopup*(label: string, flags: ImGuiPopupFlags = ImGuiPopupFlags.None) =
85   igOpenPopup(label.cstring, flags)
87 proc beginPopup*(label: string, flags: ImGuiWindowFlags = ImGuiWindowFlags.None): bool =
88   igBeginPopup(label.cstring, flags)
90 proc endPopup*() =
91   igEndPopup()
93 proc closeCurrentPopup*() =
94   igCloseCurrentPopup()
96 proc beginPopupModal*(label: string, pOpen: ptr bool = nil, flags: ImGuiWindowFlags = ImGuiWindowFlags.None): bool =
97   igBeginPopupModal(label.cstring, pOpen, flags)
99 proc beginMenu*(label: string, enabled: bool = true): bool =
100   igBeginMenu(label.cstring, enabled)
102 proc endMenu*() =
103   igEndMenu()
105 proc beginMenuBar*(): bool =
106   igBeginMenuBar()
108 proc endMenuBar*() =
109   igEndMenuBar()
111 proc beginMainMenuBar*(): bool =
112   igBeginMainMenuBar()
114 proc endMainMenuBar*() =
115   igEndMainMenuBar()
117 proc beginTable*(tableId: string, columns: int, flags: ImGuiTableFlags = ImGuiTableFlags.None, outerSz: ImVec2 = ImVec2(x: 0.0f, y: 0.0f), innerW: float32 = 0.0f): bool =
118   igBeginTable(tableId.cstring, columns.int32, flags, outerSz, innerW)
120 proc endTable*() =
121   igEndTable()
123 proc beginListBox*(label: string, size: ImVec2 = ImVec2(x: 0, y: 0)): bool =
124   igBeginListBox(label.cstring, size)
126 proc endListBox*() =
127   igEndListBox()
129 proc beginCombo*(label: string, preview: string, flags: ImGuiComboFlags = ImGuiComboFlags.None): bool =
130   igBeginCombo(label.cstring, preview.cstring, flags)
132 proc endCombo*() =
133   igEndCombo()
135 proc beginChild*(label: string, size: ImVec2 = ImVec2(x: 0, y: 0), border: bool = false, flags: ImGuiWindowFlags = ImGuiWindowFlags.None): bool {.discardable.} =
136   igBeginChild(label.cstring, size, border, flags)
138 proc endChild*() =
139   igEndChild()
141 proc treeNode*(label: string): bool =
142   igTreeNode(label.cstring)
144 proc treePop*() =
145   igTreePop()
147 proc separator*() =
148   igSeparator()
150 proc sameLine*(offsetX: float32 = 0f, spacing: float32 = -1f) =
151   igSameLine(offsetX, spacing)
153 proc dummy*(size: ImVec2) =
154   igDummy(size)
156 proc text*(args: varargs[string, `$`]) =
157   var argStr = args.join()
158   igText("%s", argStr.cstring)
160 proc image*(id: uint32, size: ImVec2, borderCol: ImVec4 = ImVec4(x: 0, y: 0, z: 0, w: 0)) =
161   igImage(cast[ImTextureId](id), size, border_col = borderCol)
163 proc textWrapped*(args: varargs[string, `$`]) =
164   var argStr = args.join()
165   igTextWrapped("%s", argStr.cstring)
167 proc button*(label: string, size: ImVec2 = ImVec2(x: 0, y: 0)): bool =
168   igButton(label.cstring, size)
170 proc arrowButton*(label: string, dir: ImGuiDir): bool =
171   igArrowButton(label.cstring, dir)
173 proc arrowButtonEx*(label: string, dir: ImGuiDir, size: ImVec2, flags: ImGuiButtonFlags = ImGuiButtonFlags.None): bool =
174   igArrowButtonEx(label.cstring, dir, size, flags)
176 proc checkbox*(label: string, v: var bool): bool {.discardable.} =
177   igCheckbox(label.cstring, v.addr)
179 proc selectable*(label: string, selected: bool = false, flags: ImGuiSelectableFlags = ImGuiSelectableFlags.None, size: ImVec2 = ImVec2(x: 0, y: 0)): bool {.discardable.} =
180   igSelectable(label.cstring, selected, flags, size)
182 proc combo*(label: string, index: var int, choices: openArray[string]): bool =
183   var choicesPtrs = newSeq[cstring](choices.len())
184   var curChoice = index.int32
185   for i, x in choices: choicesPtrs[i] = x.cstring
186   result = igCombo(label.cstring, curChoice.addr, choicesPtrs[0].addr, choices.len().int32)
187   index = curChoice.int
189 proc menuItem*(label: string, shortcut: string = "", selected: bool = false, enabled: bool = true): bool {.discardable.} =
190   igMenuItem(label.cstring, (if shortcut == "": nil else: shortcut.cstring), selected, enabled)
192 proc menuItem*(label: string, shortcut: string = "", pSelected: ptr bool, enabled: bool = true): bool {.discardable.} =
193   igMenuItem(label.cstring, (if shortcut == "": nil else: shortcut.cstring), pSelected, enabled)
195 proc inputText*(label: string, outStr: var string, outMaxLen: int = 0, flags: ImGuiInputTextFlags = ImGuiInputTextFlags.None, callback: ImGuiInputTextCallback = nil, userData: pointer = nil): bool =
196   var strMax = (if outMaxLen == 0: outStr.len() else: outMaxLen)
197   if strMax == 0: strMax = 1 # for the \0
198   var tmp = outStr.items().toSeq()
199   tmp.setLen(strMax)
200   if igInputText(label.cstring, tmp[0].addr.cstring, tmp.len().uint, flags, callback, userData):
201     outStr = $(tmp[0].addr.cstring)
202     result = true
203   else:
204     result = false
206 proc inputInt*(label: string, x: var int32, step: int32 = 1, stepFast: int32 = 100, flags: ImGuiInputTextFlags = ImGuiInputTextFlags.None): bool =
207   igInputInt(label.cstring, x.addr, step, stepFast, flags)
209 proc inputInt2*(label: string, x: var array[2, int32], flags: ImGuiInputTextFlags = ImGuiInputTextFlags.None): bool =
210   igInputInt2(label.cstring, x[0].addr, flags)
212 proc inputInt4*(label: string, x: var array[4, int32], flags: ImGuiInputTextFlags = ImGuiInputTextFlags.None): bool =
213   igInputInt4(label.cstring, x[0].addr, flags)
215 proc columns*(count: int = 1, border: bool = true) =
216   igColumns(count.int32, nil, border)
218 proc nextColumn*() =
219   igNextColumn()
221 proc setColumnWidth*(idx: int, w: float32) =
222   igSetColumnWidth(idx.int32, w)
224 proc alignTextToFramePadding*() =
225   igAlignTextToFramePadding()
227 proc setItemDefaultFocus*() =
228   igSetItemDefaultFocus()
230 proc setNextItemWidth*(w: float32) =
231   igSetNextItemWidth(w)
233 proc setNextWindowPos*(pos: ImVec2, cond: ImGuiCond = ImGuiCond.None, pivot: ImVec2 = ImVec2(x: 0, y: 0)) =
234   igSetNextWindowPos(pos, cond, pivot)
236 proc setNextWindowSize*(size: ImVec2, cond: ImGuiCond = ImGuiCond.None) =
237   igSetNextWindowSize(size, cond)
239 proc setNextWindowContentSize*(size: ImVec2) =
240   igSetNextWindowContentSize(size)
242 proc setNextWindowSizeConstraints*(minSize, maxSize: ImVec2) =
243   igSetNextWindowSizeConstraints(minSize, maxSize)
245 proc setCursorPosX*(x: float32) =
246   igSetCursorPosX(x)
248 proc setScrollFromPosX*(x: float32, ratio: float32 = 0.5f) =
249   igSetScrollFromPosX(x, ratio)
251 proc setScrollFromPosY*(y: float32, ratio: float32 = 0.5f) =
252   igSetScrollFromPosY(y, ratio)
254 proc setScrollHereX*(ratio: float32 = 0.5f) =
255   igSetScrollHereX(ratio)
257 proc setScrollHereY*(ratio: float32 = 0.5f) =
258   igSetScrollHereY(ratio)
260 proc setScrollX*(ratio: float32) =
261   igSetScrollX(ratio)
263 proc setScrollY*(ratio: float32) =
264   igSetScrollY(ratio)
266 proc getScrollX*(): float32 =
267   igGetScrollX()
269 proc getScrollY*(): float32 =
270   igGetScrollY()
272 proc getScrollMaxX*(): float32 =
273   igGetScrollMaxX()
275 proc getScrollMaxY*(): float32 =
276   igGetScrollMaxY()
278 proc getItemSize*(): ImVec2 =
279   igGetItemRectSizeNonUDT(result.addr)
281 proc getWindowSize*(): ImVec2 =
282   igGetWindowSizeNonUDT(result.addr)
284 proc getWindowContentRegionSize*(): ImVec2 =
285   igGetWindowContentRegionMaxNonUDT(result.addr)
286   var mins: ImVec2
287   igGetWindowContentRegionMinNonUDT(mins.addr)
288   result = result - mins
290 proc getIO*(): ptr ImGuiIO =
291   igGetIO()
293 proc getStyle*(): ptr ImGuiStyle =
294   igGetStyle()
296 proc getFrameHeight*(): float32 =
297   igGetFrameHeight()
299 proc getFrameHeightWithSpacing*(): float32 =
300   igGetFrameHeightWithSpacing()
302 proc getCursorPosX*(): float32 =
303   igGetCursorPosX()
305 proc getCursorPosY*(): float32 =
306   igGetCursorPosY()
308 proc getCursorPos*(): ImVec2 =
309   ImVec2(x: igGetCursorPosX(), y: igGetCursorPosY())
311 proc getMousePos*(): ImVec2 =
312   igGetMousePosNonUDT(result.addr)
314 proc calcTextSize*(text: string): ImVec2 =
315   igCalcTextSizeNonUDT(result.addr, text.cstring)
317 proc pushStyleColor*(what: ImGuiCol, col: ImVec4) =
318   igPushStyleColor(what, col)
320 proc popStyleColor*(count: int = 1) =
321   igPopStyleColor(count.int32)
323 proc pushItemWidth*(w: float32) =
324   igPushItemWidth(w)
326 proc popItemWidth*() =
327   igPopItemWidth()
329 proc isItemFocused*(): bool =
330   igIsItemFocused()
332 proc isItemActive*(): bool =
333   igIsItemActive()
335 proc isPopupOpen*(id: string): bool =
336   igIsPopupOpen(id.cstring)
338 proc isMouseDoubleClicked*(button: ImGuiMouseButton): bool =
339   igIsMouseDoubleClicked(button)
341 proc isMouseDown*(button: ImGuiMouseButton): bool =
342   igIsMouseDown(button)
344 proc isMouseClicked*(button: ImGuiMouseButton): bool =
345   igIsMouseClicked(button)
347 proc isKeyPressed*(key: ImGuiKey, repeat: bool = true): bool =
348   igIsKeyPressedMap(key, repeat)
350 proc isAnyModalPopupOpen*(): bool =
351   (igGetTopMostPopupModal() != nil)
353 # `with`-style templates for all kinds of controls
355 template doWindow*(label: string, actions: untyped): untyped =
356   if imgui.beginWindow(label):
357     actions
358     imgui.endWindow()
360 template doPopup*(label: string, actions: untyped): untyped =
361   if imgui.beginPopup(label):
362     actions
363     imgui.endPopup()
365 template doPopupModal*(label: string, actions: untyped): untyped =
366   if imgui.beginPopupModal(label):
367     actions
368     imgui.endPopup()
370 template doMenu*(label: string, actions: untyped): untyped =
371   if imgui.beginMenu(label):
372     actions
373     imgui.endMenu()
375 template doMenuBar*(actions: untyped): untyped =
376   if imgui.beginMenuBar():
377     actions
378     imgui.endMenuBar()
380 template doMainMenuBar*(actions: untyped): untyped =
381   if imgui.beginMainMenuBar():
382     actions
383     imgui.endMainMenuBar()
385 template doTreeNode*(label: string, actions: untyped): untyped =
386   if imgui.treeNode(label):
387     actions
388     imgui.treePop()
390 template doTable*(label: string, colums: int, actions: untyped): untyped =
391   if imgui.beginTable(label, columns):
392     actions
393     imgui.endTable()
395 template doCombo*(label: string, initVal: string, actions: untyped): untyped =
396   if imgui.beginCombo(label, initVal):
397     actions
398     imgui.endCombo()
400 template doListBox*(label: string, actions: untyped): untyped =
401   if imgui.beginListBox(label):
402     actions
403     imgui.endListBox()
405 template doChild*(label: string, actions: untyped): untyped =
406   if imgui.beginChild(label):
407     actions
408     imgui.endChild()
410 template doInactive*(actions: untyped): untyped =
411   imgui.pushInactive()
412   actions
413   imgui.popInactive()
415 template doColumns*(numCols: int, border: bool, actions: untyped): untyped =
416   imgui.columns(numCols, border)
417   actions
418   imgui.columns(1)