Created base template for ImGUI application.

This commit is contained in:
Jakob Friedl
2025-09-05 10:49:27 +02:00
parent cb02d79b6e
commit e7ab8b5fac
22 changed files with 3733 additions and 276 deletions

View File

@@ -1,59 +1,65 @@
[Window][CQ]
Size=2868,1695
[Window][Conquest]
Pos=0,0
Size=1908,999
Collapsed=0
[Window][Dear ImGui Demo]
Pos=0,30
Size=2868,1665
Pos=0,518
Size=954,481
Collapsed=0
DockId=0x00000003,0
DockId=0x00000006,0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Conquest]
Pos=0,0
Size=2868,1695
[Window][Example: Documents]
Pos=0,33
Size=1050,966
Collapsed=0
DockId=0x00000005,0
[Window][Dear ImGui Style Editor]
Pos=123,79
Size=1080,1629
Collapsed=0
[Window][Example: Console]
Pos=0,458
Size=2868,1237
Collapsed=0
DockId=0x00000002,0
[Window][Example: Log]
Pos=1951,30
Size=917,1103
Pos=1346,33
Size=562,966
Collapsed=0
DockId=0x00000004,0
[Window][DockSpace Demo]
Pos=0,0
Size=2868,1695
[Window][Example: Assets Browser]
Pos=60,60
Size=800,480
Collapsed=0
[Table][0x951FCC8A,6]
RefScale=24
Column 0 Width=50 Sort=0v
Column 1 Width=74
Column 2 Width=111
Column 3 Width=118
Column 4 Weight=1.0000
Column 5 Width=-1
[Window][Example: Long text display]
Pos=60,60
Size=520,600
Collapsed=0
[Window][Dear ImGui Demo/ResizableChild_478B81A3]
IsChild=1
Size=1857,115
[Window][Dear ImGui Demo/Red_BEEF922B]
IsChild=1
Size=200,100
[Window][Info Window]
Pos=956,33
Size=952,966
Collapsed=0
DockId=0x00000002,0
[Table][0xB6880529,2]
RefScale=27
Column 0 Sort=0v
[Docking][Data]
DockSpace ID=0x3674675E Window=0x538FB738 Pos=0,30 Size=2868,1665 Split=Y Selected=0x5E5F7166
DockNode ID=0x00000001 Parent=0x3674675E SizeRef=2868,426 Split=X Selected=0x5E5F7166
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1949,833 CentralNode=1 Selected=0x5E5F7166
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=917,833 Selected=0x38CCB771
DockNode ID=0x00000002 Parent=0x3674675E SizeRef=2868,1237 Selected=0x1BCA3180
DockSpace ID=0xC0DFADC4 Window=0xD0388BC8 Pos=0,30 Size=2868,1665 CentralNode=1
DockSpace ID=0x3674675E Window=0x538FB738 Pos=0,33 Size=1908,966 Split=X Selected=0x5E5F7166
DockNode ID=0x00000003 Parent=0x3674675E SizeRef=0,0 Split=X Selected=0x5E5F7166
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=954,966 Split=Y Selected=0x5E5F7166
DockNode ID=0x00000005 Parent=0x00000001 SizeRef=954,483 CentralNode=1
DockNode ID=0x00000006 Parent=0x00000001 SizeRef=954,481 Selected=0x5E5F7166
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=952,966 Selected=0x7DB93FD0
DockNode ID=0x00000004 Parent=0x3674675E SizeRef=562,966 Selected=0x3EEA4247

View File

