Skip to content

Commit 6c9c028

Browse files
authored
Adds info and camera control windows (#118)
* Adds info and camera control windows * Update docs and docstrings * Increase buf for pdflatex
1 parent 7a1a13c commit 6c9c028

14 files changed

Lines changed: 414 additions & 36 deletions

File tree

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- name: Build doxygen
2626
run: |
2727
doxygen docs/doxygen.config
28-
(cd docs/latex; make; ls; mv refman.pdf SimpleFastOpenAtomicVisualiser.pdf)
28+
(cd docs/latex; buf_size=1000000 make; ls; mv refman.pdf SimpleFastOpenAtomicVisualiser.pdf)
2929
3030
- name: Upload PDF
3131
uses: actions/upload-artifact@v4

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ include/vendored/VulkanSDK/Windows/Include
1414
include/vendored/VulkanSDK/Windows/lib
1515
docs/html
1616
docs/latex
17-
*.mp4
17+
*.mp4
18+
imgui.ini

DOCUMENTATION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Miscellaneous key bindings are:
8282
| :----- | :---- | :---- |
8383
| X | Toggle drawing the coordinate axes | |
8484
| C | Toggle drawing the simulation cell | |
85-
| I | Toggle information text | |
85+
| U | Toggle user interface windows | |
8686
| G | Screen grab | |
8787
| V | Start or finish a video recording | |
8888
| ESC | Quit | |

LICENSES.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,4 +545,30 @@ END OF TERMS AND CONDITIONS
545545
```
546546
public domain Simple, Minimalistic, No Allocations MPEG writer - http://jonolick.com
547547
Converted to C by Wladislav Artsimovich https://blog.frost.kiwi/jo-mpeg-in-c
548+
```
549+
550+
# Dear Imgui
551+
552+
```
553+
The MIT License (MIT)
554+
555+
Copyright (c) 2014-2025 Omar Cornut
556+
557+
Permission is hereby granted, free of charge, to any person obtaining a copy
558+
of this software and associated documentation files (the "Software"), to deal
559+
in the Software without restriction, including without limitation the rights
560+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
561+
copies of the Software, and to permit persons to whom the Software is
562+
furnished to do so, subject to the following conditions:
563+
564+
The above copyright notice and this permission notice shall be included in all
565+
copies or substantial portions of the Software.
566+
567+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
568+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
569+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
570+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
571+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
572+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
573+
SOFTWARE.
548574
```

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Miscellaneous key bindings are:
7878
| :----- | :---- | :---- |
7979
| X | Toggle drawing the coordinate axes | |
8080
| C | Toggle drawing the simulation cell | |
81-
| I | Toggle information text | |
81+
| U | Toggle user interface windows | |
8282
| G | Screen grab | |
8383
| V | Start or finish a video recording | |
8484
| ESC | Quit | |

include/cameraWindow.h

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
#ifndef CAMERAWINDOW_H
2+
#define CAMERAWINDOW_H
3+
4+
#include <imgui/imgui.h>
5+
#include <imgui/imgui_impl_glfw.h>
6+
#include <imgui/imgui_impl_opengl3.h>
7+
8+
#ifdef WINDOWS
9+
#include <imgui/imgui_impl_win32.h>
10+
#endif
11+
12+
#ifdef MACOS
13+
#include <imgui/imgui_impl_osx.h>
14+
#endif
15+
16+
#include <camera.h>
17+
#include <commandLine.h>
18+
#include <atom.h>
19+
#include <helpMarker.h>
20+
21+
/**
22+
* @brief The camera controls window.
23+
*
24+
*/
25+
class CameraWindow
26+
{
27+
public:
28+
29+
/**
30+
* @brief If the Camera or Atoms require updates.
31+
*
32+
*/
33+
struct CameraUpdates
34+
{
35+
CameraUpdates()
36+
: cameraMoved(false),
37+
atomsMoved(false)
38+
{}
39+
40+
bool cameraMoved;
41+
bool atomsMoved;
42+
};
43+
44+
CameraWindow() {}
45+
46+
/**
47+
* @brief Draw the window with Imgui
48+
*
49+
* @param options the current options.
50+
*
51+
* @remark Actions in the UI are queued for later application.
52+
* @see CameraWindow::applyQueueActions.
53+
*/
54+
void draw
55+
(
56+
CommandLine & options
57+
)
58+
{
59+
ImGui::Begin("Camera");
60+
ImGui::Text("Zoom ");
61+
ImGui::SameLine();
62+
63+
ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true);
64+
if (ImGui::ArrowButton("##zoomin", ImGuiDir_Up)) { zoomQueue--; }
65+
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
66+
if (ImGui::ArrowButton("##zoomout", ImGuiDir_Down)) { zoomQueue++; }
67+
ImGui::PopItemFlag();
68+
ImGui::SameLine(); HelpMarker("Zoom to and from the focus (W/S)");
69+
70+
ImGui::Text("Rotate ");
71+
ImGui::SameLine();
72+
73+
ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true);
74+
if (ImGui::ArrowButton("##rotatel", ImGuiDir_Left)) { rotateQueue--; }
75+
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
76+
if (ImGui::ArrowButton("##rotater", ImGuiDir_Right)) { rotateQueue++; }
77+
ImGui::PopItemFlag();
78+
ImGui::SameLine(); HelpMarker("Rotate around the focus (A/D)");
79+
80+
ImGui::Text("Incline ");
81+
ImGui::SameLine();
82+
83+
ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true);
84+
if (ImGui::ArrowButton("##inclineu", ImGuiDir_Up)) { inclineQueue--; }
85+
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
86+
if (ImGui::ArrowButton("##inclined", ImGuiDir_Down)) { inclineQueue++; }
87+
ImGui::PopItemFlag();
88+
ImGui::SameLine(); HelpMarker("Incline around the focus (Q/E)");
89+
90+
ImGui::Text("Pan x ");
91+
ImGui::SameLine();
92+
93+
ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true);
94+
if (ImGui::ArrowButton("##panx-", ImGuiDir_Left)) { panxQueue--; }
95+
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
96+
if (ImGui::ArrowButton("##panx+", ImGuiDir_Right)) { panxQueue++; }
97+
ImGui::PopItemFlag();
98+
ImGui::SameLine(); HelpMarker("Pan in x (Left/Right)");
99+
100+
ImGui::Text("Pan y ");
101+
ImGui::SameLine();
102+
103+
ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true);
104+
if (ImGui::ArrowButton("##pany-", ImGuiDir_Left)) { panyQueue--; }
105+
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
106+
if (ImGui::ArrowButton("##pany+", ImGuiDir_Right)) { panyQueue++; }
107+
ImGui::PopItemFlag();
108+
ImGui::SameLine(); HelpMarker("Pan in y (Up/Down)");
109+
110+
ImGui::Text("Pan z ");
111+
ImGui::SameLine();
112+
113+
ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true);
114+
if (ImGui::ArrowButton("##panz-", ImGuiDir_Left)) { panzQueue--; }
115+
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
116+
if (ImGui::ArrowButton("##panz+", ImGuiDir_Right)) { panzQueue++; }
117+
ImGui::PopItemFlag();
118+
ImGui::SameLine(); HelpMarker("Pan in z (.//)");
119+
120+
ImGui::PushItemWidth(200);
121+
ImGui::InputFloat("Zoom speed: ", &options.cameraZoomSpeed.value, 0.01f, 1.0f, "%.2f");
122+
ImGui::SameLine(); HelpMarker("Modify zoom rate (CTRL-CLICK for faster steps)");
123+
124+
ImGui::PushItemWidth(200);
125+
ImGui::InputFloat("Rotate speed: ", &options.cameraRotateSpeed.value, 0.01f, 1.0f, "%.2f");
126+
ImGui::SameLine(); HelpMarker("Modify rotate rate (CTRL-CLICK for faster steps)");
127+
128+
ImGui::PushItemWidth(200);
129+
ImGui::InputFloat("Incline speed: ", &options.cameraInclineSpeed.value, 0.01f, 1.0f, "%.2f");
130+
ImGui::SameLine(); HelpMarker("Modify inclination rate (CTRL-CLICK for faster steps)");
131+
132+
ImGui::PushItemWidth(200);
133+
ImGui::InputFloat("Pan speed: ", &options.cameraPanSpeed.value, 0.01f, 1.0f, "%.2f");
134+
ImGui::SameLine(); HelpMarker("Modify pan rate (CTRL-CLICK for faster steps)");
135+
136+
if (ImGui::Button("Reset Camera "))
137+
{
138+
resetCamera = true;
139+
}
140+
141+
ImGui::End();
142+
}
143+
144+
/**
145+
* @brief Apply queued actions from the UI.
146+
*
147+
* @param camera the Camera to update.
148+
* @param atoms the Atoms to update.
149+
* @param options the options to use for actions.
150+
* @param dr the length unit.
151+
* @param dtheta the rotation unit.
152+
* @param dphi the incline unit.
153+
* @return CameraUpdates Whether the Camera or Atoms were updated.
154+
*/
155+
CameraUpdates applyQueueActions
156+
(
157+
Camera & camera,
158+
std::vector<Atom> & atoms,
159+
const CommandLine & options,
160+
const float & dr,
161+
const float & dtheta,
162+
const float & dphi
163+
)
164+
{
165+
CameraUpdates moved;
166+
167+
if (zoomQueue != 0)
168+
{
169+
camera.zoom(dr*options.cameraZoomSpeed.value*zoomQueue);
170+
zoomQueue = 0;
171+
moved.cameraMoved = true;
172+
}
173+
174+
if (rotateQueue != 0)
175+
{
176+
camera.rotate(dtheta*options.cameraRotateSpeed.value*rotateQueue);
177+
rotateQueue = 0;
178+
moved.cameraMoved = true;
179+
}
180+
181+
if (inclineQueue != 0)
182+
{
183+
camera.incline(dphi*options.cameraInclineSpeed.value*inclineQueue);
184+
inclineQueue = 0;
185+
moved.cameraMoved = true;
186+
}
187+
188+
if (resetCamera)
189+
{
190+
if (!options.noCentering.value) { center(atoms); }
191+
if (options.focus.value < atoms.size()) { centerOn(atoms, options.focus.value); }
192+
camera.reset(atoms);
193+
moved.atomsMoved = true;
194+
moved.cameraMoved = true;
195+
resetCamera = false;
196+
}
197+
198+
if (panxQueue != 0)
199+
{
200+
translate(atoms, {dr*options.cameraPanSpeed.value*panxQueue, 0.0, 0.0});
201+
panxQueue = 0;
202+
moved.atomsMoved = true;
203+
}
204+
205+
if (panyQueue != 0)
206+
{
207+
translate(atoms, {0.0, dr*options.cameraPanSpeed.value*panyQueue, 0.0});
208+
panyQueue = 0;
209+
moved.atomsMoved = true;
210+
}
211+
212+
if (panzQueue != 0)
213+
{
214+
translate(atoms, {0.0, 0.0, dr*options.cameraPanSpeed.value*panzQueue});
215+
panzQueue = 0;
216+
moved.atomsMoved = true;
217+
}
218+
219+
return moved;
220+
}
221+
222+
private:
223+
224+
inline static int zoomQueue = 0;
225+
inline static int rotateQueue = 0;
226+
inline static int inclineQueue = 0;
227+
inline static int panxQueue = 0;
228+
inline static int panyQueue = 0;
229+
inline static int panzQueue = 0;
230+
inline static bool resetCamera = false;
231+
232+
};
233+
234+
#endif /* CAMERAWINDOW_H */

