4 utils, gfx, map, vfs, config,
5 gui/[common, controls, file_dialog, wad_dialog, map_dialog, message_box]
8 common, controls, file_dialog, wad_dialog, map_dialog, message_box, imgui
15 customBarColBg*: DFColor = colDkGrey
16 customBarColFg*: DFColor = colGrey
17 customBarColMove*: DFColor = colWhite
21 selection*: seq[MapObject] = @[]
24 CustomScrollBar* = object
34 ActionProc = proc (): void
37 confirmBox: MessageBox
38 confirmAction: ActionProc = nil
40 proc toDFColor*(c: ImVec4): DFColor =
41 result.r = uint8(c.x * 255f)
42 result.g = uint8(c.y * 255f)
43 result.b = uint8(c.z * 255f)
44 result.a = uint8(c.w * 255f)
50 addExitProc(gui.shutdown)
51 let style = imgui.getStyle()
52 customBarColBg = style.colors[ImGuiCol.ScrollbarBg.int32].toDFColor()
53 customBarColBg.a = 0xFF'u8
54 customBarColFg = style.colors[ImGuiCol.ScrollbarGrab.int32].toDFColor()
55 customBarColMove = style.colors[ImGuiCol.ScrollbarGrabActive.int32].toDFColor()
57 proc openDiscardWarning() =
58 confirmBox.open(mbQuestion, "Are you sure you want to discard the current map?")
60 proc emitMapOpenDialog() =
61 defaultFileDialog.open("Select WAD", "maps", archiveExts, false, "")
63 proc emitMapSelectDialog() =
66 proc emitMainFileMenu() =
67 if imgui.menuItem("New Map", "Ctrl+N"):
69 confirmAction = map.create
70 if imgui.menuItem("Open Map", "Ctrl+O"):
72 confirmAction = emitMapOpenDialog
73 if imgui.menuItem("Select Map"):
75 confirmAction = emitMapSelectDialog
76 if imgui.menuItem("Reopen Map", "F5"):
78 confirmAction = map.reopen
80 if imgui.menuItem("Save Map", "Ctrl+S"):
82 if imgui.menuItem("Save Map As..."):
84 if imgui.menuItem("Pack Map"):
86 if imgui.menuItem("Delete Map from WAD..."):
89 if imgui.menuItem("Exit", "F10"):
90 confirmBox.open(mbQuestion, "Are you sure you want to quit?")
93 proc emitMainEditMenu() =
94 if imgui.menuItem("Undo", "Ctrl+Z"):
96 if imgui.menuItem("Redo", "Ctrl+Y"):
99 if imgui.menuItem("Copy", "Ctrl+C"):
101 if imgui.menuItem("Cut", "Ctrl+X"):
103 if imgui.menuItem("Paste", "Ctrl+V"):
106 if imgui.menuItem("Select All", "Ctrl+A"):
108 if imgui.menuItem("Invert Selection"):
111 if imgui.menuItem("Snap to Grid", "Ctrl+Q"):
113 if imgui.menuItem("Bring to Front", "Ctrl+]"):
115 if imgui.menuItem("Send to Back", "Ctrl+["):
118 proc emitMainViewMenu() =
119 imgui.doMenu("Layers"):
120 for i, x in config.showLayer.mpairs():
121 imgui.menuItem($i, $(i.int + 1), x.addr)
123 imgui.menuItem("Show Map edges", "", config.showMapEdges.addr)
124 imgui.menuItem("Show Grid", "", config.showGrid.addr)
125 imgui.menuItem("Show Mini Map", "", config.showMiniMap.addr)
127 imgui.menuItem("Preview Mode", "TAB", config.showPreview.addr)
129 proc emitMainPropertiesMenu() =
130 if imgui.menuItem("Switch Grid step", "Ctrl+E"):
133 if imgui.menuItem("Map Properties"):
136 if imgui.menuItem("Editor Settings"):
139 proc emitMainToolsMenu() =
140 if imgui.menuItem("Check Map"):
142 if imgui.menuItem("Optimize Map"):
144 if imgui.menuItem("Run Map"):
147 proc emitAboutWindow() =
150 proc emitMainMenuBar() =
151 imgui.doMainMenuBar():
152 imgui.doMenu("File"):
154 imgui.doMenu("Edit"):
156 imgui.doMenu("View"):
158 imgui.doMenu("Properties"):
159 emitMainPropertiesMenu()
160 imgui.doMenu("Tools"):
162 imgui.doMenu("Help"):
163 if imgui.menuItem("About"):
167 imgui.setNextWindowPos(ImVec2(x: float32(gfx.vidWidth() - dockSizeRight), y: menuBarHeight.float32))
168 imgui.setNextWindowSize(ImVec2(x: dockSizeRight.float32, y: float32(gfx.vidHeight() - menuBarHeight)))
169 if imgui.beginWindow("##ObjInfo", nil, ImGuiWindowFlags.NoTitleBar or ImGuiWindowFlags.NoMove or ImGuiWindowFlags.NoResize):
172 proc emitBottomBar() =
173 imgui.setNextWindowPos(ImVec2(x: 0f, y: float32(gfx.vidHeight() - dockSizeBottom)))
174 imgui.setNextWindowSize(ImVec2(x: (gfx.vidWidth() - dockSizeRight).float32, y: dockSizeBottom.float32))
175 if imgui.beginWindow("##BottomBar", nil, ImGuiWindowFlags.NoTitleBar or ImGuiWindowFlags.NoMove or ImGuiWindowFlags.NoResize):
178 proc mainWindow*(): bool =
181 discard defaultInfoBox.display()
182 discard defaultWarningBox.display()
183 discard defaultErrorBox.display()
189 if confirmBox.display():
190 if confirmBox.getResult() == 1:
191 if confirmAction != nil:
197 if defaultFileDialog.display():
198 let wadPath = defaultFileDialog.getResultPath()
200 if defaultFileDialog.isReading():
203 var ar = vfs.mount(wadPath, true, true, true)
205 defaultMapDialog.open("Select map", ar, false)
207 discard defaultErrorBox.open(mbError, getCurrentExceptionMsg())
209 if defaultMapDialog.display():
210 let mapName = defaultMapDialog.getResult()
212 if defaultMapDialog.isReading():
216 proc maxViewportSize*(): DFSize =
217 result = gfx.vidSize()
218 result.w -= dockSizeLeft + dockSizeRight + customBarWidth
219 result.h -= dockSizeBottom + customBarWidth + menuBarHeight
221 proc viewportPos*(): DFPoint =
222 result = (dockSizeLeft, menuBarHeight)
224 proc viewportMousePos*(): DFPoint =
225 let v = imgui.getMousePos()
230 result = result - viewportPos()
232 proc scrollControls(self: var CustomScrollBar, x: var int) =
233 let pos = viewportMousePos()
235 if not imgui.isAnyModalPopupOpen():
237 if not imgui.isMouseDown(ImGuiMouseButton.Left):
240 if imgui.igIsMouseClicked(ImGuiMouseButton.Left):
241 if intersect(pos, self.start, self.size):
247 let mxPos = (if self.axis == 0: pos.x else: pos.y).float32
248 let endX = (self.maxSize - self.size.component(self.axis)).float32
249 let mxStart = self.barSize.component(self.axis).float32 / 2f
250 let mxEnd = self.size.component(self.axis).float32 - mxStart
251 let mxRatio = (mxPos - mxStart) / (mxEnd - mxStart)
252 x = int(clamp(mxRatio, 0f, 1f) * endX)
254 proc hscroll*(self: var CustomScrollBar, x: var int, size, maxSize, startY: int) =
256 self.start = (0, startY)
257 self.size = (size, customBarWidth)
258 self.barSize = (int((size.float32 / maxSize.float32) * size.float32), customBarWidth)
259 self.barStart = (int((x.float32 / maxSize.float32) * size.float32), self.start.y)
260 self.maxSize = maxSize
262 self.scrollControls(x)
264 gfx.drawQuad(self.start, (self.size.x + customBarWidth, self.size.y), customBarColBg)
265 gfx.drawQuad(self.barStart, self.barSize, (if self.active: customBarColMove else: customBarColFg))
267 proc vscroll*(self: var CustomScrollBar, x: var int, size, maxSize, startX: int) =
269 self.start = (startX, 0)
270 self.size = (customBarWidth, size)
271 self.barSize = (customBarWidth, int((size.float32 / maxSize.float32) * size.float32))
272 self.barStart = (self.start.x, int((x.float32 / maxSize.float32) * size.float32))
273 self.maxSize = maxSize
275 self.scrollControls(x)
277 gfx.drawQuad(self.start, (self.size.x, self.size.y + customBarWidth), customBarColBg)
278 gfx.drawQuad(self.barStart, self.barSize, (if self.active: customBarColMove else: customBarColFg))