@@ -1,112 +1,78 @@
import nimgl/[opengl, glfw]
import imguin/glfw_opengl
import ./utils/[lib, windowInit]
import ./utils/appImGui
proc main(hWin: glfw.GLFWWindow) =
var
clearColor: CColor
showWindowDelay = 1
showMainWindow = true
windowClass = ImGuiWindowClass_ImGuiWindowClass()
opt_fullscreen: bool = true
opt_padding: bool = false
dockspaceFlags: ImGuiDockNodeFlags = ImGuiDockNodeFlags_None.int32
windowFlags: ImGuiWindow_Flags = ImGuiWindowFlags_MenuBar.int32 or ImGuiWindowFlags_NoDocking.int32
proc main() =
var app = createApp(1024, 800, imnodes = true, title = "Conquest", docking = true)
defer: app.destroyApp()
# Setup background and theme colors (Background is only seen when opt_padding = true)
clearColor = CColor(elm:(x:0.0f, y:0.0f, z:0.0f, w:0.0f))
igStyleColorsClassic(nil)
# Setup fonts
discard setupFonts()
var showConquest = true
let io = igGetIO()
# main loop
while not hWin.windowShouldClose:
glfwPollEvents()
while not app.handle.windowShouldClose:
pollEvents()
if getWindowAttrib(hWin, GLFW_ICONIFIED) != 0:
ImGui_ImplGlfw_Sleep(10)
continue
if app.isIconifySleep():
continue
newFrame()
# Start ImGUI frame
ImGui_ImplOpenGL3_NewFrame()
ImGui_ImplGlfw_NewFrame()
igNewFrame()
# Create Dockspace where all windows are placed in
if opt_fullscreen:
# Create fullscreen dockspace as the base where all other windows are placed in
block:
var
windowClass = ImGuiWindowClass_ImGuiWindowClass()
dockspaceFlags: ImGuiDockNodeFlags = ImGuiDockNodeFlags_None.int32
windowFlags: ImGuiWindow_Flags = ImGuiWindowFlags_MenuBar.int32 or ImGuiWindowFlags_NoDocking.int32
var vp = igGetMainViewport()
igSetNextWindowPos(vp.WorkPos, ImGui_Cond_None.int32, vec2(0.0f, 0.0f))
igSetNextWindowSize(vp.WorkSize, 0)
igSetNextWindowViewport(vp.ID)
igPushStyleVar_Float(ImGuiStyleVar_WindowRounding.int32, 0.0f)
igPushStyleVar_Float(ImGuiStyleVar_WindowBorderSize.int32, 0.0f)
windowFlags = windowFlags or (
ImGuiWindowFlags_NoTitleBar.int32 or
ImGuiWindowFlags_NoCollapse.int32 or
ImGuiWindowFlags_NoResize.int32 or
ImGuiWindowFlags_NoMove.int32 or
ImGuiWindowFlags_NoBringToFrontOnFocus.int32 or
ImGuiWindowFlags_NoNavFocus.int32
)
windowFlags = windowFlags or ImGuiWindowFlags_NoTitleBar.int32 or ImGuiWindowFlags_NoCollapse.int32 or ImGuiWindowFlags_NoResize.int32 or ImGuiWindowFlags_NoMove.int32
windowFlags = windowFlags or ImGuiWindowFlags_NoBringToFrontOnFocus.int32 or ImGuiWindowFlags_NoNavFocus.int32
else:
dockspaceFlags = cast[ImGuiDockNodeFlags](dockspaceFlags and not ImGuiDockNodeFlags_PassthruCentralNode.int32)
if (dockspaceFlags and ImGuiDockNodeFlags_PassthruCentralNode.int32) == ImGuiDockNodeFlags_None.int32:
windowFlags = cast[ImGuiWindow_Flags](windowFlags or ImGuiWindowFlags_NoBackground.int32)
if not opt_padding:
# Add padding
igPushStyleVar_Vec2(ImGuiStyleVar_WindowPadding.int32, vec2(0.0f, 0.0f))
igBegin("Conquest", addr showMainWindow, windowFlags)
igBegin("Conquest", addr showConquest, windowFlags)
defer: igEnd()
if not opt_padding:
igPopStyleVar(1)
igPopStyleVar(3)
if opt_fullscreen:
igPopStyleVar(2)
# Create dockspace
if (io.ConfigFlags and ImGui_ConfigFlags_DockingEnable.int32) != ImGui_ConfigFlags_None.int32:
# Create dockspace
igDockSpace(igGetID_Str("Conquest-Dockspace"), vec2(0.0f, 0.0f), dockspaceFlags, windowClass)
# Create Dockspace menu bar
if igBeginMenuBar():
if igBeginMenu("Options", true):
# Create Dockspace menu bar
if igBeginMenuBar():
if igBeginMenu("Options", true):
igMenuItem("Fullscreen", nil, addr opt_fullscreen, true)
igMenuItem("Padding", nil, addr opt_padding, true)
if igMenuItem("Exit", nil, false, (addr showConquest) != nil):
showConquest = false
igEndMenu()
igEndMenuBar()
if igMenuItem("Close", nil, false, (addr showMainWindow) != nil):
showMainWindow = false
igEndMenu()
igEndMenuBar()
# Components and widgets
igShowDemoWindow(nil)
block:
igBegin("Info Window", nil, 0)
defer: igEnd()
igEnd()
igText(cstring(ICON_FA_USER_SHIELD & " " & getFrontendVersionString()))
# render
igRender()
glClearColor(clearColor.elm.x, clearColor.elm.y, clearColor.elm.z, clearColor.elm.w)
glClear(GL_COLOR_BUFFER_BIT)
ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData())
app.render()
if 0 != (io.ConfigFlags and ImGui_ConfigFlags_ViewportsEnable.int32):
var backup_current_window = glfwGetCurrentContext()
igUpdatePlatformWindows()
igRenderPlatformWindowsDefault(nil, nil)
backup_current_window.makeContextCurrent()
hWin.swapBuffers()
if showWindowDelay > 0:
dec showWindowDelay
else:
once: # Avoid flickering screen at startup.
hWin.showWindow()
if not showConquest:
app.handle.setWindowShouldClose(true)
when isMainModule:
windowInit(main)
main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,246 @@
import os, strutils, strformat
import nimgl/[opengl, glfw]
export opengl, glfw
import imguin/[cimgui, glfw_opengl, simple]
export cimgui, glfw_opengl, simple
import ./globals
import ./opengl/[zoomglass, loadImage]
export zoomglass, loadImage
import ./[saveImage, setupFonts, utils, vecs]
export saveImage, setupFonts, utils, vecs
proc glfwGetPlatform*(): int32 {.importc: "glfwGetPlatform".} # GLFW 3.4 >=
type
IniData = object
clearColor*: ccolor
startupPosX*, startupPosY*: cint
viewportWidth*, viewportHeight*: cint
imageSaveFormatIndex*: int
theme: Theme
Window* = object
handle*: glfw.GLFWwindow
context*: ptr ImGuiContext
imnodes*: bool
implot*: bool
implot3d*: bool
implotContext: ptr ImPlotContext
implot3dContext: ptr ImPlot3dContext
showWindowDelay: int
ini*: IniData
# Forward definitions
proc setTheme*(this: var Window, theme: Theme): string
# Sections
const
scWindow = "Window"
startupPosX = "startupPosX"
startupPosY = "startupPosY"
viewportWidth = "viewportWidth"
viewportHeight = "viewportHeigth"
colBGx = "colBGx"
colBGy = "colBGy"
colBGz = "colBGz"
colBGw = "colBGw"
theme = "theme"
scImage = "Image"
imageSaveFormatIndex = "imageSaveFormatIndex"
# Main setup function
proc createApp*(w: cint = 1024, h: cint = 900, imnodes: bool = false, implot: bool = false, implot3d = false, title: string = "ImGui window", docking: bool = true): Window =
doAssert glfwInit()
# result.loadIni()
result.ini.viewportWidth = w
result.ini.viewportHeight = h
result.implot = implot
result.implot3d = implot3d
result.imnodes = imnodes
if result.implot3d:
result.implot = true
var
fDocking = docking
fViewport = false
transparentViewport = false
block:
if transparentViewport:
fViewport = true
if fViewport:
fDocking = true
var glfwWin: GLFWwindow
var glsl_version: string
when defined(windows):
const versions = [[4, 4], [4, 3], [4, 2], [4, 1], [4, 0], [3, 3]]
else:
const versions = [[3, 3]]
for ver in versions:
let
major = ver[0].int32
minor = ver[1].int32
if transparentViewport:
glfwWindowHint(GLFWVisible, GLFW_FALSE)
glfwWindowHint(GLFWContextVersionMajor, major)
glfwWindowHint(GLFWContextVersionMinor, minor)
glfwWindowHint(GLFWOpenglForwardCompat, GLFW_TRUE)
glfwWindowHint(GLFWOpenglProfile, GLFW_OPENGL_CORE_PROFILE)
glfwWindowHint(GLFWResizable, GLFW_TRUE)
glfwWindowHint(GLFWVisible, GLFW_FALSE)
glfwWindowHint(GLFWMaximized, GLFW_TRUE)
glfwWin = glfwCreateWindow(result.ini.viewportWidth, result.ini.viewportHeight, title = title)
glsl_version = fmt"#version {major * 100 + minor * 10}"
if not glfwWin.isNil:
break
if glfwWin.isNil:
quit(-1)
glfwWin.makeContextCurrent()
setWindowPos(glfwWin, result.ini.startupPosX, result.ini.startupPosY)
glfwSwapInterval(1) # Enable vsync
# Load title bar icon
var iconName = os.joinPath(fmt"{CONQUEST_ROOT}/src/client/resources/icon.png")
LoadTileBarIcon(glfwWin, iconName)
doAssert glInit() # OpenGL init
# Setup ImGui
result.context = igCreateContext(nil)
if result.imnodes: # setup ImNodes
when defined(ImNodesEnable):
imnodes_CreateContext()
if result.implot: # setup ImPlot
when defined(ImPlotEnable) or defined(ImPlot) or defined(ImPlot3DEnable) or defined(ImPlot3D):
result.imPlotContext = ImPlot_CreateContext()
else:
echo "Fatal Error!: setup ImPlot: Specify option -d:ImPlot"
quit 1
if result.implot3d: # setup ImPlot3D
when defined(ImPlot3DEnable) or defined(ImPlot3D):
result.imPlot3dContext = ImPlot3d_CreateContext()
else:
echo "Fatal Error!: setup ImPlot3D: Specify option -d:ImPlot3DEnable"
quit 1
if fDocking:
var pio = igGetIO()
pio.ConfigFlags = pio.ConfigFlags or ImGui_ConfigFlags_DockingEnable.cint
if fViewport:
pio.ConfigFlags = pio.ConfigFlags or ImGui_ConfigFlags_ViewportsEnable.cint
pio.ConfigViewports_NoAutomerge = true
# GLFW + OpenGL
doAssert ImGui_ImplGlfw_InitForOpenGL(cast[ptr GLFWwindow](glfwwin), true)
doAssert ImGui_ImplOpenGL3_Init(glsl_version.cstring)
if transparentViewport:
result.ini.clearColor = ccolor(elm:(x:0f, y:0f, z:0f, w:0.0f)) # Transparent
result.handle = glfwWin
var pio = igGetIO()
pio.IniFileName = fmt"{CONQUEST_ROOT}/data/layout.ini"
setTheme(Dark)
discard setupFonts()
result.showWindowDelay = 2
# pollEvents
proc pollEvents*() =
glfwPollEvents()
# isIconifySleep
proc isIconifySleep*(win: Window): bool =
if getWindowAttrib(win.handle, GLFW_ICONIFIED) != 0:
ImGui_ImplGlfw_Sleep(10)
return true
# render
proc render*(window: var Window) =
igRender()
glClearColor(window.ini.clearColor.elm.x, window.ini.clearColor.elm.y, window.ini.clearColor.elm.z, window.ini.clearColor.elm.w)
glClear(GL_COLOR_BUFFER_BIT)
ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData())
var pio = igGetIO()
if 0 != (pio.ConfigFlags and ImGui_ConfigFlags_ViewportsEnable.cint):
var backup_current_window = glfwGetCurrentContext()
igUpdatePlatformWindows()
igRenderPlatformWindowsDefault(nil, nil)
backup_current_window.makeContextCurrent()
window.handle.swapBuffers()
if window.showWindowDelay > 0:
dec window.showWindowDelay
else:
once: # Avoid flickering screen at startup.
window.handle.showWindow()
# Cleanup
proc destroyApp*(window: var Window) =
# window.saveIni()
ImGui_ImplOpenGL3_Shutdown()
ImGui_ImplGlfw_Shutdown()
when defined(ImPlotEnable) or defined(ImPlot):
if window.implot:
window.imPlotContext.ImPlotDestroyContext()
when defined(ImPlot3DEnable) or defined(ImPlot3D):
if window.implot3d:
window.implot3dContext.ImPlot3dDestroyContext()
when defined(ImNodesEnable):
if window.imnodes:
imnodes_DestroyContext(nil)
window.context.igDestroyContext()
window.handle.destroyWindow()
glfwTerminate()
# newFrame
proc newFrame*() =
ImGui_ImplOpenGL3_NewFrame()
ImGui_ImplGlfw_NewFrame()
igNewFrame()
proc getFrontendVersionString*(): string =
fmt"GLFW v{$glfwGetVersionString()}"
proc getBackendVersionString*(): string =
fmt"OpenGL v{($cast[cstring](glGetString(GL_VERSION))).split[0]} (Backend)"
# setClearColor
proc setClearColor*(win: var Window, col: ccolor) =
win.ini.clearColor = col
# free
proc free*(mem: pointer) {.importc, header:"<stdlib.h>".}
# setTheme
proc setTheme*(this: var Window, theme: Theme): string =
this.ini.theme = theme
utils.setTheme(theme)
return $theme
# getTheme
proc getTheme*(this: Window): Theme =
return this.ini.theme
# getThemeLabel
proc getThemeLabel*(this: Window): string =
return $this.ini.theme

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
### README about C language header file
`IconsFontAwesome6.h` file is part of below project,
[https://github.com/juliettef/IconFontCppHeaders](https://github.com/juliettef/IconFontCppHeaders)
by audin, 2023/04

View File

@@ -0,0 +1,165 @@
Fonticons, Inc. (https://fontawesome.com)
--------------------------------------------------------------------------------
Font Awesome Free License
Font Awesome Free is free, open source, and GPL friendly. You can use it for
commercial projects, open source projects, or really almost whatever you want.
Full Font Awesome Free license: https://fontawesome.com/license/free.
--------------------------------------------------------------------------------
# Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)
The Font Awesome Free download is licensed under a Creative Commons
Attribution 4.0 International License and applies to all icons packaged
as SVG and JS file types.
--------------------------------------------------------------------------------
# Fonts: SIL OFL 1.1 License
In the Font Awesome Free download, the SIL OFL license applies to all icons
packaged as web and desktop font files.
Copyright (c) 2023 Fonticons, Inc. (https://fontawesome.com)
with Reserved Font Name: "Font Awesome".
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
SIL OPEN FONT LICENSE
Version 1.1 - 26 February 2007
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting — in part or in whole — any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
--------------------------------------------------------------------------------
# Code: MIT License (https://opensource.org/licenses/MIT)
In the Font Awesome Free download, the MIT license applies to all non-font and
non-icon files.
Copyright 2023 Fonticons, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in the
Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
# Attribution
Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font
Awesome Free files already contain embedded comments with sufficient
attribution, so you shouldn't need to do anything additional when using these
files normally.
We've kept attribution comments terse, so we ask that you do not actively work
to remove them from files, especially code. They're a great way for folks to
learn about Font Awesome.
--------------------------------------------------------------------------------
# Brand Icons
All brand icons are trademarks of their respective owners. The use of these
trademarks does not indicate endorsement of the trademark holder by Font
Awesome, nor vice versa. **Please do not use brand logos for any purpose except
to represent the company, product, or service to which they refer.**

View File

@@ -0,0 +1,10 @@
### README about font file
The `fa-solid-900.ttf` file is part of **fontawesome-free-6.4.0-web.zip**.
Please refer to its License file, `LICENSE.txt`
Web page is [https://fontawesome.com/](https://fontawesome.com/).
by audin, 2023/04

Binary file not shown.

View File

@@ -0,0 +1 @@
const CONQUEST_ROOT* {.strdefine.} = ""

View File

@@ -1,97 +0,0 @@
import imguin/cimgui
type
Vec2* = ImVec2
Vec4* = ImVec4
proc vec2*(x, y: auto): ImVec2 =
ImVec2(x: x.cfloat, y: y.cfloat)
proc vec4*(x, y, z, w: auto): ImVec4 =
ImVec4(x: x.cfloat , y: y.cfloat , z: z.cfloat , w: w.cfloat)
# Tooltips
proc setTooltip*(str:string, delay=Imgui_HoveredFlags_DelayNormal.cint, color=ImVec4(x: 1.0, y: 1.0, z: 1.0, w: 1.0)) =
if igIsItemHovered(delay):
if igBeginTooltip():
igPushStyleColorVec4(ImGuiCol_Text.cint, color)
igText(str)
igPopStyleColor(1)
igEndTooltip()
# IM_COL32
proc IM_COL32*(a,b,c,d:uint32): ImU32 =
return igGetColorU32_Vec4(vec4(a.cfloat/255, b.cfloat/255, c.cfloat/255, d.cfloat/255))
# Definitions from imguin/simple (https://github.com/dinau/imguin/blob/main/src/imguin/simple.nim)
{.push discardable.} # Push discardable applies the {.discardable.} pragma to all functions until the {.pop.} pragma is reached
when false:
type CColor* = object
x,y,z,w: cfloat
proc array3(self:ccolor): array[3,cfloat] =
result = cast[array[3,cfloat]]([self.x,self.y,self.z])
proc newCColor(col:ImVec4):ccolor =
result.x = col.x
result.y = col.y
result.z = col.z
result.w = col.w
proc vec4*(self:ccolor): ImVec4 =
ImVec4(x:self.x,y:self.y,z:self.z,w:self.z)
else:
type CColor* {.union.} = object
elm*: tuple[x,y,z,w: cfloat]
array3*: array[3, cfloat]
vec4*: ImVec4
proc igInputTextWithHint*(label: string, hint: string, buf: string, bufsize: int = buf.len, flags:Imguiinputtextflags = 0.Imguiinputtextflags, callback: ImguiInputTextCallback = nil, userdata: pointer = nil): bool {.inline,discardable.} =
igInputTextWithHint(label.cstring, hint.cstring, buf.cstring, bufsize.cuint, flags, callback, userdata)
proc igPlotLines*[T](label:string, arry: openArray[T], size:int= arry.len, offset:int = 0, overlayText:string = "", smin:float = igGetFLTMax(), smax:float = igGetFLTMax(), graphSize:Imvec2 = ImVec2(x:0,y:0), stride:int = sizeof(cfloat)) {.inline.} =
igPlotLinesFloatPtr(label.cstring, cast[ptr T](addr arry), size.cint, offset.cint, overlayText.cstring, smin.cfloat, smax.cfloat, graphSize, stride.cint)
when defined(ImKnobsEnable) or defined(ImKnobs):
proc IgKnobEx*(label: cstring; p_value: ptr cfloat; v_min: cfloat; v_max: cfloat; speed: cfloat; format: cstring; variant: IgKnobVariant; size: cfloat; flags: IgKnobFlags; steps: cint; angle_min: cfloat; angle_max: cfloat): bool =
return IgKnobFloat(label, p_value, v_min, v_max, speed, format, variant, size, flags, steps, angle_min, angle_max)
proc IgKnob*(label: cstring; p_value: ptr cfloat; v_min: cfloat; v_max: cfloat): bool =
return IgKnobFloat(label, p_value, v_min, v_max, 0, "%.3f", IgKnobVariant_Tick.IgKnobVariant,0, cast[IgKnobFlags](0),10,-1,-1)
proc igPushStyleColor*(idx: ImGuiCol; col: ImU32) = igPushStyleColor_U32(idx, col)
proc igPushStyleColor*(idx: ImGuiCol; col: ImVec4) = igPushStyleColor_Vec4(idx, col)
proc igSameLine*() = igSameLine(0.0, -1.0)
proc igBeginMenuEx*(label: cstring, icon: cstring, enabled: bool = true): bool {.importc: "igBeginMenuEx".}
proc igMenuItem*(label: cstring, shortcut: cstring = nil, selected: bool = false, enabled: bool = true): bool {.importc: "igMenuItem_Bool".}
proc igMenuItem*(label: cstring, shortcut: cstring, p_selected: ptr bool, enabled: bool = true): bool {.importc: "igMenuItem_BoolPtr".}
proc igMenuItemEx*(label: cstring, icon: cstring, shortcut: cstring = nil, selected: bool = false, enabled: bool = true): bool {.importc: "igMenuItemEx".}
proc igBeginChild*(str_id: cstring, size: ImVec2 = ImVec2(x: 0, y: 0), border: bool = false, flags: ImGuiWindowFlags = 0.ImGuiWindowFlags): bool {.importc: "igBeginChild_Str".}
proc igBeginChild*(id: ImGuiID, size: ImVec2 = ImVec2(x: 0, y: 0), border: bool = false, flags: ImGuiWindowFlags = 0.ImGuiWindowFlags): bool {.importc: "igBeginChild_ID".}
when not defined(igGetIO):
template igGetIO*(): ptr ImGuiIO =
igGetIO_Nil()
{.pop.}
# Fonts
proc pointToPx*(point: float32): cfloat =
return ((point * 96) / 72).cfloat
proc setupFonts*(): (bool, string, string) =
let io = igGetIO()
let
fontPath = "/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf"
fontName = "NotoMono-Regular"
fontSize = pointToPx(18.0f)
# Set base font
io.Fonts.ImFontAtlas_AddFontFromFileTTF(fontPath.cstring, fontSize, nil, nil)
result = (true, fontPath, fontName)

View File

@@ -0,0 +1,2 @@
import ./opengl/loadImage
export loadImage

View File

@@ -0,0 +1,149 @@
# Install packages $ nimble stb_image nimgl
import std/[os, strutils, strformat]
when defined(SDL):
import imguin/[glad/gl]
else:
import nimgl/[opengl,glfw]
import stb_image/read as stbi
# Refer to:
# OpenGLでの描画内容の画像化と保存(2012-11-07)
# https://npal-shared.hatenablog.com/entry/20121107/1352284053
type
loadSaveError = object of CatchableError
#------------------------
# loadTextureFromBuffer()
#------------------------
proc loadTextureFromBuffer*(textureID: var uint32, xs, ys, imageWidth, imageHeight:int) =
const comp = RGBA
if 1 > imageWidth or 1 > imageHeight :
raise newException(loadSaveError, "Error!: Rect of image is mismatch")
var
texBuffer = newSeq[GLuByte](imageWidth * imageHeight * comp)
dataBuffer = newSeq[GLuByte](imageWidth * imageHeight * comp)
# Specify OpenGL buffer to be read, 'GL_FRONT': Front buffer, 'GL_BACK': Back buffer
glReadBuffer( GL_BACK )
# Read form OpenGL buffer and save to local buffer
glReadPixels( xs.GLint, ys.GLint, # x,y position (left down) at start //0 or getCurrentWidth() - 1
imageWidth.GLsizei, imageHeight.GLsizei, # width, height to be read
GL_RGBA, # Read type
GL_UNSIGNED_BYTE, # Save type
texBuffer[0].addr) # Pointer to pixel data
when true:
# Fix upside-down of image
let widthStep = comp * imageWidth
var n = 0
for y in 0..<imageHeight:
for x in 0..<imageWidth:
dataBuffer[ ( imageHeight - y - 1 ) * widthStep + (x * comp) + comp - 4 ] = texBuffer[n + comp - 4] # copy R
dataBuffer[ ( imageHeight - y - 1 ) * widthStep + (x * comp) + comp - 3 ] = texBuffer[n + comp - 3] # copy G
dataBuffer[ ( imageHeight - y - 1 ) * widthStep + (x * comp) + comp - 2 ] = texBuffer[n + comp - 2] # copy B
dataBuffer[ ( imageHeight - y - 1 ) * widthStep + (x * comp) + comp - 1 ] = texBuffer[n + comp - 1] # copy A
inc(n,comp)
# Setup filtering parameters for display
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR.GLint)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR.GLint)
# This is required on WebGL for non power-of-two textures
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE.GLint)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE.GLint)
# Upload pixels into texture
#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
# TODO
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)
#endif
# Create a OpenGL texture identifier
var loadReq{.global.}:bool
if textureID == 0:
glGenTextures(1, addr textureID)
loadReq = true
glBindTexture(GL_TEXTURE_2D, textureID)
# Load texture
var err:int
if loadReq:
loadReq = false
glTexImage2D(GL_TEXTURE_2D # target
, 0 # level
, GL_RGBA.GLint # internal format
, imageWidth.GLSizei # width
, imageHeight.GLsizei # height
, 0 # [Border]: 0: Not have border 1: Have border
# https://stackoverflow.com/questions/913801/what-does-border-mean-in-the-glteximage2d-function
, GL_RGBA # format
, GL_UNSIGNED_BYTE # type
, dataBuffer[0].addr) # *pixels
err = glGetError().int
if err != 0:
raise newException(loadSaveError, fmt"Error!: [0x{err:X}]: glTexImage2D()")
# Update texture
glTexSubImage2D(GL_TEXTURE_2D # target
, 0.GLint # level
, 0.Glint, 0.GLint # x,y offset
, imageWidth.GLsizei
, imageHeight.GLsizei
, GL_RGBA #, GL_UNSIGNED_INT_8_8_8_8_REV # is Fast than GL_UNSIGNED_BYTE ?
, GL_UNSIGNED_BYTE
, dataBuffer[0].addr)
err = glGetError().int
if err != 0:
raise newException(loadSaveError, fmt"Error! [0x{err:X}]: glTexSubImage2D()")
#---------------------
# loadTextureFromFile
#---------------------
proc loadTextureFromFile*(filename: string, outTexture: var GLuint, outWidth: var int, outHeight: var int): bool {.discardable.} =
if not filename.fileExists:
echo "Error!: Image file not found error: ", filename
return false
var
channels: int
image_data = stbi.load(filename, outWidth, outHeight, channels, stbi.RGBA)
# Create a OpenGL texture identifier
glGenTextures(1, addr outTexture)
glBindTexture(GL_TEXTURE_2D, outTexture)
# Setup filtering parameters for display
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR.GLint)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR.GLint)
# This is required on WebGL for non power-of-two textures
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE.GLint)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE.GLint)
# Upload pixels into texture
#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
# TODO
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA.GLint
, outWidth.GLSizei, outHeight.GLsizei
, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data[0].addr)
return true
when not defined(SDL):
#---------------------
# Load title bar icon
#---------------------
proc LoadTileBarIcon*(window:GLFWwindow, iconName:string) =
if iconName.fileExists:
var
w, h: int
channels: int
pixels: seq[byte]
pixels = stbi.load(iconName, w, h, channels, stbi.RGBA)
var img = GLFWImage(width: w.int32, height: h.int32
, pixels: cast[ptr cuchar](pixels[0].addr))
glfw.setWindowIcon(window, 1, img.addr)
else:
echo "Not found: ",iconName
glfw.setWindowIcon(window, 0, nil)

View File

@@ -0,0 +1,41 @@
import imguin/[cimgui,simple]
import loadImage
import ../fonticon/IconsFontAwesome6
#--------------
#--- zoomGlass
#--------------
proc zoomGlass*(textureID: var uint32, itemWidth:int, itemPosTop, itemPosEnd:ImVec2 , capture = false) =
# itemPosTop and itemPosEnd are absolute position in main window.
if igBeginItemTooltip():
defer: igEndTooltip()
let itemHeight = itemPosEnd.y.int - itemPosTop.y.int
let my_tex_w = itemWidth.float
let my_tex_h = itemHeight.float
let wkSize = igGetMainViewport().Worksize
if capture:
loadTextureFromBuffer(textureID # TextureID
, itemPosTop.x.int # x start pos
, wkSize.y.int - itemPosEnd.y.int # y start pos
, itemWidth ,itemHeight) # Image width and height must be 2^n.
#igText("lbp: (%.2f, %.2f)", pio.MousePos.x, pio.MousePos.y)
let pio = igGetIO()
let region_sz = 32.0f
var region_x = pio.MousePos.x - itemPosTop.x - region_sz * 0.5f
var region_y = pio.MousePos.y - itemPosTop.y - region_sz * 0.5f
let zoom = 4.0f
if region_x < 0.0f:
region_x = 0.0f
elif region_x > (my_tex_w - region_sz):
region_x = my_tex_w - region_sz
if region_y < 0.0f:
region_y = 0.0f
elif region_y > my_tex_h - region_sz:
region_y = my_tex_h - region_sz
let uv0 = ImVec2(x: (region_x) / my_tex_w, y: (region_y) / my_tex_h)
let uv1 = ImVec2(x: (region_x + region_sz) / my_tex_w, y: (region_y + region_sz) / my_tex_h)
let tint_col = ImVec4(x: 1.0f, y: 1.0f, z: 1.0f, w: 1.0f) #// No tint
let border_col = ImVec4(x: 0.22f, y: 0.56f, z: 0.22f, w: 1.0f) # Green
igText(ICON_FA_MAGNIFYING_GLASS & " 4 x")
let texRef = ImTextureRef(internal_TexData: nil, internal_TexID: textureID)
igImage(texRef, ImVec2(x: region_sz * zoom, y: region_sz * zoom), uv0, uv1) #, tint_col, border_col)

View File

@@ -0,0 +1,58 @@
import std/[os,strutils]
import nimgl/[opengl]
import stb_image/write as stbiw
# saveImage
proc saveImage*(fname:string, xs, ys, width, height:int, comp:int = RGB,quality:int = 90) =
# Image size must be 2*n
let imageWidth = (width div 2) * 2
let imageHeight = (height div 2) * 2
if not (comp == RGB):
echo "Error!: Color component numbers must be 3 (RGB) at saveImage.nim"
return
if 1 > imageWidth or 1 > imageHeight :
echo "Error!: Rect of save image is mismatch at saveImage.nim"
return
var
texBuffer = newSeq[GLuByte](imageWidth * imageHeight * comp)
dataBuffer = newSeq[GLuByte](imageWidth * imageHeight * comp)
glReadBuffer( GL_BACK )
glReadPixels( xs.GLint, ys.GLint,
imageWidth.GLsizei, imageHeight.GLsizei,
GL_RGB,
GL_UNSIGNED_BYTE,
texBuffer[0].addr
)
# Set upside-down
let widthStep = 3 * imageWidth
var n = 0
for y in 0..<imageHeight:
for x in 0..<imageWidth:
dataBuffer[ ( imageHeight - y - 1 ) * widthStep + (x * 3) + 0 ] = texBuffer[n + 0] # copy R
dataBuffer[ ( imageHeight - y - 1 ) * widthStep + (x * 3) + 1 ] = texBuffer[n + 1] # copy G
dataBuffer[ ( imageHeight - y - 1 ) * widthStep + (x * 3) + 2 ] = texBuffer[n + 2] # copy B
inc(n,3)
# Save image
var
(_,_,ext) = fname.splitfile()
res:bool
case ext.toLowerAscii()
of ".jpg",".jpeg":
# JPEG quality is 90% default. quality=1..100
res = stbiw.writeJPG(fname, imageWidth, imageHeight, comp, dataBuffer, quality)
of ".png":
res = stbiw.writePNG(fname, imageWidth, imageHeight, comp, dataBuffer)
of ".bmp":
res = stbiw.writeBMP(fname, imageWidth, imageHeight, comp, dataBuffer)
of ".tga":
# if quality == 0 then useRLE == false.
res = stbiw.writeTGA(fname, imageWidth, imageHeight, comp, dataBuffer, useRLE = (quality > 0))
else:
echo "Error! Unrecognize image extension: [",ext,"]"
res = false
if not res:
echo "Error!: at stbiw.writeNNN() function in saveImage.nim"

