Compare commits
10 commits
243af95a3b
...
801b00ad97
Author | SHA1 | Date | |
---|---|---|---|
801b00ad97 | |||
4940b07403 | |||
2f09c6eb9c | |||
3521f50d1b | |||
11df6595c0 | |||
44c28b6825 | |||
92ab9f6fb9 | |||
b117f3cd4d | |||
d086cf629b | |||
143d3769c7 |
31 changed files with 6320 additions and 35 deletions
|
@ -25,4 +25,6 @@ add_subdirectory(client)
|
||||||
add_subdirectory(editor)
|
add_subdirectory(editor)
|
||||||
|
|
||||||
|
|
||||||
install(FILES $<TARGET_RUNTIME_DLLS:editor> TYPE BIN)
|
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests )
|
||||||
|
enable_testing()
|
||||||
|
add_subdirectory(tests)
|
||||||
|
|
|
@ -43,6 +43,8 @@ int processHeader(fs::path srcRoot, fs::path srcPath, fs::path outPath) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fs::create_directories(outPath.parent_path()); // Make sure generated dir exists before we try writing to it
|
||||||
|
|
||||||
// We write to a special log file instead of stdout/stderr to
|
// We write to a special log file instead of stdout/stderr to
|
||||||
// 1. avoid confusion
|
// 1. avoid confusion
|
||||||
// 2. prevent MSBuild from reading the word "error" and detecting there's a problem with the program (there isn't)
|
// 2. prevent MSBuild from reading the word "error" and detecting there's a problem with the program (there isn't)
|
||||||
|
@ -74,8 +76,6 @@ int processHeader(fs::path srcRoot, fs::path srcPath, fs::path outPath) {
|
||||||
data::analyzeClasses(cursor, srcRootStr, &dataAnlyState);
|
data::analyzeClasses(cursor, srcRootStr, &dataAnlyState);
|
||||||
enum_::analyzeClasses(cursor, srcRootStr, &enumAnlyState);
|
enum_::analyzeClasses(cursor, srcRootStr, &enumAnlyState);
|
||||||
|
|
||||||
fs::create_directories(outPath.parent_path()); // Make sure generated dir exists before we try writing to it
|
|
||||||
|
|
||||||
printf("[AUTOGEN] Generating file %s...\n", relpathStr.c_str());
|
printf("[AUTOGEN] Generating file %s...\n", relpathStr.c_str());
|
||||||
std::ofstream outStream(outPathStr);
|
std::ofstream outStream(outPathStr);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include "logger.h"
|
||||||
#include "objects/part/part.h"
|
#include "objects/part/part.h"
|
||||||
|
#include "panic.h"
|
||||||
#include "rendering/renderer.h"
|
#include "rendering/renderer.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
@ -37,7 +39,13 @@ int main() {
|
||||||
glfwSetFramebufferSizeCallback(window, resizeCallback);
|
glfwSetFramebufferSizeCallback(window, resizeCallback);
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
glewInit();
|
int version = gladLoadGL(glfwGetProcAddress);
|
||||||
|
if (version == 0) {
|
||||||
|
Logger::fatalError("Failed to initialize OpenGL context");
|
||||||
|
panic();
|
||||||
|
} else {
|
||||||
|
Logger::debugf("Initialized GL context version %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version));
|
||||||
|
}
|
||||||
|
|
||||||
gDataModel->Init();
|
gDataModel->Init();
|
||||||
renderInit(1200, 900);
|
renderInit(1200, 900);
|
||||||
|
@ -83,7 +91,7 @@ int main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void errorCatcher(int id, const char* str) {
|
void errorCatcher(int id, const char* str) {
|
||||||
Logger::fatalErrorf("GLFW Error: [{}] {}", id, str);
|
Logger::fatalErrorf("GLFW Error: [%d] %s", id, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
float lastTime;
|
float lastTime;
|
||||||
|
|
|
@ -3,6 +3,8 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/deps.cmake)
|
||||||
## Sources
|
## Sources
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
src/stb.cpp
|
src/stb.cpp
|
||||||
|
src/glad.cpp
|
||||||
|
|
||||||
src/ptr_helpers.h
|
src/ptr_helpers.h
|
||||||
src/enum/part.h
|
src/enum/part.h
|
||||||
src/enum/surface.cpp
|
src/enum/surface.cpp
|
||||||
|
@ -195,8 +197,8 @@ list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp)
|
||||||
add_library(openblocks STATIC ${SOURCES})
|
add_library(openblocks STATIC ${SOURCES})
|
||||||
set_target_properties(openblocks PROPERTIES OUTPUT_NAME "openblocks")
|
set_target_properties(openblocks PROPERTIES OUTPUT_NAME "openblocks")
|
||||||
target_link_directories(openblocks PUBLIC ${LUAJIT_LIBRARY_DIRS})
|
target_link_directories(openblocks PUBLIC ${LUAJIT_LIBRARY_DIRS})
|
||||||
target_link_libraries(openblocks libglew_static reactphysics3d pugixml::pugixml Freetype::Freetype glm::glm libluajit ${LuaJIT_LIBRARIES})
|
target_link_libraries(openblocks reactphysics3d pugixml::pugixml Freetype::Freetype glm::glm libluajit ${LuaJIT_LIBRARIES})
|
||||||
target_include_directories(openblocks PUBLIC "src" "../include" ${ReactPhysics3D_SOURCE_DIR}/include ${LUAJIT_INCLUDE_DIRS} ${stb_SOURCE_DIR} ${glew_SOURCE_DIR}/include)
|
target_include_directories(openblocks PUBLIC "src" "../include" "${CMAKE_SOURCE_DIR}/external/glad" ${ReactPhysics3D_SOURCE_DIR}/include ${LUAJIT_INCLUDE_DIRS} ${stb_SOURCE_DIR})
|
||||||
add_dependencies(openblocks autogen_build autogen)
|
add_dependencies(openblocks autogen_build autogen)
|
||||||
|
|
||||||
# Windows-specific dependencies
|
# Windows-specific dependencies
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
|
||||||
include(CPM)
|
include(CPM)
|
||||||
|
|
||||||
CPMAddPackage("gh:Perlmint/glew-cmake#glew-cmake-2.2.0")
|
# Some packages will build helper binaries. This keeps them out of our own build output
|
||||||
|
set (PREV_BIN_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||||
|
unset (CMAKE_RUNTIME_OUTPUT_DIRECTORY)
|
||||||
|
|
||||||
CPMAddPackage("gh:g-truc/glm#1.0.1")
|
CPMAddPackage("gh:g-truc/glm#1.0.1")
|
||||||
CPMAddPackage(NAME reactphysics3d GITHUB_REPOSITORY "DanielChappuis/reactphysics3d" VERSION 0.10.2 PATCHES ${CMAKE_SOURCE_DIR}/patches/std_chrono.patch)
|
CPMAddPackage(NAME reactphysics3d GITHUB_REPOSITORY "DanielChappuis/reactphysics3d" VERSION 0.10.2 PATCHES ${CMAKE_SOURCE_DIR}/patches/std_chrono.patch)
|
||||||
# https://github.com/StereoKit/StereoKit/blob/0be056efebcee5e58ad1438f4cf6dfdb942f6cf9/CMakeLists.txt#L205
|
# https://github.com/StereoKit/StereoKit/blob/0be056efebcee5e58ad1438f4cf6dfdb942f6cf9/CMakeLists.txt#L205
|
||||||
|
@ -13,6 +16,7 @@ CPMAddPackage(
|
||||||
GIT_REPOSITORY https://github.com/aseprite/freetype2.git
|
GIT_REPOSITORY https://github.com/aseprite/freetype2.git
|
||||||
GIT_TAG VER-2-10-0
|
GIT_TAG VER-2-10-0
|
||||||
VERSION 2.10.0
|
VERSION 2.10.0
|
||||||
|
PATCHES ${CMAKE_SOURCE_DIR}/patches/freetype_cmakever.patch
|
||||||
)
|
)
|
||||||
|
|
||||||
if (freetype_ADDED)
|
if (freetype_ADDED)
|
||||||
|
@ -21,4 +25,6 @@ endif()
|
||||||
|
|
||||||
CPMAddPackage("gh:nothings/stb#8cfb1605c02aee9fb6eb5d8ea559017745bd9a16") # 2.14
|
CPMAddPackage("gh:nothings/stb#8cfb1605c02aee9fb6eb5d8ea559017745bd9a16") # 2.14
|
||||||
CPMAddPackage("gh:WohlSoft/LuaJIT#a5da8f4a31972b74254f00969111b8b7a07cf584") # v2.1
|
CPMAddPackage("gh:WohlSoft/LuaJIT#a5da8f4a31972b74254f00969111b8b7a07cf584") # v2.1
|
||||||
set(LUAJIT_INCLUDE_DIRS ${LuaJIT_SOURCE_DIR}/src)
|
set(LUAJIT_INCLUDE_DIRS ${LuaJIT_SOURCE_DIR}/src)
|
||||||
|
|
||||||
|
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PREV_BIN_PATH})
|
2
core/src/glad.cpp
Normal file
2
core/src/glad.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define GLAD_GL_IMPLEMENTATION
|
||||||
|
#include <glad/gl.h>
|
|
@ -58,7 +58,7 @@ std::optional<HandleFace> raycastHandle(rp3d::Ray ray) {
|
||||||
// Implement manual detection via boxes instead of... this shit
|
// Implement manual detection via boxes instead of... this shit
|
||||||
// This code also hardly works, and is not good at all... Hooo nope.
|
// This code also hardly works, and is not good at all... Hooo nope.
|
||||||
rp3d::RigidBody* body = world->createRigidBody(CFrame::IDENTITY + cframe.Position());
|
rp3d::RigidBody* body = world->createRigidBody(CFrame::IDENTITY + cframe.Position());
|
||||||
body->addCollider(common.createBoxShape(cframe.Rotation() * Vector3(handleSize(face) / 2.f)), rp3d::Transform::identity());
|
body->addCollider(common.createBoxShape((cframe.Rotation() * Vector3(handleSize(face) / 2.f)).Abs()), rp3d::Transform::identity());
|
||||||
|
|
||||||
rp3d::RaycastInfo info;
|
rp3d::RaycastInfo info;
|
||||||
if (body->raycast(ray, info)) {
|
if (body->raycast(ray, info)) {
|
||||||
|
|
|
@ -10,18 +10,26 @@
|
||||||
static std::ofstream logStream;
|
static std::ofstream logStream;
|
||||||
static std::vector<Logger::LogListener> logListeners;
|
static std::vector<Logger::LogListener> logListeners;
|
||||||
std::string Logger::currentLogDir = "NULL";
|
std::string Logger::currentLogDir = "NULL";
|
||||||
|
static std::stringstream* rawOutputBuffer = nullptr;
|
||||||
|
|
||||||
void Logger::init() {
|
void Logger::init() {
|
||||||
initProgramLogsDir();
|
initProgramLogsDir();
|
||||||
|
|
||||||
const auto now = std::chrono::system_clock::now();
|
const auto now = std::chrono::system_clock::now();
|
||||||
|
const auto nows = std::chrono::floor<std::chrono::seconds>(now);
|
||||||
|
|
||||||
std::string fileName = std::format("log_{0:%Y%m%d}_{0:%H%M%S}.txt", now);
|
std::string fileName = std::format("log_{0:%Y%m%d}_{0:%H%M%S}.txt", nows);
|
||||||
|
|
||||||
logStream = std::ofstream(currentLogDir = (getProgramLogsDir() + "/" + fileName));
|
logStream = std::ofstream(currentLogDir = (getProgramLogsDir() + "/" + fileName));
|
||||||
Logger::debug("Logger initialized");
|
Logger::debug("Logger initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initializes the logger in a "void" mode for testing.
|
||||||
|
// It is not necessary to call Logger::finish
|
||||||
|
void Logger::initTest(std::stringstream* outputBuffer) {
|
||||||
|
rawOutputBuffer = outputBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
void Logger::finish() {
|
void Logger::finish() {
|
||||||
Logger::debug("Closing logger...");
|
Logger::debug("Closing logger...");
|
||||||
logStream.close();
|
logStream.close();
|
||||||
|
@ -41,6 +49,7 @@ void Logger::log(std::string message, Logger::LogLevel logLevel, ScriptSource so
|
||||||
|
|
||||||
logStream << formattedLogLine << std::endl;
|
logStream << formattedLogLine << std::endl;
|
||||||
printf("%s\n", formattedLogLine.c_str());
|
printf("%s\n", formattedLogLine.c_str());
|
||||||
|
if (rawOutputBuffer != nullptr) *rawOutputBuffer << logLevelStr << ": " << message << "\n";
|
||||||
|
|
||||||
for (Logger::LogListener listener : logListeners) {
|
for (Logger::LogListener listener : logListeners) {
|
||||||
listener(logLevel, message, source);
|
listener(logLevel, message, source);
|
||||||
|
@ -53,4 +62,8 @@ void Logger::log(std::string message, Logger::LogLevel logLevel, ScriptSource so
|
||||||
|
|
||||||
void Logger::addLogListener(Logger::LogListener listener) {
|
void Logger::addLogListener(Logger::LogListener listener) {
|
||||||
logListeners.push_back(listener);
|
logListeners.push_back(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::resetLogListeners() {
|
||||||
|
logListeners.clear();
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class Script;
|
class Script;
|
||||||
|
@ -26,8 +27,10 @@ namespace Logger {
|
||||||
extern std::string currentLogDir;
|
extern std::string currentLogDir;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
void initTest(std::stringstream* out); // Testing only!
|
||||||
void finish();
|
void finish();
|
||||||
void addLogListener(LogListener);
|
void addLogListener(LogListener);
|
||||||
|
void resetLogListeners(); // Testing only!
|
||||||
|
|
||||||
void log(std::string message, LogLevel logLevel, ScriptSource source = {});
|
void log(std::string message, LogLevel logLevel, ScriptSource source = {});
|
||||||
inline void info(std::string message) { log(message, LogLevel::INFO); }
|
inline void info(std::string message) { log(message, LogLevel::INFO); }
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#include "rendering/shader.h"
|
#include "rendering/shader.h"
|
||||||
#include "rendering/texture.h"
|
#include "rendering/texture.h"
|
||||||
#include "timeutil.h"
|
#include "timeutil.h"
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <glm/ext/vector_float4.hpp>
|
#include <glm/ext/vector_float4.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "rendering/shader.h"
|
#include "rendering/shader.h"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <glm/ext/matrix_clip_space.hpp>
|
#include <glm/ext/matrix_clip_space.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
|
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
|
|
||||||
#include "mesh2d.h"
|
#include "mesh2d.h"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
|
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "texture3d.h"
|
#include "texture3d.h"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
|
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "torus.h"
|
#include "torus.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
|
|
||||||
#define PI 3.1415926535f
|
#define PI 3.1415926535f
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,15 @@
|
||||||
|
|
||||||
tu_time_t TIME_STARTED_MICROS = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count();
|
tu_time_t TIME_STARTED_MICROS = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count();
|
||||||
|
|
||||||
|
static tu_time_t timeOverride = -1UL;
|
||||||
|
|
||||||
tu_time_t tu_clock_micros() {
|
tu_time_t tu_clock_micros() {
|
||||||
|
if (timeOverride != -1UL) return timeOverride;
|
||||||
tu_time_t now = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count();;
|
tu_time_t now = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count();;
|
||||||
|
|
||||||
return now - TIME_STARTED_MICROS;
|
return now - TIME_STARTED_MICROS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tu_set_override(tu_time_t destTime) {
|
||||||
|
timeOverride = destTime;
|
||||||
}
|
}
|
|
@ -5,4 +5,8 @@
|
||||||
typedef uint64_t tu_time_t;
|
typedef uint64_t tu_time_t;
|
||||||
|
|
||||||
// Provides a high-accuracy time since the program started in microseconds (via std::chrono)
|
// Provides a high-accuracy time since the program started in microseconds (via std::chrono)
|
||||||
tu_time_t tu_clock_micros();
|
tu_time_t tu_clock_micros();
|
||||||
|
|
||||||
|
#ifdef TU_TIME_EXPOSE_TEST
|
||||||
|
void tu_set_override(tu_time_t destTime);
|
||||||
|
#endif
|
2
deps.txt
2
deps.txt
|
@ -1,6 +1,6 @@
|
||||||
opengl (Linux: glvnd, Windows: [built-in/none])
|
opengl (Linux: glvnd, Windows: [built-in/none])
|
||||||
glfw
|
glfw
|
||||||
glew
|
glad
|
||||||
glm
|
glm
|
||||||
stb
|
stb
|
||||||
qt6
|
qt6
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include <GL/glew.h>
|
#include <glad/gl.h>
|
||||||
#include <glm/common.hpp>
|
#include <glm/common.hpp>
|
||||||
#include <glm/vector_relational.hpp>
|
#include <glm/vector_relational.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -35,7 +35,13 @@ MainGLWidget::MainGLWidget(QWidget* parent): QOpenGLWidget(parent), contextMenu(
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainGLWidget::initializeGL() {
|
void MainGLWidget::initializeGL() {
|
||||||
glewInit();
|
int version = gladLoaderLoadGL();
|
||||||
|
if (version == 0) {
|
||||||
|
Logger::fatalError("Failed to initialize OpenGL context");
|
||||||
|
panic();
|
||||||
|
} else {
|
||||||
|
Logger::debugf("Initialized GL context version %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version));
|
||||||
|
}
|
||||||
renderInit(width(), height());
|
renderInit(width(), height());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5914
external/glad/glad/gl.h
vendored
Normal file
5914
external/glad/glad/gl.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
14
patches/freetype_cmakever.patch
Normal file
14
patches/freetype_cmakever.patch
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index 28dc3b3f6..37fd14713 100644
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -85,7 +85,8 @@
|
||||||
|
# FreeType explicitly marks the API to be exported and relies on the compiler
|
||||||
|
# to hide all other symbols. CMake supports a C_VISBILITY_PRESET property
|
||||||
|
# starting with 2.8.12.
|
||||||
|
-cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
+# cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
+cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
if (NOT CMAKE_VERSION VERSION_LESS 3.3)
|
||||||
|
# Allow symbol visibility settings also on static libraries. CMake < 3.3
|
14
tests/CMakeLists.txt
Normal file
14
tests/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
function (create_test TEST_NAME)
|
||||||
|
set(TARGET_NAME test_${TEST_NAME})
|
||||||
|
add_executable(${TARGET_NAME} ${ARGN})
|
||||||
|
target_link_libraries(${TARGET_NAME} PRIVATE openblocks)
|
||||||
|
add_dependencies(${TARGET_NAME} openblocks)
|
||||||
|
add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME})
|
||||||
|
endfunction ()
|
||||||
|
|
||||||
|
create_test(lua src/luatest.cpp)
|
||||||
|
create_test(luasched src/luaschedtest.cpp)
|
||||||
|
create_test(luasignal src/luasignaltest.cpp)
|
||||||
|
|
||||||
|
# https://stackoverflow.com/a/36729074/16255372
|
||||||
|
add_custom_target(check ${CMAKE_CTEST_COMMAND} --output-on-failure WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
77
tests/src/luaschedtest.cpp
Normal file
77
tests/src/luaschedtest.cpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#include "testutillua.h"
|
||||||
|
|
||||||
|
#include "timeutil.h"
|
||||||
|
|
||||||
|
void test_wait1(DATAMODEL_REF m) {
|
||||||
|
auto ctx = m->GetService<ScriptContext>();
|
||||||
|
std::stringstream out;
|
||||||
|
Logger::initTest(&out);
|
||||||
|
|
||||||
|
tu_set_override(0);
|
||||||
|
luaEval(m, "wait(1) print('Wait')");
|
||||||
|
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("", out.str());
|
||||||
|
|
||||||
|
TT_ADVANCETIME(0.5);
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("", out.str());
|
||||||
|
|
||||||
|
TT_ADVANCETIME(0.5);
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("INFO: Wait\n", out.str());
|
||||||
|
|
||||||
|
Logger::initTest(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_wait0(DATAMODEL_REF m) {
|
||||||
|
auto ctx = m->GetService<ScriptContext>();
|
||||||
|
std::stringstream out;
|
||||||
|
Logger::initTest(&out);
|
||||||
|
|
||||||
|
tu_set_override(0);
|
||||||
|
luaEval(m, "wait(0) print('Wait')");
|
||||||
|
ASSERT_EQ("", out.str());
|
||||||
|
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("", out.str());
|
||||||
|
|
||||||
|
TT_ADVANCETIME(0.03);
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("INFO: Wait\n", out.str());
|
||||||
|
|
||||||
|
Logger::initTest(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_delay(DATAMODEL_REF m) {
|
||||||
|
auto ctx = m->GetService<ScriptContext>();
|
||||||
|
std::stringstream out;
|
||||||
|
Logger::initTest(&out);
|
||||||
|
|
||||||
|
tu_set_override(0);
|
||||||
|
luaEval(m, "delay(1, function() print('Delay') end)");
|
||||||
|
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("", out.str());
|
||||||
|
|
||||||
|
TT_ADVANCETIME(0.5);
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("", out.str());
|
||||||
|
|
||||||
|
TT_ADVANCETIME(0.5);
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("INFO: Delay\n", out.str());
|
||||||
|
|
||||||
|
Logger::initTest(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto m = DataModel::New();
|
||||||
|
m->Init(true);
|
||||||
|
|
||||||
|
test_wait1(m);
|
||||||
|
test_wait0(m);
|
||||||
|
test_delay(m);
|
||||||
|
|
||||||
|
return TEST_STATUS;
|
||||||
|
}
|
103
tests/src/luasignaltest.cpp
Normal file
103
tests/src/luasignaltest.cpp
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
|
||||||
|
#include "testutil.h"
|
||||||
|
#include "testutillua.h"
|
||||||
|
|
||||||
|
#include "timeutil.h"
|
||||||
|
#include "objects/part/part.h"
|
||||||
|
#include "objects/service/workspace.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
void test_connect(DATAMODEL_REF m) {
|
||||||
|
auto ctx = m->GetService<ScriptContext>();
|
||||||
|
auto part = Part::New();
|
||||||
|
m->GetService<Workspace>()->AddChild(part);
|
||||||
|
std::stringstream out;
|
||||||
|
Logger::initTest(&out);
|
||||||
|
|
||||||
|
luaEval(m, "workspace.Part.Touched:Connect(function() print('Fired!') end)");
|
||||||
|
ASSERT_EQ("", out.str());
|
||||||
|
|
||||||
|
part->Touched->Fire();
|
||||||
|
ASSERT_EQ("INFO: Fired!\n", out.str());
|
||||||
|
part->Touched->Fire();
|
||||||
|
ASSERT_EQ("INFO: Fired!\nINFO: Fired!\n", out.str());
|
||||||
|
|
||||||
|
Logger::initTest(nullptr);
|
||||||
|
part->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_waitwithin(DATAMODEL_REF m) {
|
||||||
|
auto ctx = m->GetService<ScriptContext>();
|
||||||
|
auto part = Part::New();
|
||||||
|
m->GetService<Workspace>()->AddChild(part);
|
||||||
|
std::stringstream out;
|
||||||
|
Logger::initTest(&out);
|
||||||
|
|
||||||
|
tu_set_override(0);
|
||||||
|
luaEval(m, "workspace.Part.Touched:Connect(function() print('Fired!') wait(1) print('Waited') end)");
|
||||||
|
ASSERT_EQ("", out.str());
|
||||||
|
|
||||||
|
// One shot
|
||||||
|
part->Touched->Fire();
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("INFO: Fired!\n", out.str());
|
||||||
|
TT_ADVANCETIME(0.5);
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("INFO: Fired!\n", out.str());
|
||||||
|
TT_ADVANCETIME(0.5);
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("INFO: Fired!\nINFO: Waited\n", out.str());
|
||||||
|
|
||||||
|
// Clear
|
||||||
|
out = std::stringstream();
|
||||||
|
Logger::initTest(&out); // Shouldn't *theoretically* be necessary, but just in principle...
|
||||||
|
|
||||||
|
// Double fire
|
||||||
|
part->Touched->Fire();
|
||||||
|
TT_ADVANCETIME(0.2);
|
||||||
|
part->Touched->Fire();
|
||||||
|
ASSERT_EQ("INFO: Fired!\nINFO: Fired!\n", out.str());
|
||||||
|
TT_ADVANCETIME(1-0.2); // Small extra delay is necessary because floating point math
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("INFO: Fired!\nINFO: Fired!\nINFO: Waited\n", out.str());
|
||||||
|
TT_ADVANCETIME(0.2);
|
||||||
|
ctx->RunSleepingThreads();
|
||||||
|
ASSERT_EQ("INFO: Fired!\nINFO: Fired!\nINFO: Waited\nINFO: Waited\n", out.str());
|
||||||
|
|
||||||
|
tu_set_override(-1UL);
|
||||||
|
Logger::initTest(nullptr);
|
||||||
|
part->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_await(DATAMODEL_REF m) {
|
||||||
|
auto ctx = m->GetService<ScriptContext>();
|
||||||
|
auto part = Part::New();
|
||||||
|
m->GetService<Workspace>()->AddChild(part);
|
||||||
|
std::stringstream out;
|
||||||
|
Logger::initTest(&out);
|
||||||
|
|
||||||
|
tu_set_override(0);
|
||||||
|
luaEval(m, "workspace.Part.Touched:Wait() print('Fired!')");
|
||||||
|
ASSERT_EQ("", out.str());
|
||||||
|
|
||||||
|
part->Touched->Fire();
|
||||||
|
ASSERT_EQ("INFO: Fired!\n", out.str());
|
||||||
|
part->Touched->Fire(); // Firing again should not affect output
|
||||||
|
ASSERT_EQ("INFO: Fired!\n", out.str());
|
||||||
|
|
||||||
|
tu_set_override(-1UL);
|
||||||
|
Logger::initTest(nullptr);
|
||||||
|
part->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto m = DataModel::New();
|
||||||
|
m->Init(true);
|
||||||
|
|
||||||
|
test_connect(m);
|
||||||
|
test_waitwithin(m);
|
||||||
|
test_await(m);
|
||||||
|
|
||||||
|
return TEST_STATUS;
|
||||||
|
}
|
20
tests/src/luatest.cpp
Normal file
20
tests/src/luatest.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include "testutil.h"
|
||||||
|
#include "testutillua.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
void test_output(DATAMODEL_REF m) {
|
||||||
|
ASSERT_EQ("INFO: Hello, world!\n", luaEvalOut(m, "print('Hello, world!')"));
|
||||||
|
// ASSERT_EQ("WARN: Some warning here.\n", luaEvalOut(m, "warn('Some warning here.')"));
|
||||||
|
// ASSERT_EQ("ERROR: An error!.\n", luaEvalOut(m, "error('An error!')"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto m = DataModel::New();
|
||||||
|
m->Init(true);
|
||||||
|
|
||||||
|
test_output(m);
|
||||||
|
|
||||||
|
return TEST_STATUS;
|
||||||
|
}
|
70
tests/src/testutil.h
Normal file
70
tests/src/testutil.h
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// https://bastian.rieck.me/blog/2017/simple_unit_tests/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <regex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef __FUNCTION__
|
||||||
|
#define __FUNC_NAME __FUNCTION__
|
||||||
|
#else
|
||||||
|
#define __FUNC_NAME __func__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ASSERT(x, msg) __assert((x), __FILE__, __LINE__, __FUNC_NAME, msg)
|
||||||
|
#define ASSERT_EQ(x, y) __assert_eq((x) == (y), __FILE__, __LINE__, __FUNC_NAME, #x, (y))
|
||||||
|
// #define ASSERT_EQSTR(x, y) ASSERT(strcmp(x, y) == 0, #x " != " #y)
|
||||||
|
#define ASSERT_EQSTR(x, y) ASSERT_EQ(x, y)
|
||||||
|
|
||||||
|
#define DATAMODEL_REF std::shared_ptr<DataModel>
|
||||||
|
|
||||||
|
#define TU_TIME_EXPOSE_TEST
|
||||||
|
#define TT_ADVANCETIME(secs) tu_set_override(tu_clock_micros() + (secs) * 1'000'000);
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
int TEST_STATUS = 0;
|
||||||
|
|
||||||
|
inline void __assert(bool cond, std::string file, int line, std::string func, std::string message) {
|
||||||
|
if (cond) return;
|
||||||
|
fprintf(stderr, "ASSERT FAILED : %s:%d : %s : '%s'\n", file.c_str(), line, func.c_str(), message.c_str());
|
||||||
|
TEST_STATUS = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline std::string quote(T value) {
|
||||||
|
return std::to_string(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::string quote<std::string>(std::string value) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::quoted(value);
|
||||||
|
std::string newstr = ss.str();
|
||||||
|
|
||||||
|
newstr = std::regex_replace(newstr, std::regex("\n"), "\\n");
|
||||||
|
return newstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline std::string quote<const char*>(const char* value) {
|
||||||
|
return quote<std::string>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline std::string quote<char*>(char* value) {
|
||||||
|
return quote<std::string>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void __assert_eq(bool cond, std::string file, int line, std::string func, std::string model, T value) {
|
||||||
|
if (cond) return;
|
||||||
|
std::string message = model + " != " + quote(value);
|
||||||
|
fprintf(stderr, "ASSERT FAILED : %s:%d : %s : '%s'\n", file.c_str(), line, func.c_str(), message.c_str());
|
||||||
|
TEST_STATUS = 1;
|
||||||
|
}
|
30
tests/src/testutillua.h
Normal file
30
tests/src/testutillua.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "testutil.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
#include "objects/datamodel.h"
|
||||||
|
#include "objects/script.h"
|
||||||
|
#include "objects/service/script/scriptcontext.h"
|
||||||
|
|
||||||
|
std::string luaEvalOut(DATAMODEL_REF m, std::string source) {
|
||||||
|
std::stringstream out;
|
||||||
|
Logger::initTest(&out);
|
||||||
|
|
||||||
|
auto s = Script::New();
|
||||||
|
m->AddChild(s);
|
||||||
|
s->source = source;
|
||||||
|
s->Run();
|
||||||
|
|
||||||
|
Logger::initTest(nullptr);
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaEval(DATAMODEL_REF m, std::string source) {
|
||||||
|
auto s = Script::New();
|
||||||
|
m->AddChild(s);
|
||||||
|
s->source = source;
|
||||||
|
s->Run();
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue