Added initial client UI structure.
This commit is contained in:
@@ -9,12 +9,12 @@ srcDir = "src"
|
|||||||
# Build tasks
|
# Build tasks
|
||||||
|
|
||||||
import os, strformat
|
import os, strformat
|
||||||
|
let cqRoot = getCurrentDir()
|
||||||
task server, "Build conquest server binary":
|
task server, "Build conquest server binary":
|
||||||
let cqRoot = getCurrentDir()
|
|
||||||
exec fmt"nim c -d:CONQUEST_ROOT={cqRoot} src/server/main.nim"
|
exec fmt"nim c -d:CONQUEST_ROOT={cqRoot} src/server/main.nim"
|
||||||
|
|
||||||
task client, "Build conquest client binary":
|
task client, "Build conquest client binary":
|
||||||
discard
|
exec fmt"nim c -d:release -d:CONQUEST_ROOT={cqRoot} src/client/main.nim"
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|
||||||
@@ -28,3 +28,4 @@ requires "tiny_sqlite >= 0.2.0"
|
|||||||
requires "prologue >= 0.6.6"
|
requires "prologue >= 0.6.6"
|
||||||
requires "winim >= 3.9.4"
|
requires "winim >= 3.9.4"
|
||||||
requires "ptr_math >= 0.3.0"
|
requires "ptr_math >= 0.3.0"
|
||||||
|
requires "imguin >= 1.92.2.0"
|
||||||
36
data/layout.ini
Normal file
36
data/layout.ini
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
[Window][CQ]
|
||||||
|
Size=2868,1695
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Dear ImGui Demo]
|
||||||
|
Pos=0,30
|
||||||
|
Size=2868,1665
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000001,0
|
||||||
|
|
||||||
|
[Window][Debug##Default]
|
||||||
|
Pos=60,60
|
||||||
|
Size=400,400
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Conquest]
|
||||||
|
Pos=0,0
|
||||||
|
Size=2868,1695
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Dear ImGui Style Editor]
|
||||||
|
Pos=123,79
|
||||||
|
Size=1080,1629
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Example: Console]
|
||||||
|
Pos=0,781
|
||||||
|
Size=2868,914
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000002,0
|
||||||
|
|
||||||
|
[Docking][Data]
|
||||||
|
DockSpace ID=0x3674675E Window=0x538FB738 Pos=0,30 Size=2868,1665 Split=Y Selected=0x5E5F7166
|
||||||
|
DockNode ID=0x00000001 Parent=0x3674675E SizeRef=2868,749 CentralNode=1 Selected=0x5E5F7166
|
||||||
|
DockNode ID=0x00000002 Parent=0x3674675E SizeRef=2868,914 Selected=0x1BCA3180
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ Basic API-only Commands
|
|||||||
Execution Commands
|
Execution Commands
|
||||||
------------------
|
------------------
|
||||||
- [x] shell : Execute shell command (to be implemented using Windows APIs instead of execCmdEx)
|
- [x] shell : Execute shell command (to be implemented using Windows APIs instead of execCmdEx)
|
||||||
- [ ] bof : Execute Beacon Object File in memory and retrieve output (bof /local/path/file.o)
|
- [x] bof : Execute Beacon Object File in memory and retrieve output (bof /local/path/file.o)
|
||||||
- Read from listener endpoint directly to memory
|
- Read from listener endpoint directly to memory
|
||||||
- Base for all kinds of BOFs (Situational Awareness, ...)
|
- Base for all kinds of BOFs (Situational Awareness, ...)
|
||||||
- [ ] pe : Execute PE file in memory and retrieve output (pe /local/path/mimikatz.exe)
|
- [ ] pe : Execute PE file in memory and retrieve output (pe /local/path/mimikatz.exe)
|
||||||
@@ -35,10 +35,10 @@ Execution Commands
|
|||||||
|
|
||||||
Post-Exploitation
|
Post-Exploitation
|
||||||
-----------------
|
-----------------
|
||||||
- [ ] upload : Upload file from server to agent (upload /local/path/to/file C:\Windows\Tasks)
|
- [x] upload : Upload file from server to agent (upload /local/path/to/file C:\Windows\Tasks)
|
||||||
- File to be downloaded moved to specific endpoint on listener, e.g. GET /<listener>/<agent>/<upload-task>/file
|
- File to be downloaded moved to specific endpoint on listener, e.g. GET /<listener>/<agent>/<upload-task>/file
|
||||||
- Read from webserver and written to disk
|
- Read from webserver and written to disk
|
||||||
- [ ] download : Download file from agent to teamserver
|
- [x] download : Download file from agent to teamserver
|
||||||
- Create loot directory for agent to store files in
|
- Create loot directory for agent to store files in
|
||||||
- Read file into memory and send byte stream to specific endpoint, e.g. POST /<listener>/<agent>/<download>-task/file
|
- Read file into memory and send byte stream to specific endpoint, e.g. POST /<listener>/<agent>/<download>-task/file
|
||||||
- Encrypt file in-transit!!!
|
- Encrypt file in-transit!!!
|
||||||
|
|||||||
73
src/client/config.nims
Normal file
73
src/client/config.nims
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
switch "o", "bin/client"
|
||||||
|
|
||||||
|
# Select compiler
|
||||||
|
var TC = "gcc"
|
||||||
|
# var TC = "clang"
|
||||||
|
|
||||||
|
# Dismiss background window
|
||||||
|
switch "app", "gui"
|
||||||
|
|
||||||
|
# Select static link or shared/dll link
|
||||||
|
when defined(windows):
|
||||||
|
const STATIC_LINK_GLFW = false
|
||||||
|
const STATIC_LINK_CC = true #libstd++ or libc
|
||||||
|
if TC == "vcc":
|
||||||
|
switch "passL","d3d9.lib kernel32.lib user32.lib gdi32.lib winspool.lib"
|
||||||
|
switch "passL","comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib"
|
||||||
|
switch "passL","uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
switch "passL","imm32.lib"
|
||||||
|
else:
|
||||||
|
switch "passL","-lgdi32 -limm32 -lcomdlg32 -luser32 -lshell32"
|
||||||
|
else: # for Linux
|
||||||
|
const STATIC_LINK_GLFW = true
|
||||||
|
const STATIC_LINK_CC= false
|
||||||
|
|
||||||
|
when STATIC_LINK_GLFW: # GLFW static link
|
||||||
|
switch "define","glfwStaticLib"
|
||||||
|
else: # shared/dll
|
||||||
|
when defined(windows):
|
||||||
|
if TC == "vcc":
|
||||||
|
discard
|
||||||
|
else:
|
||||||
|
switch "passL","-lglfw3.dll"
|
||||||
|
switch "define", "glfwDLL"
|
||||||
|
#switch "define","cimguiDLL"
|
||||||
|
else:
|
||||||
|
switch "passL","-lglfw"
|
||||||
|
|
||||||
|
when STATIC_LINK_CC: # gcc static link
|
||||||
|
case TC
|
||||||
|
of "vcc":
|
||||||
|
discard
|
||||||
|
else:
|
||||||
|
switch "passC", "-static"
|
||||||
|
switch "passL", "-static "
|
||||||
|
|
||||||
|
# Set compiler options
|
||||||
|
case TC
|
||||||
|
of "vcc" , "clang_cl":
|
||||||
|
switch "define","lto"
|
||||||
|
else:
|
||||||
|
if "" == findExe(TC): # GCC is default compiler if TC dosn't exist on the PATH
|
||||||
|
echo "#### Set to cc = ",TC
|
||||||
|
TC = "gcc"
|
||||||
|
if "" == findExe(TC): # if gcc dosn't exist, try clang
|
||||||
|
TC = "clang"
|
||||||
|
echo "#### Set to cc = ",TC
|
||||||
|
|
||||||
|
# Reduce code size further
|
||||||
|
when false:
|
||||||
|
switch "gc", "arc"
|
||||||
|
switch "define", "useMalloc"
|
||||||
|
switch "define", "noSignalHandler"
|
||||||
|
|
||||||
|
case TC
|
||||||
|
of "gcc":
|
||||||
|
switch "passC", "-ffunction-sections"
|
||||||
|
switch "passC", "-fdata-sections"
|
||||||
|
switch "passL", "-Wl,--gc-sections"
|
||||||
|
switch "cc",TC
|
||||||
|
of "clang":
|
||||||
|
switch "cc.exe","clang"
|
||||||
|
switch "cc.linkerexe","clang"
|
||||||
|
switch "cc",TC
|
||||||
112
src/client/main.nim
Normal file
112
src/client/main.nim
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
import nimgl/[opengl, glfw]
|
||||||
|
import imguin/glfw_opengl
|
||||||
|
import ./utils/[lib, windowInit]
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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()
|
||||||
|
|
||||||
|
let io = igGetIO()
|
||||||
|
|
||||||
|
# main loop
|
||||||
|
while not hWin.windowShouldClose:
|
||||||
|
glfwPollEvents()
|
||||||
|
|
||||||
|
if getWindowAttrib(hWin, GLFW_ICONIFIED) != 0:
|
||||||
|
ImGui_ImplGlfw_Sleep(10)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Start ImGUI frame
|
||||||
|
ImGui_ImplOpenGL3_NewFrame()
|
||||||
|
ImGui_ImplGlfw_NewFrame()
|
||||||
|
igNewFrame()
|
||||||
|
|
||||||
|
# Create Dockspace where all windows are placed in
|
||||||
|
if opt_fullscreen:
|
||||||
|
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
|
||||||
|
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:
|
||||||
|
igPushStyleVar_Vec2(ImGuiStyleVar_WindowPadding.int32, vec2(0.0f, 0.0f))
|
||||||
|
|
||||||
|
igBegin("Conquest", addr showMainWindow, windowFlags)
|
||||||
|
|
||||||
|
if not opt_padding:
|
||||||
|
igPopStyleVar(1)
|
||||||
|
|
||||||
|
if opt_fullscreen:
|
||||||
|
igPopStyleVar(2)
|
||||||
|
|
||||||
|
# Create dockspace
|
||||||
|
if (io.ConfigFlags and ImGui_ConfigFlags_DockingEnable.int32) != ImGui_ConfigFlags_None.int32:
|
||||||
|
igDockSpace(igGetID_Str("Conquest-Dockspace"), vec2(0.0f, 0.0f), dockspaceFlags, windowClass)
|
||||||
|
|
||||||
|
# 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("Close", nil, false, (addr showMainWindow) != nil):
|
||||||
|
showMainWindow = false
|
||||||
|
igEndMenu()
|
||||||
|
igEndMenuBar()
|
||||||
|
|
||||||
|
# Components and widgets
|
||||||
|
igShowDemoWindow(nil)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
igEnd()
|
||||||
|
|
||||||
|
# render
|
||||||
|
igRender()
|
||||||
|
glClearColor(clearColor.elm.x, clearColor.elm.y, clearColor.elm.z, clearColor.elm.w)
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT)
|
||||||
|
ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData())
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
windowInit(main)
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
-d:"adwminor=4"
|
|
||||||
--outdir:"../bin"
|
|
||||||
97
src/client/utils/lib.nim
Normal file
97
src/client/utils/lib.nim
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
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)
|
||||||
|
|
||||||
62
src/client/utils/windowInit.nim
Normal file
62
src/client/utils/windowInit.nim
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user