View File

@@ -0,0 +1,76 @@
import os, strformat
import imguin/[cimgui, simple]
import ./globals
import ../utils/fonticon/IconsFontAwesome6
export IconsFontAwesome6
let IconfontFullPath = fmt"{CONQUEST_ROOT}/src/client/utils/fonticon/fa6/fa-solid-900.ttf"
# Convert point to pixel
proc point2px*(point: float32): cfloat = ((point * 96) / 72).cfloat
# setupFonts
type
TFontInfo = object
fontDir, osRootDir: string
fontTable: seq[(string, string, float)] # path, name, point
when defined(windows):
const
fontInfo = TFontInfo(
osRootDir: os.getEnv("windir"), # get OS root
fontDir: "fonts",
fontTable: @[ #
("segoeui.ttf", "Seoge UI", 14.4),
]
)
else: # For Debian/Ubuntu/Mint
const
fontInfo = TFontInfo(
osRootDir: "/",
fontDir: "usr/share/fonts",
fontTable: @[
("truetype/noto/NotoSansMono-Regular.ttf", "Noto Sans Mono", 20.0)
]
)
proc new_ImFontConfig(): ImFontConfig =
# Custom constructor with default params taken from imgui.h
result.FontDataOwnedByAtlas = true
result.FontNo = 0
result.OversampleH = 3
result.OversampleV = 1
result.PixelSnapH = false
result.GlyphMaxAdvanceX = float.high
result.RasterizerMultiply = 1.0
result.RasterizerDensity = 1.0
result.MergeMode = false
result.EllipsisChar = cast[ImWchar](-1)
proc setupFonts*(): (bool, string, string) =
let pio = igGetIO()
var config {.global.} = new_ImFontConfig()
# Load first base font
result = (false, "Default", "ProggyClean.ttf")
var seqFontNames: seq[(string, string)]
for (fontName, fontTitle, point) in fontInfo.fontTable:
let fontFullPath = os.joinPath(fontInfo.osRootDir, fontInfo.fontDir, fontName)
if os.fileExists(fontFullPath):
seqFontNames.add((fontName, fontTitle))
pio.Fonts.ImFontAtlas_AddFontFromFileTTF(fontFullPath.cstring, point.point2px, nil, nil)
break
if seqFontNames.len > 0:
result = (true, seqFontNames[0][0].extractFilename, seqFontNames[0][1])
else:
pio.Fonts.ImFontAtlas_AddFontDefault(nil)
# Merge Icon font
config.MergeMode = true
var ranges_icon_fonts {.global.} = [ICON_MIN_FA.uint16, ICON_MAX_FA.uint16, 0]
if os.fileExists(IconfontFullPath):
pio.Fonts.ImFontAtlas_AddFontFromFileTTF(IconfontFullPath.cstring, 11.point2px, addr config, addr ranges_icon_fonts[0])
else:
echo "Error!: Can't find Icon fonts: ", IconfontFullPath

