Add graphical error messages

Error and warning messages now show up as dialog boxes using Boxer.
Additional dependencies:
- fmt (for string formatting)
- Boxer (static)
This commit is contained in:
Epicalert 2021-02-14 23:47:07 +08:00
parent e56009c125
commit 3773532816
No known key found for this signature in database
GPG key ID: CAA46F858D0979BD
7 changed files with 59 additions and 18 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "libs/Boxer"]
path = libs/Boxer
url = https://github.com/aaronmjacobs/Boxer.git

View file

@ -1,7 +1,9 @@
cmake_minimum_required( VERSION 3.0 ) cmake_minimum_required( VERSION 3.0 )
project( Facecam2D VERSION 0.1.0 ) project( Facecam2D VERSION 0.1.0 )
set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ) set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake )
add_subdirectory( "libs/Boxer" )
find_package( libzip REQUIRED ) find_package( libzip REQUIRED )
find_package( fmt REQUIRED )
find_package( WebP REQUIRED ) find_package( WebP REQUIRED )
find_package( OpenCV REQUIRED ) find_package( OpenCV REQUIRED )
message (STATUS "Found OpenCV at: " ${OpenCV_INCLUDE_DIRS} ) message (STATUS "Found OpenCV at: " ${OpenCV_INCLUDE_DIRS} )
@ -44,5 +46,7 @@ add_executable( fc2d
src/model.cpp src/model.cpp
src/toml.c src/toml.c
src/tomlcpp.cpp src/tomlcpp.cpp
src/error.cpp
) )
target_link_libraries( fc2d ${OpenCV_LIBS} ${OPENGL_LIBRARIES} ${WEBP_LIBRARIES} FreeGLUT::freeglut GLEW::glew zip ) target_link_libraries( fc2d ${OpenCV_LIBS} ${OPENGL_LIBRARIES} ${WEBP_LIBRARIES}
FreeGLUT::freeglut GLEW::glew zip Boxer fmt )

1
libs/Boxer Submodule

@ -0,0 +1 @@
Subproject commit 01c17f6a9cd66068f7890ea887ab3b9a673f0434

25
src/error.cpp Normal file
View file

@ -0,0 +1,25 @@
#include <iostream>
#ifndef NO_GRAPHICAL_DIALOG
#include <boxer/boxer.h>
#endif
void showError(std::string message, std::string titleMessage, bool fatal = true) {
#ifndef NO_GRAPHICAL_DIALOG
boxer::show(message.c_str(), titleMessage.c_str(), boxer::Style::Error);
#endif
std::cerr << "ERROR: " << message << std::endl;
if (fatal) {
std::abort();
}
}
void showWarning(std::string message, std::string titleMessage) {
#ifndef NO_GRAPHICAL_DIALOG
boxer::show(message.c_str(), titleMessage.c_str(), boxer::Style::Warning);
#endif
std::cerr << "WARN: " << message << std::endl;
}

7
src/error.hpp Normal file
View file

@ -0,0 +1,7 @@
#ifndef ERROR_HPP
#define ERROR_HPP
void showError(std::string message, std::string titleMessage, bool fatal = true);
void showWarning(std::string message, std::string titleMessage);
#endif

View file