include/commandLine.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ struct CommandLine
289289
extractFlag(hideAtoms, flags);
290290
extractFlag(showAxes, flags);
291291
extractFlag(showCell, flags);
292-
extractFlag(hideInfoText, flags);
292+
extractFlag(hideUI, flags);
293293
extractFlag(play, flags);
294294
extractFlag(meshes, flags);
295295
extractFlag(darkTheme, flags);
@@ -353,7 +353,7 @@ struct CommandLine
353353
Argument<std::filesystem::path> colourmap = {"colourmap", "The colourmap path.", "", {}};
354354
Argument<std::filesystem::path> atomColours = {"atomColours", "Path for per-atom colour overrides.", "", {}};
355355
Argument<std::string> videoName = {"videoName", "Name of saved video.", "", ""};
356-
Argument<vec<2>> resolution = {"resolution", "Window resolution in pixels.", "", {512, 512}};
356+
Argument<vec<2>> resolution = {"resolution", "Window resolution in pixels.", "", {800, 800}};
357357
Argument<uint64_t> bondFocus = {"bondFocus", "Only draw bonds for this atom.", "", NULL_INDEX};
358358
Argument<uint64_t> focus = {"focus", "Centre on a particular atom.", "", NULL_INDEX};
359359
Argument<float> cameraZoomSpeed = {"cameraZoomSpeed", "Speed of the camera's zoom.", "", 1.0};
@@ -376,7 +376,7 @@ struct CommandLine
376376
Argument<bool> hideAtoms = {"hideAtoms", "Hide atoms.", "Toggleable at runtime.", false};
377377
Argument<bool> showAxes = {"showAxes", "Show the coordinate axes.", "Toggleable at runtime.", false};
378378
Argument<bool> showCell = {"showCell", "Show the simulation cell.", "Toggleable at runtime.", false};
379-
Argument<bool> hideInfoText = {"hideInfoText", "Hide information and statistics text.", "Toggleable at runtime.", false};
379+
Argument<bool> hideUI = {"hideUI", "Hide information and statistics text.", "Toggleable at runtime.", false};
380380
Argument<bool> play = {"play", "Play trajectory.", "Toggleable at runtime.", false};
381381
Argument<bool> noCentering = {"noCentering", "Do not centre the atoms", "Toggleable at runtime.", false};
382382
Argument<bool> darkTheme = {"darkTheme", "Use dark theme", "Toggleable at runtime.", false};
@@ -629,7 +629,7 @@ struct CommandLine
629629
<< "\n"
630630
<< sidebyside(argumentHelp(noCentering), argumentHelp(noTransparencySorting), 42)
631631
<< "\n"
632-
<< sidebyside(argumentHelp(levelOfDetail), argumentHelp(hideInfoText), 42)
632+
<< sidebyside(argumentHelp(levelOfDetail), argumentHelp(hideUI), 42)
633633
<< "\n"
634634
<< sidebyside(argumentHelp(videoName), argumentHelp(fieldOfView), 42)
635635
<< "\n"
@@ -759,6 +759,10 @@ jo_mpeg
759759
Public domain.
760760
Jon Olick.
761761
762+
Dear Imgui
763+
MIT.
764+
Omar Cornut.
765+
762766
With thanks, Jerboa.
763767
)";
764768