View File

@@ -0,0 +1,45 @@
import imguin/cimgui
import ../utils/[utils,vecs]
#--------------------------------------------------------
# This is very simple toggle button implement from
# https://github.com/sonoro1234/anima/blob/09901c69586bddd6d0463e8b7460eb251a1837e2/anima/igwidgets.lua#L6-L30
# Refer to
# https://github.com/ocornut/imgui/issues/1537
#--------------------------------------------------------
# igToggleButton
proc igToggleButton*(str_id:string, v: var bool): bool =
var pos: ImVec2
igGetCursorScreenPos(addr pos)
let draw_list = igGetWindowDrawList()
let height = igGetFrameHeight() * 0.9
let width = height * 1.65
let radius = height * 0.50
var ret = false
if igInvisibleButton(str_id.cstring, vec2(width, height), 0.ImGuiButtonFlags):
v = not v
ret = true
var col_bg, col_base: ImU32
if igIsItemHovered(0.ImGuiHoveredFlags):
col_base = IM_COL32(218-20, 218-20, 218-20, 255)
col_bg = col_base
if v:
col_bg = col_base or igGetColorU32_U32(ImGuiCol_ButtonHovered.ImU32, 1)
else:
col_base = IM_COL32(218, 218, 218, 255)
col_bg = col_base
if v:
col_bg = col_base or igGetColorU32_U32(ImGuiCol_Button.ImU32, 1)
draw_list.ImDrawList_AddRectFilled(pos, vec2(pos.x + width, pos.y + height), col_bg, height * 0.5, 0.ImDrawFlags)
var m:cfloat
if v:
m = pos.x + width - radius
else:
m = pos.x + radius
draw_list.ImDrawList_AddCircleFilled(vec2(m , pos.y + radius) ,radius - 1.5 ,IM_COL32(255, 255, 255, 255) ,0)
igSameLine(0.0, -1.0)
igText(str_id)
return ret