@ -115,7 +115,7 @@ void initTexture (GLuint* texNum, unsigned char* buffer, size_t bufferLength) {
//try stb_image (png, jpg, gif, etc) //try stb_image (png, jpg, gif, etc)
pixels = stbi_load_from_memory(buffer, bufferLength, &x, &y, &channels, 4); pixels = stbi_load_from_memory(buffer, bufferLength, &x, &y, &channels, 4);
if (!pixels) { if (!pixels) {
std::cerr << "Corrupt or unsupported texture format!" << std::endl; showError("Corrupt or unsupported texture format!", "Could not load texture", false);
GLubyte defaultPixels[] = GLubyte defaultPixels[] =
{255, 0, 255, 255, 0, 0, 0, 255, {255, 0, 255, 255, 0, 0, 0, 255,

View file

@ -1,9 +1,11 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <zip.h> #include <zip.h>
#include <fmt/core.h>
#include <tomlcpp.hpp> //dynamically link tomlcpp if it becomes common in repositories #include <tomlcpp.hpp> //dynamically link tomlcpp if it becomes common in repositories
#include <model.hpp> #include <model.hpp>
#include <config.hpp> #include <config.hpp>
#include <error.hpp>
#define BUFFER_SIZE_MODEL_DESC 8192 // 8 KiB #define BUFFER_SIZE_MODEL_DESC 8192 // 8 KiB
#define BUFFER_SIZE_TEXTURE 16777220 // 16 MiB #define BUFFER_SIZE_TEXTURE 16777220 // 16 MiB
@ -21,7 +23,7 @@ void textureFromArchive(zip_t* archive, const char* path, ModelPart* part, size_
delete [] textureBuffer; delete [] textureBuffer;
} else { } else {
std::cerr << path << " does not exist in archive!" << std::endl; showError(fmt::format("Texture file \"{}\" does not exist in archive!", path), "Could not open model");
} }
} }
@ -30,7 +32,7 @@ Model::Model(const char* path) {
zip_t* archive = zip_open(path, ZIP_RDONLY, &zipError); zip_t* archive = zip_open(path, ZIP_RDONLY, &zipError);
if (!archive) { if (!archive) {
std::cerr << "Model file " << path << " does not exist!" << std::endl; showError(fmt::format("Model file {} does not exist or is corrupt!", path), "Could not open model");
return; return;
} }
@ -43,13 +45,13 @@ Model::Model(const char* path) {
// parse model.toml // parse model.toml
auto modelDesc = toml::parse(std::string(modelDescBuffer)); auto modelDesc = toml::parse(std::string(modelDescBuffer));
if (!modelDesc.table) { if (!modelDesc.table) {
std::cerr << "cannot parse model.toml! " << std::endl << modelDesc.errmsg << std::endl; showError("Cannot parse model.toml:\n" + modelDesc.errmsg, "Could not open model");
} }
// get format table // get format table
auto format = modelDesc.table->getTable("format"); auto format = modelDesc.table->getTable("format");
if (!format) { if (!format) {
std::cerr << "Model does not have a format table!" << std::endl; showError("Model does not have a format table!", "Could not open model");
} else { } else {
// get format version // get format version
auto formatMajResult = format->getInt("version_major"); auto formatMajResult = format->getInt("version_major");
@ -60,14 +62,14 @@ Model::Model(const char* path) {
if (formatMajResult.second != SUPPORTED_MODEL_MAJOR || if (formatMajResult.second != SUPPORTED_MODEL_MAJOR ||
formatMinResult.second > SUPPORTED_MODEL_MINOR ) { formatMinResult.second > SUPPORTED_MODEL_MINOR ) {
std::cerr << "Model format version " << showError(fmt::format("Model format version {0}.{1} is unsupported! This version of {2} supports model file version"
formatMajResult.second << "." << formatMinResult.second << " {3}.0 to version {3}.{4}.",
" is unsupported! This version of " << PROJECT_NAME << " supports model file version " << formatMajResult.second, formatMinResult.second,
SUPPORTED_MODEL_MAJOR << ".0 to version " << PROJECT_NAME,
SUPPORTED_MODEL_MAJOR << "." << SUPPORTED_MODEL_MINOR << std::endl; SUPPORTED_MODEL_MAJOR, SUPPORTED_MODEL_MINOR), "Could not open model");
} }
} else { } else {
std::cerr << "Model does not define a format version!" << std::endl; showError("Model does not define a format version!", "Could not open model");
} }
} }
@ -76,14 +78,14 @@ Model::Model(const char* path) {
auto modelInfo = modelDesc.table->getTable("model_info"); auto modelInfo = modelDesc.table->getTable("model_info");
if (!modelInfo) { if (!modelInfo) {
std::cerr << "Model does not have a model_info table!" << std::endl; showError("Model does not have a model_info table!", "Could not open model");
} else { } else {
// get name // get name
auto nameResult = modelInfo->getString("name"); auto nameResult = modelInfo->getString("name");
if (!nameResult.first) { if (!nameResult.first) {
std::cerr << "Model does not have a name!" << std::endl; showWarning("Model does not have a name!", "Model warning");
} else { } else {
name = nameResult.second; name = nameResult.second;
} }
@ -99,9 +101,7 @@ Model::Model(const char* path) {
// position // position
auto bindResult = partsVec[i].getString("bind"); auto bindResult = partsVec[i].getString("bind");
if (!bindResult.first) { if (bindResult.first) {
std::cerr << "Part " << i << " does not define a bind!" << std::endl;
} else {
newPart.setBind(bindResult.second); newPart.setBind(bindResult.second);
} }
@ -140,7 +140,8 @@ Model::Model(const char* path) {
auto textureVec = *textureArray->getTableVector().get(); auto textureVec = *textureArray->getTableVector().get();
if (textureVec.size() < 1) { if (textureVec.size() < 1) {
std::cerr << "Part " << i << " does not define any textures!" << std::endl; showWarning(fmt::format("Part {} does not define any textures! Parts with no textures defined will"
" show a default \"missing texture\" pattern.", i), "Model warning");
} else { } else {
// a list of textures with triggers were defined // a list of textures with triggers were defined
for (int j = 0; j < textureVec.size(); j++) { for (int j = 0; j < textureVec.size(); j++) {