A framework for making snappy, interactive, touch-friendly user interfaces with OpenGL 3+.
- This template is a work in progress, and features may be added or changed any time.
- Example apps and utilities that depend on OpenCV are available and maintained in the with-opencv branch. In the
master
branch, CMake is configured to search for OpenCV, but that library isn't used beyond configuration.
Copy and paste this code to get started. libopencv-dev
is only required in the with-opencv
branch
# Install dependencies
sudo apt-get update
sudo apt-get install -y build-essential git make cmake libopencv-dev xorg-dev
# Clone the repository (with libraries)
git clone https://github.com/m516/Cpp-UI-Template.git --recursive
# Building
cd Cpp-UI-Template
cmake .
make -j$(nproc)
The binary is in the src/ folder for some reason. I'll have to check that out 🤔
I use this project as a template to quickly build and visualize interactive, multithreaded computer vision applications with OpenCV, and you can too. Every class can be an App::App
, a Pipeline::Process
, or both.
Apps (App::App
)
Apps are instances of classes that inherit app::App
to create new tabs in the UI. All the low-level graphics are handled in the UI namespace, so we can just focus on creating and using ImGui widgets.
Making an App is easy. Create a new folder in src/apps
with the name of the app. Inside the folder make a new header. Name it something uselessly nebulous like "app.hpp"
Include important things:
#pragma once
#include "ui/app.hpp" // For the app template
#include <imgui/imgui.h> // For making widgets
There a special namespace "apps" for all your apps. Make the class there so you don't mess up anyone else's code. Inherit the app::App
for access to the UI.
namespace Apps{
class ImGui_Demo: public app::App{
public:
Apps can inherit three methods:
void uiInit()
, run once as soon as the app is initializedvoid uiDraw()
, run repeatedly every frame.void uiClose()
, run once when the app is closing.
Let's make a window with a button:
virtual void uiDraw(){
ImGui::Begin("The Do-Nothing Button");
ImGui::Button("Press me");
ImGui::End();
}
Note that ImGui documentation can be found in its demo
That's it! Now create the app in main/main.cpp
and run the UI:
int main()
{
Apps::ImGui_Demo imgui_demo;
imgui_demo.uiInit();
UI::init();
while(UI::Window::window) UI::update();
return 0;
}
Important: Make sure all UI's are initialized BEFORE running UI::init()
. I get that this process is extremely clunky, and I'll try to fix it soon.
Also, if you make any implementation (.cpp) files for your apps, make sure those are included in src/CMakeLists.txt. (I know, this is also super inconvenient. I won't make any promises, but there might be an update that makes this step unnecessary.)
#pragma once
#include "ui/app.hpp"
#include <imgui/imgui.h>
namespace Apps{
class ImGui_Demo: public app::App{
public:
virtual void uiDraw(){
ImGui::ShowDemoWindow(NULL);
}
}; // End class ImGui_Demo
} // End namespace Apps
Process (Pipeline::Process
)
Extending Pipeline::Process
allows a class to take any data from another Process, do something with the data when new data arrives, concurrently while the previous process is getting more data, and makes it available for other Processes. For example, a Webcam can be a Process and grab image frames as quickly as possible. As soon as a frame is received, it can be passed to a Thresholding module that begins processing the data almost immediately.
There are three parts to a process:
- Constructing the process. The constructor of a Process only has one input: the Process where data is coming from. The input and output data types are template parameters, so you get to choose what comes in and goes out. (i.e., Process is defined as:
template<typename InType, typename OutType> class Process
) virtual void processOnce()
: override this to process the data one time. Data comes fom*process_in
, a pointer of the input type. Make sure to put the results of your computation inprocess_out
.startProcessingContinuallyInNewThread()
: Call this somewhere to spawn a new thread that runsprocessOnce()
only when there is new data inprocess_in
.
Processes can also be combined with Apps to make blazing fast UIs! Webcam
and Threshold
are both Processes and Apps. They can render data as an App in real time while simultaneously getting more data as a Process. To try them out, check out and build the project in the with-opencv
branch and build the project.
Note: More extensive documentation is underway, but the existing apps can be used for reference.
My work is under the MIT License with libraries whose licenses are as follows:
Name | Installation instructions | License | Github Repository |
---|---|---|---|
OpenCV | official instructions as of 7/13/2020 (volatile) | 3-clause BSD License | yes |
GLAD | Included in project (Unofficial instructions) (path to KHR library modified) | Varies | Generator |
GLFW | Included in project (Official instructions) | zlib license | yes |
ImGui | Included in project (static library) | MIT License | yes |