View File

@@ -0,0 +1,31 @@
import imguin/[cimgui]
import ./vecs
#---------------
#--- setTooltip
#---------------
proc setTooltip*(str:string, delay=Imgui_HoveredFlags_DelayNormal.cint, color=ImVec4(x: 1.0, y: 1.0, z: 1.0, w: 1.0)) =
if igIsItemHovered(delay):
if igBeginTooltip():
igPushStyleColorVec4(ImGuiCol_Text.cint, color)
igText(str)
igPopStyleColor(1)
igEndTooltip()
type
Theme* = enum
Light, Dark, Classic
# setTheme
proc setTheme*(themeName: Theme) =
case themeName
of Light:
igStyleColorsLight(nil)
of Dark:
igStyleColorsDark(nil)
of Classic:
igStyleColorsClassic(nil)
# IM_COL32
proc IM_COL32*(a,b,c,d:uint32): ImU32 =
return igGetColorU32_Vec4(vec4(a.cfloat/255, b.cfloat/255, c.cfloat/255, d.cfloat/255))

11
src/client/utils/vecs.nim Normal file
View File

@@ -0,0 +1,11 @@
import imguin/cimgui
type
Vec2* = ImVec2
Vec4* = ImVec4
proc vec2*(x, y: auto): ImVec2 =
ImVec2(x: x.cfloat, y: y.cfloat)
proc vec4*(x, y, z, w: auto): ImVec4 =
ImVec4(x: x.cfloat , y: y.cfloat , z: z.cfloat , w: w.cfloat)