@@ -935,7 +939,7 @@ END OF TERMS AND CONDITIONS)";
935939
{hideAtoms.name, hideAtoms},
936940
{showAxes.name, showAxes},
937941
{showCell.name, showCell},
938-
{hideInfoText.name, hideInfoText},
942+
{hideUI.name, hideUI},
939943
{play.name, play},
940944
{noCentering.name, noCentering},
941945
{darkTheme.name, darkTheme},

include/font.h

Lines changed: 4 additions & 0 deletions
Large diffs are not rendered by default.

include/helpMarker.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#ifndef HELPMARKER_H
2+
#define HELPMARKER_H
3+
4+
#include <imgui/imgui.h>
5+
#include <imgui/imgui_impl_glfw.h>
6+
#include <imgui/imgui_impl_opengl3.h>
7+
8+
#ifdef WINDOWS
9+
#include <imgui/imgui_impl_win32.h>
10+
#endif
11+
12+
#ifdef MACOS
13+
#include <imgui/imgui_impl_osx.h>
14+
#endif
15+
16+
/**
17+
* @brief Draw a help marker (?) in Imgui UIs
18+
*
19+
* @param desc the help message.
20+
*/
21+
static void HelpMarker(const char* desc)
22+
{
23+
ImGui::TextDisabled("(?)");
24+
if (ImGui::BeginItemTooltip())
25+
{
26+
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
27+
ImGui::TextUnformatted(desc);
28+
ImGui::PopTextWrapPos();
29+
ImGui::EndTooltip();
30+
}
31+
}
32+
33+
#endif /* HELPMARKER_H */

0 commit comments

Comments
 (0)