View File

@@ -1,62 +0,0 @@
import os
import nimgl/[opengl, glfw]
import imguin/glfw_opengl
import ./lib
const CONQUEST_ROOT* {.strdefine.} = ""
when defined(windows):
when not defined(vcc): # imguinVcc.res TODO WIP
include ./res/resource
import tinydialogs
# Forward definitions
proc windowInit*(winMain: proc(win: glfw.GLFWWindow)) =
doAssert glfwInit()
defer: glfwTerminate()
glfwWindowHint(GLFWContextVersionMajor, 3)
glfwWindowHint(GLFWContextVersionMinor, 3)
glfwWindowHint(GLFWOpenglForwardCompat, GLFW_TRUE)
glfwWindowHint(GLFWOpenglProfile, GLFW_OPENGL_CORE_PROFILE)
glfwWindowHint(GLFWResizable, GLFW_TRUE)
glfwWindowHint(GLFWVisible, GLFW_FALSE)
glfwWindowHint(GLFWMaximized, GLFW_TRUE) # Maximize Window on startup
var glfwWin = glfwCreateWindow(1024, 800, "Conquest")
if glfwWin.isNil:
quit(-1)
glfwWin.makeContextCurrent()
defer: glfwWin.destroyWindow()
glfwSwapInterval(1) # Enable vsync
# TODO: Set application icon (requires imguin_examples/utils/loadImage [https://github.com/dinau/imguin_examples/blob/main/utils/opengl/loadImage.nim])
# var IconName = joinPath(CONQUEST_ROOT, "src/client/resources/icon.png")
# LoadTileBarIcon(glfwWin, IconName)
doAssert glInit() # OpenGL init
# Setup ImGui
let context = igCreateContext(nil)
defer: context.igDestroyContext()
# Configure docking
var pio = igGetIO()
pio.ConfigFlags = pio.ConfigFlags or ImGui_ConfigFlags_DockingEnable.int32
# GLFW + OpenGL
const glsl_version = "#version 130" # GL 3.0 + GLSL 130
doAssert ImGui_ImplGlfw_InitForOpenGL(cast[ptr GLFWwindow](glfwwin), true)
defer: ImGui_ImplGlfw_Shutdown()
doAssert ImGui_ImplOpenGL3_Init(glsl_version)
defer: ImGui_ImplOpenGL3_Shutdown()
# Set ini filename
pio.IniFileName = CONQUEST_ROOT & "/data/layout.ini"
glfwWin.winMain()