mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
Conversion to cpp 20
This commit is contained in:
@@ -33,7 +33,7 @@ set(VERSION_PATCH ${VERSION_DAY})
|
|||||||
set(VERSION_STRING "${VERSION_YEAR}.${VERSION_MONTH}.${VERSION_DAY}")
|
set(VERSION_STRING "${VERSION_YEAR}.${VERSION_MONTH}.${VERSION_DAY}")
|
||||||
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
file(GLOB HEADERS "*.h"
|
file(GLOB HEADERS "*.h"
|
||||||
"Console/*.h"
|
"Console/*.h"
|
||||||
|
|||||||
59
EU07.cpp
59
EU07.cpp
@@ -77,41 +77,54 @@ LONG WINAPI CrashHandler(EXCEPTION_POINTERS *ExceptionInfo)
|
|||||||
return EXCEPTION_EXECUTE_HANDLER;
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
#ifdef WITHDUMPGEN
|
#ifdef WITHDUMPGEN
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SetUnhandledExceptionFilter(CrashHandler);
|
SetUnhandledExceptionFilter(CrashHandler);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
// init start timestamp
|
// init start timestamp
|
||||||
Global.startTimestamp = std::chrono::steady_clock::now();
|
Global.startTimestamp = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
// quick short-circuit for standalone e3d export
|
// quick short-circuit for standalone e3d export
|
||||||
if (argc == 6 && std::string(argv[1]) == "-e3d") {
|
if (argc == 6 && std::string(argv[1]) == "-e3d")
|
||||||
std::string in(argv[2]);
|
{
|
||||||
std::string out(argv[3]);
|
std::string in(argv[2]);
|
||||||
int flags = std::stoi(std::string(argv[4]));
|
std::string out(argv[3]);
|
||||||
int dynamic = std::stoi(std::string(argv[5]));
|
int flags = std::stoi(std::string(argv[4]));
|
||||||
export_e3d_standalone(in, out, flags, dynamic);
|
int dynamic = std::stoi(std::string(argv[5]));
|
||||||
} else {
|
export_e3d_standalone(in, out, flags, dynamic);
|
||||||
try {
|
}
|
||||||
auto result { Application.init( argc, argv ) };
|
else
|
||||||
if( result == 0 ) {
|
{
|
||||||
result = Application.run();
|
try
|
||||||
Application.exit();
|
{
|
||||||
}
|
auto result{Application.init(argc, argv)};
|
||||||
} catch( std::bad_alloc const &Error ) {
|
if (result == 0)
|
||||||
ErrorLog( "Critical error, memory allocation failure: " + std::string( Error.what() ) );
|
{
|
||||||
}
|
result = Application.run();
|
||||||
}
|
Application.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc const &Error)
|
||||||
|
{
|
||||||
|
ErrorLog("Critical error, memory allocation failure: " + std::string(Error.what()));
|
||||||
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
catch (std::runtime_error const &Error)
|
||||||
|
{
|
||||||
|
std::string msg = "Simulator crash occured :(\n";
|
||||||
|
msg += Error.what();
|
||||||
|
MessageBoxA(nullptr, msg.c_str(), "Simulator crashed :(", MB_ICONERROR);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
#endif
|
#endif
|
||||||
std::_Exit(0); // skip destructors, there are ordering errors which causes segfaults
|
std::_Exit(0); // skip destructors, there are ordering errors which causes segfaults
|
||||||
}
|
}
|
||||||
|
|||||||
669
PyInt.cpp
669
PyInt.cpp
@@ -20,53 +20,76 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#endif
|
#endif
|
||||||
#include <simulation.h>
|
#include <simulation.h>
|
||||||
|
|
||||||
void render_task::run() {
|
void render_task::run()
|
||||||
|
{
|
||||||
|
|
||||||
// convert provided input to a python dictionary
|
// convert provided input to a python dictionary
|
||||||
auto *input = PyDict_New();
|
auto *input = PyDict_New();
|
||||||
if (input == nullptr) {
|
if (input == nullptr)
|
||||||
|
{
|
||||||
cancel();
|
cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for( auto const &datapair : m_input->floats ) { auto *value{ PyGetFloat( datapair.second ) }; PyDict_SetItemString( input, datapair.first.c_str(), value ); Py_DECREF( value ); }
|
for (auto const &datapair : m_input->floats)
|
||||||
for( auto const &datapair : m_input->integers ) { auto *value{ PyGetInt( datapair.second ) }; PyDict_SetItemString( input, datapair.first.c_str(), value ); Py_DECREF( value ); }
|
{
|
||||||
for( auto const &datapair : m_input->bools ) { auto *value{ PyGetBool( datapair.second ) }; PyDict_SetItemString( input, datapair.first.c_str(), value ); }
|
auto *value{PyGetFloat(datapair.second)};
|
||||||
for( auto const &datapair : m_input->strings ) { auto *value{ PyGetString( datapair.second.c_str() ) }; PyDict_SetItemString( input, datapair.first.c_str(), value ); Py_DECREF( value ); }
|
PyDict_SetItemString(input, datapair.first.c_str(), value);
|
||||||
for (auto const &datapair : m_input->vec2_lists) {
|
Py_DECREF(value);
|
||||||
PyObject *list = PyList_New(datapair.second.size());
|
}
|
||||||
|
for (auto const &datapair : m_input->integers)
|
||||||
|
{
|
||||||
|
auto *value{PyGetInt(datapair.second)};
|
||||||
|
PyDict_SetItemString(input, datapair.first.c_str(), value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
}
|
||||||
|
for (auto const &datapair : m_input->bools)
|
||||||
|
{
|
||||||
|
auto *value{PyGetBool(datapair.second)};
|
||||||
|
PyDict_SetItemString(input, datapair.first.c_str(), value);
|
||||||
|
}
|
||||||
|
for (auto const &datapair : m_input->strings)
|
||||||
|
{
|
||||||
|
auto *value{PyGetString(datapair.second.c_str())};
|
||||||
|
PyDict_SetItemString(input, datapair.first.c_str(), value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
}
|
||||||
|
for (auto const &datapair : m_input->vec2_lists)
|
||||||
|
{
|
||||||
|
PyObject *list = PyList_New(datapair.second.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < datapair.second.size(); i++) {
|
for (size_t i = 0; i < datapair.second.size(); i++)
|
||||||
auto const &vec = datapair.second[i];
|
{
|
||||||
WriteLog("passing " + glm::to_string(vec));
|
auto const &vec = datapair.second[i];
|
||||||
|
WriteLog("passing " + glm::to_string(vec));
|
||||||
|
|
||||||
PyObject *tuple = PyTuple_New(2);
|
PyObject *tuple = PyTuple_New(2);
|
||||||
PyTuple_SetItem(tuple, 0, PyGetFloat(vec.x)); // steals ref
|
PyTuple_SetItem(tuple, 0, PyGetFloat(vec.x)); // steals ref
|
||||||
PyTuple_SetItem(tuple, 1, PyGetFloat(vec.y)); // steals ref
|
PyTuple_SetItem(tuple, 1, PyGetFloat(vec.y)); // steals ref
|
||||||
|
|
||||||
PyList_SetItem(list, i, tuple); // steals ref
|
PyList_SetItem(list, i, tuple); // steals ref
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDict_SetItemString(input, datapair.first.c_str(), list);
|
PyDict_SetItemString(input, datapair.first.c_str(), list);
|
||||||
Py_DECREF(list);
|
Py_DECREF(list);
|
||||||
}
|
}
|
||||||
m_input = nullptr;
|
m_input = nullptr;
|
||||||
|
|
||||||
// call the renderer
|
// call the renderer
|
||||||
auto *output { PyObject_CallMethod( m_renderer, "render", "O", input ) };
|
auto *output{PyObject_CallMethod(m_renderer, const_cast<char *>("render"), const_cast<char *>("O"), input)};
|
||||||
Py_DECREF( input );
|
Py_DECREF(input);
|
||||||
|
|
||||||
if( output != nullptr ) {
|
if (output != nullptr)
|
||||||
auto *outputwidth { PyObject_CallMethod( m_renderer, "get_width", nullptr ) };
|
{
|
||||||
auto *outputheight { PyObject_CallMethod( m_renderer, "get_height", nullptr ) };
|
auto *outputwidth{PyObject_CallMethod(m_renderer, const_cast<char *>("get_width"), nullptr)};
|
||||||
// upload texture data
|
auto *outputheight{PyObject_CallMethod(m_renderer, const_cast<char *>("get_height"), nullptr)};
|
||||||
if( ( outputwidth != nullptr )
|
// upload texture data
|
||||||
&& ( outputheight != nullptr )
|
if ((outputwidth != nullptr) && (outputheight != nullptr) && m_target)
|
||||||
&& m_target) {
|
{
|
||||||
int width = PyInt_AsLong( outputwidth );
|
int width = PyInt_AsLong(outputwidth);
|
||||||
int height = PyInt_AsLong( outputheight );
|
int height = PyInt_AsLong(outputheight);
|
||||||
int components, format;
|
int components, format;
|
||||||
|
|
||||||
const unsigned char *image = reinterpret_cast<const unsigned char *>( PyString_AsString( output ) );
|
const unsigned char *image = reinterpret_cast<const unsigned char *>(PyString_AsString(output));
|
||||||
|
|
||||||
std::lock_guard<std::mutex> guard(m_target->mutex);
|
std::lock_guard<std::mutex> guard(m_target->mutex);
|
||||||
|
|
||||||
@@ -101,16 +124,22 @@ void render_task::run() {
|
|||||||
m_target->components = components;
|
m_target->components = components;
|
||||||
m_target->format = format;
|
m_target->format = format;
|
||||||
m_target->timestamp = std::chrono::high_resolution_clock::now();
|
m_target->timestamp = std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
if( outputheight != nullptr ) { Py_DECREF( outputheight ); }
|
if (outputheight != nullptr)
|
||||||
if( outputwidth != nullptr ) { Py_DECREF( outputwidth ); }
|
{
|
||||||
Py_DECREF( output );
|
Py_DECREF(outputheight);
|
||||||
}
|
}
|
||||||
|
if (outputwidth != nullptr)
|
||||||
|
{
|
||||||
|
Py_DECREF(outputwidth);
|
||||||
|
}
|
||||||
|
Py_DECREF(output);
|
||||||
|
}
|
||||||
|
|
||||||
// get commands from renderer
|
// get commands from renderer
|
||||||
auto *commandsPO = PyObject_CallMethod(m_renderer, "getCommands", nullptr);
|
auto *commandsPO = PyObject_CallMethod(m_renderer, const_cast<char *>("getCommands"), nullptr);
|
||||||
if (commandsPO != nullptr)
|
if (commandsPO != nullptr)
|
||||||
{
|
{
|
||||||
std::vector<std::string> commands = python_external_utils::PyObjectToStringArray(commandsPO);
|
std::vector<std::string> commands = python_external_utils::PyObjectToStringArray(commandsPO);
|
||||||
|
|
||||||
Py_DECREF(commandsPO);
|
Py_DECREF(commandsPO);
|
||||||
@@ -152,7 +181,8 @@ void render_task::run() {
|
|||||||
cd.param1 = p1;
|
cd.param1 = p1;
|
||||||
cd.param2 = p2;
|
cd.param2 = p2;
|
||||||
|
|
||||||
WriteLog("Python: Executing command [" + baseCmd + "] with params: P1=" + std::to_string(p1) + " P2=" + std::to_string(p2) + " Target ID=" + std::to_string(simulation::Train->id()));
|
WriteLog("Python: Executing command [" + baseCmd + "] with params: P1=" + std::to_string(p1) + " P2=" + std::to_string(p2) +
|
||||||
|
" Target ID=" + std::to_string(simulation::Train->id()));
|
||||||
|
|
||||||
simulation::Commands.push(cd, static_cast<size_t>(command_target::vehicle) | simulation::Train->id());
|
simulation::Commands.push(cd, static_cast<size_t>(command_target::vehicle) | simulation::Train->id());
|
||||||
}
|
}
|
||||||
@@ -162,302 +192,317 @@ void render_task::run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_task::upload()
|
void render_task::upload()
|
||||||
{
|
{
|
||||||
if (Global.python_uploadmain && m_target && m_target->shared_tex)
|
if (Global.python_uploadmain && m_target && m_target->shared_tex)
|
||||||
{
|
{
|
||||||
m_target->shared_tex->update_from_memory(m_target->width, m_target->height, reinterpret_cast<const uint8_t*>(m_target->image.data()));
|
m_target->shared_tex->update_from_memory(m_target->width, m_target->height, reinterpret_cast<const uint8_t *>(m_target->image.data()));
|
||||||
//glBindTexture(GL_TEXTURE_2D, m_target->shared_tex->get_id());
|
// glBindTexture(GL_TEXTURE_2D, m_target->shared_tex->get_id());
|
||||||
//glTexImage2D(
|
// glTexImage2D(
|
||||||
// GL_TEXTURE_2D, 0,
|
// GL_TEXTURE_2D, 0,
|
||||||
// m_target->format,
|
// m_target->format,
|
||||||
// m_target->width, m_target->height, 0,
|
// m_target->width, m_target->height, 0,
|
||||||
// m_target->components, GL_UNSIGNED_BYTE, m_target->image);
|
// m_target->components, GL_UNSIGNED_BYTE, m_target->image);
|
||||||
//
|
//
|
||||||
//if (Global.python_mipmaps)
|
// if (Global.python_mipmaps)
|
||||||
//{
|
//{
|
||||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
// glGenerateMipmap(GL_TEXTURE_2D);
|
// glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
//}
|
//}
|
||||||
//else
|
// else
|
||||||
//{
|
//{
|
||||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
//if (Global.python_threadedupload)
|
// if (Global.python_threadedupload)
|
||||||
// glFlush();
|
// glFlush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_task::cancel() {
|
void render_task::cancel() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// initializes the module. returns true on success
|
// initializes the module. returns true on success
|
||||||
auto python_taskqueue::init() -> bool {
|
auto python_taskqueue::init() -> bool
|
||||||
|
{
|
||||||
|
|
||||||
crashreport_add_info("python.threadedupload", Global.python_threadedupload ? "yes" : "no");
|
crashreport_add_info("python.threadedupload", Global.python_threadedupload ? "yes" : "no");
|
||||||
crashreport_add_info("python.uploadmain", Global.python_uploadmain ? "yes" : "no");
|
crashreport_add_info("python.uploadmain", Global.python_uploadmain ? "yes" : "no");
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (sizeof(void*) == 8)
|
if (sizeof(void *) == 8)
|
||||||
Py_SetPythonHome("python64");
|
Py_SetPythonHome(const_cast<char *>("python64"));
|
||||||
else
|
else
|
||||||
Py_SetPythonHome("python");
|
Py_SetPythonHome(const_cast<char *>("python"));
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
if (sizeof(void*) == 8)
|
if (sizeof(void *) == 8)
|
||||||
Py_SetPythonHome("linuxpython64");
|
Py_SetPythonHome(const_cast<char *>("linuxpython64"));
|
||||||
else
|
else
|
||||||
Py_SetPythonHome("linuxpython");
|
Py_SetPythonHome(const_cast<char *>("linuxpython"));
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
if (sizeof(void*) == 8)
|
if (sizeof(void *) == 8)
|
||||||
Py_SetPythonHome("macpython64");
|
Py_SetPythonHome(const_cast<char *>("macpython64"));
|
||||||
else
|
else
|
||||||
Py_SetPythonHome("macpython");
|
Py_SetPythonHome(const_cast<char *>("macpython"));
|
||||||
#endif
|
#endif
|
||||||
Py_InitializeEx(0);
|
Py_InitializeEx(0);
|
||||||
|
|
||||||
PyEval_InitThreads();
|
PyEval_InitThreads();
|
||||||
|
|
||||||
PyObject *stringiomodule { nullptr };
|
PyObject *stringiomodule{nullptr};
|
||||||
PyObject *stringioclassname { nullptr };
|
PyObject *stringioclassname{nullptr};
|
||||||
PyObject *stringioobject { nullptr };
|
PyObject *stringioobject{nullptr};
|
||||||
|
|
||||||
// do the setup work while we hold the lock
|
// do the setup work while we hold the lock
|
||||||
m_main = PyImport_ImportModule("__main__");
|
m_main = PyImport_ImportModule("__main__");
|
||||||
if (m_main == nullptr) {
|
if (m_main == nullptr)
|
||||||
ErrorLog( "Python Interpreter: __main__ module is missing" );
|
{
|
||||||
goto release_and_exit;
|
ErrorLog("Python Interpreter: __main__ module is missing");
|
||||||
}
|
goto release_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
stringiomodule = PyImport_ImportModule( "cStringIO" );
|
stringiomodule = PyImport_ImportModule("cStringIO");
|
||||||
stringioclassname = (
|
stringioclassname = (stringiomodule != nullptr ? PyObject_GetAttrString(stringiomodule, "StringIO") : nullptr);
|
||||||
stringiomodule != nullptr ?
|
stringioobject = (stringioclassname != nullptr ? PyObject_CallObject(stringioclassname, nullptr) : nullptr);
|
||||||
PyObject_GetAttrString( stringiomodule, "StringIO" ) :
|
m_stderr = {(stringioobject == nullptr ? nullptr : PySys_SetObject(const_cast<char *>("stderr"), stringioobject) != 0 ? nullptr : stringioobject)};
|
||||||
nullptr );
|
|
||||||
stringioobject = (
|
|
||||||
stringioclassname != nullptr ?
|
|
||||||
PyObject_CallObject( stringioclassname, nullptr ) :
|
|
||||||
nullptr );
|
|
||||||
m_stderr = { (
|
|
||||||
stringioobject == nullptr ? nullptr :
|
|
||||||
PySys_SetObject( "stderr", stringioobject ) != 0 ? nullptr :
|
|
||||||
stringioobject ) };
|
|
||||||
|
|
||||||
if( false == run_file( "abstractscreenrenderer" ) ) { goto release_and_exit; }
|
if (false == run_file("abstractscreenrenderer"))
|
||||||
|
{
|
||||||
|
goto release_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
// release the lock, save the state for future use
|
// release the lock, save the state for future use
|
||||||
m_mainthread = PyEval_SaveThread();
|
m_mainthread = PyEval_SaveThread();
|
||||||
|
|
||||||
WriteLog( "Python Interpreter: setup complete" );
|
WriteLog("Python Interpreter: setup complete");
|
||||||
|
|
||||||
// init workers
|
// init workers
|
||||||
for( auto &worker : m_workers ) {
|
for (auto &worker : m_workers)
|
||||||
|
{
|
||||||
|
|
||||||
GLFWwindow *openglcontextwindow = nullptr;
|
GLFWwindow *openglcontextwindow = nullptr;
|
||||||
if (Global.python_threadedupload)
|
if (Global.python_threadedupload)
|
||||||
openglcontextwindow = Application.window( -1 );
|
openglcontextwindow = Application.window(-1);
|
||||||
worker = std::thread(
|
worker = std::jthread(&python_taskqueue::run, this, openglcontextwindow, std::ref(m_tasks), std::ref(m_uploadtasks), std::ref(m_condition), std::ref(m_exit));
|
||||||
&python_taskqueue::run, this,
|
|
||||||
openglcontextwindow, std::ref( m_tasks ), std::ref(m_uploadtasks), std::ref( m_condition ), std::ref( m_exit ) );
|
|
||||||
|
|
||||||
if( false == worker.joinable() ) { return false; }
|
if (false == worker.joinable())
|
||||||
}
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
release_and_exit:
|
release_and_exit:
|
||||||
PyEval_ReleaseLock();
|
PyEval_ReleaseLock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// shuts down the module
|
// shuts down the module
|
||||||
void python_taskqueue::exit() {
|
void python_taskqueue::exit()
|
||||||
if (!m_initialized)
|
{
|
||||||
return;
|
if (!m_initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
// let the workers know we're done with them
|
// let the workers know we're done with them
|
||||||
m_exit = true;
|
m_exit = true;
|
||||||
m_condition.notify_all();
|
m_condition.notify_all();
|
||||||
// let them free up their shit before we proceed
|
// let them free up their shit before we proceed
|
||||||
for( auto &worker : m_workers ) {
|
m_workers = {};
|
||||||
if (worker.joinable())
|
// get rid of the leftover tasks
|
||||||
worker.join();
|
// with the workers dead we don't have to worry about concurrent access anymore
|
||||||
}
|
for (auto task : m_tasks.data)
|
||||||
// get rid of the leftover tasks
|
{
|
||||||
// with the workers dead we don't have to worry about concurrent access anymore
|
task->cancel();
|
||||||
for( auto task : m_tasks.data ) {
|
}
|
||||||
task->cancel();
|
// take a bow
|
||||||
}
|
acquire_lock();
|
||||||
// take a bow
|
Py_Finalize();
|
||||||
acquire_lock();
|
|
||||||
Py_Finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds specified task along with provided collection of data to the work queue. returns true on success
|
// adds specified task along with provided collection of data to the work queue. returns true on success
|
||||||
auto python_taskqueue::insert( task_request const &Task ) -> bool {
|
auto python_taskqueue::insert(task_request const &Task) -> bool
|
||||||
|
{
|
||||||
|
|
||||||
if( !m_initialized
|
if (!m_initialized || (false == Global.python_enabled) || (Task.renderer.empty()) || (Task.input == nullptr) || (Task.target == 0))
|
||||||
|| ( false == Global.python_enabled )
|
{
|
||||||
|| ( Task.renderer.empty() )
|
return false;
|
||||||
|| ( Task.input == nullptr )
|
}
|
||||||
|| ( Task.target == 0 ) ) { return false; }
|
|
||||||
|
|
||||||
auto *renderer { fetch_renderer( Task.renderer ) };
|
auto *renderer{fetch_renderer(Task.renderer)};
|
||||||
if( renderer == nullptr ) { return false; }
|
if (renderer == nullptr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto newtask = std::make_shared<render_task>( renderer, Task.input, Task.target );
|
auto newtask = std::make_shared<render_task>(renderer, Task.input, Task.target);
|
||||||
bool newtaskinserted { false };
|
bool newtaskinserted{false};
|
||||||
// acquire a lock on the task queue and add the new task
|
// acquire a lock on the task queue and add the new task
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock( m_tasks.mutex );
|
std::lock_guard<std::mutex> lock(m_tasks.mutex);
|
||||||
// check the task list for a pending request with the same target
|
// check the task list for a pending request with the same target
|
||||||
for( auto &task : m_tasks.data ) {
|
for (auto &task : m_tasks.data)
|
||||||
if( task->target() == Task.target ) {
|
{
|
||||||
// replace pending task in the slot with the more recent one
|
if (task->target() == Task.target)
|
||||||
task->cancel();
|
{
|
||||||
task = newtask;
|
// replace pending task in the slot with the more recent one
|
||||||
newtaskinserted = true;
|
task->cancel();
|
||||||
break;
|
task = newtask;
|
||||||
}
|
newtaskinserted = true;
|
||||||
}
|
break;
|
||||||
if( false == newtaskinserted ) {
|
}
|
||||||
m_tasks.data.emplace_back( newtask );
|
}
|
||||||
}
|
if (false == newtaskinserted)
|
||||||
}
|
{
|
||||||
// potentially wake a worker to handle the new task
|
m_tasks.data.emplace_back(newtask);
|
||||||
m_condition.notify_one();
|
}
|
||||||
// all done
|
}
|
||||||
return true;
|
// potentially wake a worker to handle the new task
|
||||||
|
m_condition.notify_one();
|
||||||
|
// all done
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// executes python script stored in specified file. returns true on success
|
// executes python script stored in specified file. returns true on success
|
||||||
auto python_taskqueue::run_file( std::string const &File, std::string const &Path ) -> bool {
|
auto python_taskqueue::run_file(std::string const &File, std::string const &Path) -> bool
|
||||||
|
{
|
||||||
|
|
||||||
auto const lookup { FileExists( { Path + File, "python/local/" + File }, { ".py" } ) };
|
auto const lookup{FileExists({Path + File, "python/local/" + File}, {".py"})};
|
||||||
if( lookup.first.empty() ) { return false; }
|
if (lookup.first.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::ifstream inputfile { lookup.first + lookup.second };
|
std::ifstream inputfile{lookup.first + lookup.second};
|
||||||
std::string input;
|
std::string input;
|
||||||
input.assign( std::istreambuf_iterator<char>( inputfile ), std::istreambuf_iterator<char>() );
|
input.assign(std::istreambuf_iterator<char>(inputfile), std::istreambuf_iterator<char>());
|
||||||
|
|
||||||
if( PyRun_SimpleString( input.c_str() ) != 0 ) {
|
if (PyRun_SimpleString(input.c_str()) != 0)
|
||||||
error();
|
{
|
||||||
return false;
|
error();
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// acquires the python gil and sets the main thread as current
|
// acquires the python gil and sets the main thread as current
|
||||||
void python_taskqueue::acquire_lock() {
|
void python_taskqueue::acquire_lock()
|
||||||
|
{
|
||||||
|
|
||||||
PyEval_RestoreThread( m_mainthread );
|
PyEval_RestoreThread(m_mainthread);
|
||||||
}
|
}
|
||||||
|
|
||||||
// releases the python gil and swaps the main thread out
|
// releases the python gil and swaps the main thread out
|
||||||
void python_taskqueue::release_lock() {
|
void python_taskqueue::release_lock()
|
||||||
|
{
|
||||||
|
|
||||||
PyEval_SaveThread();
|
PyEval_SaveThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto python_taskqueue::fetch_renderer( std::string const Renderer ) ->PyObject * {
|
auto python_taskqueue::fetch_renderer(std::string const Renderer) -> PyObject *
|
||||||
|
{
|
||||||
|
|
||||||
auto const lookup { m_renderers.find( Renderer ) };
|
auto const lookup{m_renderers.find(Renderer)};
|
||||||
if( lookup != std::end( m_renderers ) ) {
|
if (lookup != std::end(m_renderers))
|
||||||
return lookup->second;
|
{
|
||||||
}
|
return lookup->second;
|
||||||
// try to load specified renderer class
|
}
|
||||||
auto const path { substr_path( Renderer ) };
|
// try to load specified renderer class
|
||||||
auto const file { Renderer.substr( path.size() ) };
|
auto const path{substr_path(Renderer)};
|
||||||
PyObject *renderer { nullptr };
|
auto const file{Renderer.substr(path.size())};
|
||||||
PyObject *rendererarguments { nullptr };
|
PyObject *renderer{nullptr};
|
||||||
PyObject *renderername { nullptr };
|
PyObject *rendererarguments{nullptr};
|
||||||
acquire_lock();
|
PyObject *renderername{nullptr};
|
||||||
{
|
acquire_lock();
|
||||||
if( m_main == nullptr ) {
|
{
|
||||||
ErrorLog( "Python Renderer: __main__ module is missing" );
|
if (m_main == nullptr)
|
||||||
goto cache_and_return;
|
{
|
||||||
}
|
ErrorLog("Python Renderer: __main__ module is missing");
|
||||||
|
goto cache_and_return;
|
||||||
|
}
|
||||||
|
|
||||||
if( false == run_file( file, path ) ) {
|
if (false == run_file(file, path))
|
||||||
goto cache_and_return;
|
{
|
||||||
}
|
goto cache_and_return;
|
||||||
renderername = PyObject_GetAttrString( m_main, file.c_str() );
|
}
|
||||||
if( renderername == nullptr ) {
|
renderername = PyObject_GetAttrString(m_main, file.c_str());
|
||||||
ErrorLog( "Python Renderer: class \"" + file + "\" not defined" );
|
if (renderername == nullptr)
|
||||||
goto cache_and_return;
|
{
|
||||||
}
|
ErrorLog("Python Renderer: class \"" + file + "\" not defined");
|
||||||
rendererarguments = Py_BuildValue("(s)", path.c_str());
|
goto cache_and_return;
|
||||||
if( rendererarguments == nullptr ) {
|
}
|
||||||
ErrorLog( "Python Renderer: failed to create initialization arguments" );
|
rendererarguments = Py_BuildValue("(s)", path.c_str());
|
||||||
goto cache_and_return;
|
if (rendererarguments == nullptr)
|
||||||
}
|
{
|
||||||
renderer = PyObject_CallObject( renderername, rendererarguments );
|
ErrorLog("Python Renderer: failed to create initialization arguments");
|
||||||
|
goto cache_and_return;
|
||||||
|
}
|
||||||
|
renderer = PyObject_CallObject(renderername, rendererarguments);
|
||||||
|
|
||||||
PyObject_CallMethod(renderer, "manul_set_format", "(s)", "RGBA");
|
PyObject_CallMethod(renderer, const_cast<char *>("manul_set_format"), const_cast<char *>("(s)"), "RGBA");
|
||||||
|
|
||||||
if( PyErr_Occurred() != nullptr ) {
|
if (PyErr_Occurred() != nullptr)
|
||||||
error();
|
{
|
||||||
renderer = nullptr;
|
error();
|
||||||
}
|
renderer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
cache_and_return:
|
cache_and_return:
|
||||||
// clean up after yourself
|
// clean up after yourself
|
||||||
if( rendererarguments != nullptr ) {
|
if (rendererarguments != nullptr)
|
||||||
Py_DECREF( rendererarguments );
|
{
|
||||||
}
|
Py_DECREF(rendererarguments);
|
||||||
}
|
}
|
||||||
release_lock();
|
}
|
||||||
// cache the failures as well so we don't try again on subsequent requests
|
release_lock();
|
||||||
m_renderers.emplace( Renderer, renderer );
|
// cache the failures as well so we don't try again on subsequent requests
|
||||||
return renderer;
|
m_renderers.emplace(Renderer, renderer);
|
||||||
|
return renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void python_taskqueue::run( GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> &Exit ) {
|
void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> &Exit)
|
||||||
|
{
|
||||||
|
|
||||||
if (Context)
|
if (Context)
|
||||||
glfwMakeContextCurrent( Context );
|
glfwMakeContextCurrent(Context);
|
||||||
|
|
||||||
// create a state object for this thread
|
// create a state object for this thread
|
||||||
PyEval_AcquireLock();
|
PyEval_AcquireLock();
|
||||||
auto *threadstate { PyThreadState_New( m_mainthread->interp ) };
|
auto *threadstate{PyThreadState_New(m_mainthread->interp)};
|
||||||
PyEval_ReleaseLock();
|
PyEval_ReleaseLock();
|
||||||
|
|
||||||
std::shared_ptr<render_task> task { nullptr };
|
std::shared_ptr<render_task> task{nullptr};
|
||||||
|
|
||||||
while( false == Exit.load() ) {
|
while (false == Exit.load())
|
||||||
// regardless of the reason we woke up prime the spurious wakeup flag for the next time
|
{
|
||||||
Condition.spurious( true );
|
// regardless of the reason we woke up prime the spurious wakeup flag for the next time
|
||||||
// keep working as long as there's any scheduled tasks
|
Condition.spurious(true);
|
||||||
do {
|
// keep working as long as there's any scheduled tasks
|
||||||
task = nullptr;
|
do
|
||||||
// acquire a lock on the task queue and potentially grab a task from it
|
{
|
||||||
{
|
task = nullptr;
|
||||||
std::lock_guard<std::mutex> lock( Tasks.mutex );
|
// acquire a lock on the task queue and potentially grab a task from it
|
||||||
if( false == Tasks.data.empty() ) {
|
{
|
||||||
// fifo
|
std::lock_guard<std::mutex> lock(Tasks.mutex);
|
||||||
task = Tasks.data.front();
|
if (false == Tasks.data.empty())
|
||||||
Tasks.data.pop_front();
|
{
|
||||||
}
|
// fifo
|
||||||
}
|
task = Tasks.data.front();
|
||||||
if( task != nullptr ) {
|
Tasks.data.pop_front();
|
||||||
// swap in my thread state
|
}
|
||||||
PyEval_RestoreThread( threadstate );
|
}
|
||||||
{
|
if (task != nullptr)
|
||||||
// execute python code
|
{
|
||||||
task->run();
|
// swap in my thread state
|
||||||
|
PyEval_RestoreThread(threadstate);
|
||||||
|
{
|
||||||
|
// execute python code
|
||||||
|
task->run();
|
||||||
if (Context)
|
if (Context)
|
||||||
task->upload();
|
task->upload();
|
||||||
else
|
else
|
||||||
@@ -465,24 +510,24 @@ void python_taskqueue::run( GLFWwindow *Context, rendertask_sequence &Tasks, upl
|
|||||||
std::lock_guard<std::mutex> lock(Upload_Tasks.mutex);
|
std::lock_guard<std::mutex> lock(Upload_Tasks.mutex);
|
||||||
Upload_Tasks.data.push_back(task);
|
Upload_Tasks.data.push_back(task);
|
||||||
}
|
}
|
||||||
if( PyErr_Occurred() != nullptr )
|
if (PyErr_Occurred() != nullptr)
|
||||||
error();
|
error();
|
||||||
}
|
}
|
||||||
// clear the thread state
|
// clear the thread state
|
||||||
PyEval_SaveThread();
|
PyEval_SaveThread();
|
||||||
}
|
}
|
||||||
// TBD, TODO: add some idle time between tasks in case we're on a single thread cpu?
|
// TBD, TODO: add some idle time between tasks in case we're on a single thread cpu?
|
||||||
} while( task != nullptr );
|
} while (task != nullptr);
|
||||||
// if there's nothing left to do wait until there is
|
// if there's nothing left to do wait until there is
|
||||||
// but check every now and then on your own to minimize potential deadlock situations
|
// but check every now and then on your own to minimize potential deadlock situations
|
||||||
Condition.wait_for( std::chrono::seconds( 5 ) );
|
Condition.wait_for(std::chrono::seconds(5));
|
||||||
}
|
}
|
||||||
// clean up thread state data
|
// clean up thread state data
|
||||||
PyEval_AcquireLock();
|
PyEval_AcquireLock();
|
||||||
PyThreadState_Swap( nullptr );
|
PyThreadState_Swap(nullptr);
|
||||||
PyThreadState_Clear( threadstate );
|
PyThreadState_Clear(threadstate);
|
||||||
PyThreadState_Delete( threadstate );
|
PyThreadState_Delete(threadstate);
|
||||||
PyEval_ReleaseLock();
|
PyEval_ReleaseLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void python_taskqueue::update()
|
void python_taskqueue::update()
|
||||||
@@ -495,46 +540,53 @@ void python_taskqueue::update()
|
|||||||
m_uploadtasks.data.clear();
|
m_uploadtasks.data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void python_taskqueue::error()
|
||||||
python_taskqueue::error() {
|
{
|
||||||
|
|
||||||
if( m_stderr != nullptr ) {
|
if (m_stderr != nullptr)
|
||||||
// std err pythona jest buforowane
|
{
|
||||||
PyErr_Print();
|
// std err pythona jest buforowane
|
||||||
auto *errortext { PyObject_CallMethod( m_stderr, "getvalue", nullptr ) };
|
PyErr_Print();
|
||||||
ErrorLog( PyString_AsString( errortext ) );
|
auto *errortext{PyObject_CallMethod(m_stderr, const_cast<char *>("getvalue"), nullptr)};
|
||||||
// czyscimy bufor na kolejne bledy
|
ErrorLog(PyString_AsString(errortext));
|
||||||
PyObject_CallMethod( m_stderr, "truncate", "i", 0 );
|
// czyscimy bufor na kolejne bledy
|
||||||
}
|
PyObject_CallMethod(m_stderr, const_cast<char *>("truncate"), const_cast<char *>("i"), 0);
|
||||||
else {
|
}
|
||||||
// nie dziala buffor pythona
|
else
|
||||||
PyObject *type, *value, *traceback;
|
{
|
||||||
PyErr_Fetch( &type, &value, &traceback );
|
// nie dziala buffor pythona
|
||||||
if( type == nullptr ) {
|
PyObject *type, *value, *traceback;
|
||||||
ErrorLog( "Python Interpreter: don't know how to handle null exception" );
|
PyErr_Fetch(&type, &value, &traceback);
|
||||||
}
|
if (type == nullptr)
|
||||||
PyErr_NormalizeException( &type, &value, &traceback );
|
{
|
||||||
if( type == nullptr ) {
|
ErrorLog("Python Interpreter: don't know how to handle null exception");
|
||||||
ErrorLog( "Python Interpreter: don't know how to handle null exception" );
|
}
|
||||||
}
|
PyErr_NormalizeException(&type, &value, &traceback);
|
||||||
auto *typetext { PyObject_Str( type ) };
|
if (type == nullptr)
|
||||||
if( typetext != nullptr ) {
|
{
|
||||||
ErrorLog( PyString_AsString( typetext ) );
|
ErrorLog("Python Interpreter: don't know how to handle null exception");
|
||||||
}
|
}
|
||||||
if( value != nullptr ) {
|
auto *typetext{PyObject_Str(type)};
|
||||||
ErrorLog( PyString_AsString( value ) );
|
if (typetext != nullptr)
|
||||||
}
|
{
|
||||||
auto *tracebacktext { PyObject_Str( traceback ) };
|
ErrorLog(PyString_AsString(typetext));
|
||||||
if( tracebacktext != nullptr ) {
|
}
|
||||||
ErrorLog( PyString_AsString( tracebacktext ) );
|
if (value != nullptr)
|
||||||
}
|
{
|
||||||
else {
|
ErrorLog(PyString_AsString(value));
|
||||||
WriteLog( "Python Interpreter: failed to retrieve the stack traceback" );
|
}
|
||||||
}
|
auto *tracebacktext{PyObject_Str(traceback)};
|
||||||
}
|
if (tracebacktext != nullptr)
|
||||||
|
{
|
||||||
|
ErrorLog(PyString_AsString(tracebacktext));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteLog("Python Interpreter: failed to retrieve the stack traceback");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::string> python_external_utils::PyObjectToStringArray(PyObject *pyList)
|
std::vector<std::string> python_external_utils::PyObjectToStringArray(PyObject *pyList)
|
||||||
{
|
{
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
@@ -570,7 +622,6 @@ std::vector<std::string> python_external_utils::PyObjectToStringArray(PyObject *
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
131
PyInt.h
131
PyInt.h
@@ -19,8 +19,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning( push )
|
#pragma warning(push)
|
||||||
#pragma warning( disable : 5033 )
|
#pragma warning(disable : 5033)
|
||||||
#endif
|
#endif
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
@@ -44,12 +44,13 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning( pop )
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Classes.h"
|
#include "Classes.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#define PyGetFloat(param) PyFloat_FromDouble(param)
|
#define PyGetFloat(param) PyFloat_FromDouble(param)
|
||||||
#define PyGetInt(param) PyInt_FromLong(param)
|
#define PyGetInt(param) PyInt_FromLong(param)
|
||||||
@@ -57,10 +58,11 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#define PyGetString(param) PyString_FromString(param)
|
#define PyGetString(param) PyString_FromString(param)
|
||||||
|
|
||||||
// python rendertarget
|
// python rendertarget
|
||||||
struct python_rt {
|
struct python_rt
|
||||||
|
{
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
|
|
||||||
ITexture* shared_tex;
|
ITexture *shared_tex;
|
||||||
|
|
||||||
int format;
|
int format;
|
||||||
int components;
|
int components;
|
||||||
@@ -72,83 +74,86 @@ struct python_rt {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO: extract common base and inherit specialization from it
|
// TODO: extract common base and inherit specialization from it
|
||||||
class render_task {
|
class render_task
|
||||||
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
render_task( PyObject *Renderer, std::shared_ptr<dictionary_source> Input, std::shared_ptr<python_rt> Target ) :
|
render_task(PyObject *Renderer, std::shared_ptr<dictionary_source> Input, std::shared_ptr<python_rt> Target) : m_renderer(Renderer), m_input(Input), m_target(Target) {}
|
||||||
m_renderer( Renderer ), m_input( Input ), m_target( Target )
|
// methods
|
||||||
{}
|
|
||||||
// methods
|
|
||||||
void run();
|
void run();
|
||||||
void upload();
|
void upload();
|
||||||
void cancel();
|
void cancel();
|
||||||
auto target() const -> std::shared_ptr<python_rt> { return m_target; }
|
auto target() const -> std::shared_ptr<python_rt>
|
||||||
|
{
|
||||||
|
return m_target;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// members
|
// members
|
||||||
PyObject *m_renderer {nullptr};
|
PyObject *m_renderer{nullptr};
|
||||||
std::shared_ptr<dictionary_source> m_input{nullptr};
|
std::shared_ptr<dictionary_source> m_input{nullptr};
|
||||||
std::shared_ptr<python_rt> m_target { nullptr };
|
std::shared_ptr<python_rt> m_target{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
class python_taskqueue {
|
class python_taskqueue
|
||||||
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// types
|
// types
|
||||||
struct task_request {
|
struct task_request
|
||||||
|
{
|
||||||
|
|
||||||
std::string const &renderer;
|
std::string const &renderer;
|
||||||
std::shared_ptr<dictionary_source> input;
|
std::shared_ptr<dictionary_source> input;
|
||||||
std::shared_ptr<python_rt> target;
|
std::shared_ptr<python_rt> target;
|
||||||
};
|
};
|
||||||
// constructors
|
// constructors
|
||||||
python_taskqueue() = default;
|
python_taskqueue() = default;
|
||||||
// methods
|
// methods
|
||||||
// initializes the module. returns true on success
|
// initializes the module. returns true on success
|
||||||
auto init() -> bool;
|
auto init() -> bool;
|
||||||
// shuts down the module
|
// shuts down the module
|
||||||
void exit();
|
void exit();
|
||||||
// adds specified task along with provided collection of data to the work queue. returns true on success
|
// adds specified task along with provided collection of data to the work queue. returns true on success
|
||||||
auto insert( task_request const &Task ) -> bool;
|
auto insert(task_request const &Task) -> bool;
|
||||||
// executes python script stored in specified file. returns true on success
|
// executes python script stored in specified file. returns true on success
|
||||||
auto run_file( std::string const &File, std::string const &Path = "" ) -> bool;
|
auto run_file(std::string const &File, std::string const &Path = "") -> bool;
|
||||||
// acquires the python gil and sets the main thread as current
|
// acquires the python gil and sets the main thread as current
|
||||||
void acquire_lock();
|
void acquire_lock();
|
||||||
// releases the python gil and swaps the main thread out
|
// releases the python gil and swaps the main thread out
|
||||||
void release_lock();
|
void release_lock();
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// types
|
// types
|
||||||
static int const WORKERCOUNT { 1 };
|
static int const WORKERCOUNT{1};
|
||||||
using worker_array = std::array<std::thread, WORKERCOUNT >;
|
using worker_array = std::array<std::jthread, WORKERCOUNT>;
|
||||||
using rendertask_sequence = threading::lockable< std::deque<std::shared_ptr<render_task>> >;
|
using rendertask_sequence = threading::lockable<std::deque<std::shared_ptr<render_task>>>;
|
||||||
using uploadtask_sequence = threading::lockable< std::deque<std::shared_ptr<render_task>> >;
|
using uploadtask_sequence = threading::lockable<std::deque<std::shared_ptr<render_task>>>;
|
||||||
// methods
|
// methods
|
||||||
auto fetch_renderer( std::string const Renderer ) -> PyObject *;
|
auto fetch_renderer(std::string const Renderer) -> PyObject *;
|
||||||
void run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> &Exit );
|
void run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> &Exit);
|
||||||
void error();
|
void error();
|
||||||
|
|
||||||
// members
|
// members
|
||||||
PyObject *m_main { nullptr };
|
PyObject *m_main{nullptr};
|
||||||
PyObject *m_stderr { nullptr };
|
PyObject *m_stderr{nullptr};
|
||||||
PyThreadState *m_mainthread{ nullptr };
|
PyThreadState *m_mainthread{nullptr};
|
||||||
worker_array m_workers;
|
worker_array m_workers;
|
||||||
threading::condition_variable m_condition; // wakes up the workers
|
threading::condition_variable m_condition; // wakes up the workers
|
||||||
std::atomic<bool> m_exit { false }; // signals the workers to quit
|
std::atomic<bool> m_exit{false}; // signals the workers to quit
|
||||||
std::unordered_map<std::string, PyObject *> m_renderers; // cache of python classes
|
std::unordered_map<std::string, PyObject *> m_renderers; // cache of python classes
|
||||||
rendertask_sequence m_tasks;
|
rendertask_sequence m_tasks;
|
||||||
uploadtask_sequence m_uploadtasks;
|
uploadtask_sequence m_uploadtasks;
|
||||||
bool m_initialized { false };
|
bool m_initialized{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
class python_external_utils
|
class python_external_utils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::vector<std::string> PyObjectToStringArray(PyObject *pyList);
|
static std::vector<std::string> PyObjectToStringArray(PyObject *pyList);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -135,24 +135,24 @@ int eu07_application::run_crashgui()
|
|||||||
|
|
||||||
if (Global.asLang == "pl")
|
if (Global.asLang == "pl")
|
||||||
{
|
{
|
||||||
ImGui::Begin(u8"Raportowanie błędów", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoResize);
|
ImGui::Begin("Raportowanie błędów", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoResize);
|
||||||
ImGui::TextUnformatted(u8"Podczas ostatniego uruchomienia symulatora wystąpił błąd.\nWysłać raport o błędzie do deweloperów?\n");
|
ImGui::TextUnformatted("Podczas ostatniego uruchomienia symulatora wystąpił błąd.\nWysłać raport o błędzie do deweloperów?\n");
|
||||||
ImGui::TextUnformatted((u8"Usługa udostępniana przez " + crashreport_get_provider() + "\n").c_str());
|
ImGui::TextUnformatted(("Usługa udostępniana przez " + crashreport_get_provider() + "\n").c_str());
|
||||||
y = ImGui::Button(u8"Tak", ImVec2S(60, 0));
|
y = ImGui::Button("Tak", ImVec2S(60, 0));
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Checkbox(u8"W przyszłości przesyłaj raporty o błędach automatycznie", &autoup);
|
ImGui::Checkbox("W przyszłości przesyłaj raporty o błędach automatycznie", &autoup);
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::TextDisabled("(?)");
|
ImGui::TextDisabled("(?)");
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::TextUnformatted(u8"W celu wyłączenia tej funkcji będzie trzeba skasować plik crashdumps/autoupload_enabled.conf");
|
ImGui::TextUnformatted("W celu wyłączenia tej funkcji będzie trzeba skasować plik crashdumps/autoupload_enabled.conf");
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
n = ImGui::Button(u8"Nie", ImVec2S(60, 0));
|
n = ImGui::Button("Nie", ImVec2S(60, 0));
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -391,7 +391,7 @@ timetable_panel::update() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// header
|
// header
|
||||||
m_tablelines.emplace_back( u8"┌─────┬────────────────────────────────────┬─────────┬─────┐", Global.UITextColor );
|
m_tablelines.emplace_back( "┌─────┬────────────────────────────────────┬─────────┬─────┐", Global.UITextColor );
|
||||||
|
|
||||||
TMTableLine const *tableline;
|
TMTableLine const *tableline;
|
||||||
for( int i = table.StationStart; i <= table.StationCount; ++i ) {
|
for( int i = table.StationStart; i <= table.StationCount; ++i ) {
|
||||||
@@ -423,11 +423,11 @@ timetable_panel::update() {
|
|||||||
auto const arrival { (
|
auto const arrival { (
|
||||||
tableline->Ah >= 0 ?
|
tableline->Ah >= 0 ?
|
||||||
to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Am, true, 3 ) :
|
to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Am, true, 3 ) :
|
||||||
u8" │ " ) };
|
" │ " ) };
|
||||||
auto const departure { (
|
auto const departure { (
|
||||||
tableline->Dh >= 0 ?
|
tableline->Dh >= 0 ?
|
||||||
to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Dm, true, 3 ) :
|
to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Dm, true, 3 ) :
|
||||||
u8" │ " ) };
|
" │ " ) };
|
||||||
auto const candepart { (
|
auto const candepart { (
|
||||||
( table.StationStart < table.StationIndex )
|
( table.StationStart < table.StationIndex )
|
||||||
&& ( i < table.StationIndex )
|
&& ( i < table.StationIndex )
|
||||||
@@ -446,25 +446,25 @@ timetable_panel::update() {
|
|||||||
candepart ? colors::uitextgreen : // czas minął i odjazd był, to nazwa stacji będzie na zielono
|
candepart ? colors::uitextgreen : // czas minął i odjazd był, to nazwa stacji będzie na zielono
|
||||||
isatpassengerstop ? colors::uitextorange :
|
isatpassengerstop ? colors::uitextorange :
|
||||||
Global.UITextColor ) };
|
Global.UITextColor ) };
|
||||||
auto const trackcount{ ( tableline->TrackNo == 1 ? u8" ┃ " : u8" ║ " ) };
|
auto const trackcount{ ( tableline->TrackNo == 1 ? " ┃ " : " ║ " ) };
|
||||||
m_tablelines.emplace_back(
|
m_tablelines.emplace_back(
|
||||||
( u8"│ " + vmax + u8" │ " + station + trackcount + arrival + u8" │ " + traveltime + u8" │" ),
|
( "│ " + vmax + " │ " + station + trackcount + arrival + " │ " + traveltime + " │" ),
|
||||||
linecolor );
|
linecolor );
|
||||||
m_tablelines.emplace_back(
|
m_tablelines.emplace_back(
|
||||||
( u8"│ │ " + location + tableline->StationWare + trackcount + departure + u8" │ │" ),
|
( "│ │ " + location + tableline->StationWare + trackcount + departure + " │ │" ),
|
||||||
linecolor );
|
linecolor );
|
||||||
// divider/footer
|
// divider/footer
|
||||||
if( i < table.StationCount ) {
|
if( i < table.StationCount ) {
|
||||||
auto const *nexttableline { tableline + 1 };
|
auto const *nexttableline { tableline + 1 };
|
||||||
std::string const vmaxnext{ ( tableline->vmax == nexttableline->vmax ? u8"│ ├" : u8"├─────┼" ) };
|
std::string const vmaxnext{ ( tableline->vmax == nexttableline->vmax ? "│ ├" : "├─────┼" ) };
|
||||||
auto const trackcountnext{ ( nexttableline->TrackNo == 1 ? u8"╂" : u8"╫" ) };
|
auto const trackcountnext{ ( nexttableline->TrackNo == 1 ? "╂" : "╫" ) };
|
||||||
m_tablelines.emplace_back(
|
m_tablelines.emplace_back(
|
||||||
vmaxnext + u8"────────────────────────────────────" + trackcountnext + u8"─────────┼─────┤",
|
vmaxnext + "────────────────────────────────────" + trackcountnext + "─────────┼─────┤",
|
||||||
Global.UITextColor );
|
Global.UITextColor );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_tablelines.emplace_back(
|
m_tablelines.emplace_back(
|
||||||
u8"└─────┴────────────────────────────────────┴─────────┴─────┘",
|
"└─────┴────────────────────────────────────┴─────────┴─────┘",
|
||||||
Global.UITextColor );
|
Global.UITextColor );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
683
parser.cpp
683
parser.cpp
@@ -24,259 +24,283 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
// cParser -- generic class for parsing text data.
|
// cParser -- generic class for parsing text data.
|
||||||
|
|
||||||
// constructors
|
// constructors
|
||||||
cParser::cParser( std::string const &Stream, buffertype const Type, std::string Path, bool const Loadtraction, std::vector<std::string> Parameters, bool allowRandom ) :
|
cParser::cParser(std::string const &Stream, buffertype const Type, std::string Path, bool const Loadtraction, std::vector<std::string> Parameters, bool allowRandom)
|
||||||
mPath(Path),
|
: mPath(Path), LoadTraction(Loadtraction), allowRandomIncludes(allowRandom)
|
||||||
LoadTraction( Loadtraction ),
|
{
|
||||||
allowRandomIncludes(allowRandom) {
|
// store to calculate sub-sequent includes from relative path
|
||||||
// store to calculate sub-sequent includes from relative path
|
if (Type == buffertype::buffer_FILE)
|
||||||
if( Type == buffertype::buffer_FILE ) {
|
{
|
||||||
mFile = Stream;
|
mFile = Stream;
|
||||||
}
|
}
|
||||||
// reset pointers and attach proper type of buffer
|
// reset pointers and attach proper type of buffer
|
||||||
switch (Type) {
|
switch (Type)
|
||||||
case buffer_FILE: {
|
{
|
||||||
Path.append( Stream );
|
case buffer_FILE:
|
||||||
mStream = std::make_shared<std::ifstream>( Path, std::ios_base::binary );
|
{
|
||||||
// content of *.inc files is potentially grouped together
|
Path.append(Stream);
|
||||||
if( ( Stream.size() >= 4 )
|
mStream = std::make_shared<std::ifstream>(Path, std::ios_base::binary);
|
||||||
&& ( ToLower( Stream.substr( Stream.size() - 4 ) ) == ".inc" ) ) {
|
// content of *.inc files is potentially grouped together
|
||||||
mIncFile = true;
|
if ((Stream.size() >= 4) && (ToLower(Stream.substr(Stream.size() - 4)) == ".inc"))
|
||||||
scene::Groups.create();
|
{
|
||||||
}
|
mIncFile = true;
|
||||||
break;
|
scene::Groups.create();
|
||||||
}
|
}
|
||||||
case buffer_TEXT: {
|
break;
|
||||||
mStream = std::make_shared<std::istringstream>( Stream );
|
}
|
||||||
break;
|
case buffer_TEXT:
|
||||||
}
|
{
|
||||||
default: {
|
mStream = std::make_shared<std::istringstream>(Stream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
default:
|
||||||
// calculate stream size
|
{
|
||||||
if (mStream)
|
break;
|
||||||
{
|
}
|
||||||
if( true == mStream->fail() ) {
|
}
|
||||||
ErrorLog( "Failed to open file \"" + Path + "\"" );
|
// calculate stream size
|
||||||
}
|
if (mStream)
|
||||||
else {
|
{
|
||||||
mSize = mStream->rdbuf()->pubseekoff( 0, std::ios_base::end );
|
if (true == mStream->fail())
|
||||||
mStream->rdbuf()->pubseekoff( 0, std::ios_base::beg );
|
{
|
||||||
mLine = 1;
|
ErrorLog("Failed to open file \"" + Path + "\"");
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
// set parameter set if one was provided
|
{
|
||||||
if( false == Parameters.empty() ) {
|
mSize = mStream->rdbuf()->pubseekoff(0, std::ios_base::end);
|
||||||
parameters.swap( Parameters );
|
mStream->rdbuf()->pubseekoff(0, std::ios_base::beg);
|
||||||
}
|
mLine = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// set parameter set if one was provided
|
||||||
|
if (false == Parameters.empty())
|
||||||
|
{
|
||||||
|
parameters.swap(Parameters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
cParser::~cParser() {
|
cParser::~cParser()
|
||||||
|
{
|
||||||
|
|
||||||
if( true == mIncFile ) {
|
if (true == mIncFile)
|
||||||
// wrap up the node group holding content of processed file
|
{
|
||||||
scene::Groups.close();
|
// wrap up the node group holding content of processed file
|
||||||
}
|
scene::Groups.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <> glm::vec3 cParser::getToken(bool const ToLower, char const *Break)
|
||||||
glm::vec3
|
{
|
||||||
cParser::getToken( bool const ToLower, char const *Break ) {
|
// NOTE: this specialization ignores default arguments
|
||||||
// NOTE: this specialization ignores default arguments
|
getTokens(3, false, "\n\r\t ,;[]");
|
||||||
getTokens( 3, false, "\n\r\t ,;[]" );
|
glm::vec3 output;
|
||||||
glm::vec3 output;
|
*this >> output.x >> output.y >> output.z;
|
||||||
*this
|
return output;
|
||||||
>> output.x
|
|
||||||
>> output.y
|
|
||||||
>> output.z;
|
|
||||||
return output;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template <> cParser &cParser::operator>>(std::string &Right)
|
||||||
cParser&
|
{
|
||||||
cParser::operator>>( std::string &Right ) {
|
|
||||||
|
|
||||||
if( true == this->tokens.empty() ) { return *this; }
|
if (true == this->tokens.empty())
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Right = this->tokens.front();
|
Right = this->tokens.front();
|
||||||
this->tokens.pop_front();
|
this->tokens.pop_front();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template <> cParser &cParser::operator>>(bool &Right)
|
||||||
cParser&
|
{
|
||||||
cParser::operator>>( bool &Right ) {
|
|
||||||
|
|
||||||
if( true == this->tokens.empty() ) { return *this; }
|
if (true == this->tokens.empty())
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Right = ( ( this->tokens.front() == "true" )
|
Right = ((this->tokens.front() == "true") || (this->tokens.front() == "yes") || (this->tokens.front() == "1"));
|
||||||
|| ( this->tokens.front() == "yes" )
|
this->tokens.pop_front();
|
||||||
|| ( this->tokens.front() == "1" ) );
|
|
||||||
this->tokens.pop_front();
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <> bool cParser::getToken<bool>(bool const ToLower, const char *Break)
|
||||||
bool
|
{
|
||||||
cParser::getToken<bool>( bool const ToLower, const char *Break ) {
|
|
||||||
|
|
||||||
auto const token = getToken<std::string>( true, Break );
|
auto const token = getToken<std::string>(true, Break);
|
||||||
return ( ( token == "true" )
|
return ((token == "true") || (token == "yes") || (token == "1"));
|
||||||
|| ( token == "yes" )
|
|
||||||
|| ( token == "1" ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
cParser &
|
cParser &cParser::autoclear(bool const Autoclear)
|
||||||
cParser::autoclear( bool const Autoclear ) {
|
{
|
||||||
|
|
||||||
m_autoclear = Autoclear;
|
m_autoclear = Autoclear;
|
||||||
if( mIncludeParser ) { mIncludeParser->autoclear( Autoclear ); }
|
if (mIncludeParser)
|
||||||
|
{
|
||||||
|
mIncludeParser->autoclear(Autoclear);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cParser::getTokens(unsigned int Count, bool ToLower, const char *Break)
|
bool cParser::getTokens(unsigned int Count, bool ToLower, const char *Break)
|
||||||
{
|
{
|
||||||
if( true == m_autoclear ) {
|
if (true == m_autoclear)
|
||||||
// legacy parser behaviour
|
{
|
||||||
tokens.clear();
|
// legacy parser behaviour
|
||||||
}
|
tokens.clear();
|
||||||
/*
|
}
|
||||||
if (LoadTraction==true)
|
/*
|
||||||
trtest="niemaproblema"; //wczytywać
|
if (LoadTraction==true)
|
||||||
else
|
trtest="niemaproblema"; //wczytywać
|
||||||
trtest="x"; //nie wczytywać
|
else
|
||||||
*/
|
trtest="x"; //nie wczytywać
|
||||||
/*
|
*/
|
||||||
int i;
|
/*
|
||||||
this->str("");
|
int i;
|
||||||
this->clear();
|
this->str("");
|
||||||
*/
|
this->clear();
|
||||||
for (unsigned int i = tokens.size(); i < Count; ++i)
|
*/
|
||||||
{
|
for (unsigned int i = tokens.size(); i < Count; ++i)
|
||||||
std::string token = readToken(ToLower, Break);
|
{
|
||||||
if( true == token.empty() ) {
|
std::string token = readToken(ToLower, Break);
|
||||||
// no more tokens
|
if (true == token.empty())
|
||||||
break;
|
{
|
||||||
}
|
// no more tokens
|
||||||
// collect parameters
|
break;
|
||||||
tokens.emplace_back( token );
|
}
|
||||||
/*
|
// collect parameters
|
||||||
if (i == 0)
|
tokens.emplace_back(token);
|
||||||
this->str(token);
|
/*
|
||||||
else
|
if (i == 0)
|
||||||
{
|
this->str(token);
|
||||||
std::string temp = this->str();
|
else
|
||||||
temp.append("\n");
|
{
|
||||||
temp.append(token);
|
std::string temp = this->str();
|
||||||
this->str(temp);
|
temp.append("\n");
|
||||||
}
|
temp.append(token);
|
||||||
*/
|
this->str(temp);
|
||||||
}
|
}
|
||||||
if (tokens.size() < Count)
|
*/
|
||||||
return false;
|
}
|
||||||
else
|
if (tokens.size() < Count)
|
||||||
return true;
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cParser::readToken( bool ToLower, const char *Break ) {
|
std::string cParser::readToken(bool ToLower, const char *Break)
|
||||||
|
{
|
||||||
|
|
||||||
std::string token;
|
std::string token;
|
||||||
if( mIncludeParser ) {
|
if (mIncludeParser)
|
||||||
// see if there's include parsing going on. clean up when it's done.
|
{
|
||||||
token = mIncludeParser->readToken( ToLower, Break );
|
// see if there's include parsing going on. clean up when it's done.
|
||||||
if( true == token.empty() ) {
|
token = mIncludeParser->readToken(ToLower, Break);
|
||||||
mIncludeParser = nullptr;
|
if (true == token.empty())
|
||||||
}
|
{
|
||||||
}
|
mIncludeParser = nullptr;
|
||||||
if( true == token.empty() ) {
|
}
|
||||||
// get the token yourself if the delegation attempt failed
|
}
|
||||||
char c { 0 };
|
if (true == token.empty())
|
||||||
do {
|
{
|
||||||
while( mStream->peek() != EOF && strchr( Break, c = mStream->get() ) == NULL ) {
|
// get the token yourself if the delegation attempt failed
|
||||||
if( ToLower )
|
char c{0};
|
||||||
c = tolower( c );
|
do
|
||||||
token += c;
|
{
|
||||||
if( findQuotes( token ) ) // do glue together words enclosed in quotes
|
while (mStream->peek() != EOF && strchr(Break, c = mStream->get()) == NULL)
|
||||||
continue;
|
{
|
||||||
if( skipComments && trimComments( token ) ) // don't glue together words separated with comment
|
if (ToLower)
|
||||||
break;
|
c = tolower(c);
|
||||||
}
|
token += c;
|
||||||
if( c == '\n' ) {
|
if (findQuotes(token)) // do glue together words enclosed in quotes
|
||||||
// update line counter
|
continue;
|
||||||
++mLine;
|
if (skipComments && trimComments(token)) // don't glue together words separated with comment
|
||||||
}
|
break;
|
||||||
} while( token == "" && mStream->peek() != EOF ); // double check in case of consecutive separators
|
}
|
||||||
}
|
if (c == '\n')
|
||||||
// check the first token for potential presence of utf bom
|
{
|
||||||
if( mFirstToken ) {
|
// update line counter
|
||||||
mFirstToken = false;
|
++mLine;
|
||||||
if( token.rfind( "\xef\xbb\xbf", 0 ) == 0 ) {
|
}
|
||||||
token.erase( 0, 3 );
|
} while (token == "" && mStream->peek() != EOF); // double check in case of consecutive separators
|
||||||
}
|
}
|
||||||
if( true == token.empty() ) {
|
// check the first token for potential presence of utf bom
|
||||||
// potentially possible if our first token was standalone utf bom
|
if (mFirstToken)
|
||||||
token = readToken( ToLower, Break );
|
{
|
||||||
}
|
mFirstToken = false;
|
||||||
}
|
if (token.rfind("\xef\xbb\xbf", 0) == 0)
|
||||||
|
{
|
||||||
|
token.erase(0, 3);
|
||||||
|
}
|
||||||
|
if (true == token.empty())
|
||||||
|
{
|
||||||
|
// potentially possible if our first token was standalone utf bom
|
||||||
|
token = readToken(ToLower, Break);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( false == parameters.empty() ) {
|
if (false == parameters.empty())
|
||||||
// if there's parameter list, check the token for potential parameters to replace
|
{
|
||||||
size_t pos; // początek podmienianego ciągu
|
// if there's parameter list, check the token for potential parameters to replace
|
||||||
while( ( pos = token.find( "(p" ) ) != std::string::npos ) {
|
size_t pos; // początek podmienianego ciągu
|
||||||
// check if the token is a parameter which should be replaced with stored true value
|
while ((pos = token.find("(p")) != std::string::npos)
|
||||||
auto const parameter{ token.substr( pos + 2, token.find( ")", pos ) - ( pos + 2 ) ) }; // numer parametru
|
{
|
||||||
token.erase( pos, token.find( ")", pos ) - pos + 1 ); // najpierw usunięcie "(pN)"
|
// check if the token is a parameter which should be replaced with stored true value
|
||||||
size_t nr = atoi( parameter.c_str() ) - 1;
|
auto const parameter{token.substr(pos + 2, token.find(")", pos) - (pos + 2))}; // numer parametru
|
||||||
if( nr < parameters.size() ) {
|
token.erase(pos, token.find(")", pos) - pos + 1); // najpierw usunięcie "(pN)"
|
||||||
token.insert( pos, parameters.at( nr ) ); // wklejenie wartości parametru
|
size_t nr = atoi(parameter.c_str()) - 1;
|
||||||
if( ToLower )
|
if (nr < parameters.size())
|
||||||
for( ; pos < parameters.at( nr ).size(); ++pos )
|
{
|
||||||
token[ pos ] = tolower( token[ pos ] );
|
token.insert(pos, parameters.at(nr)); // wklejenie wartości parametru
|
||||||
}
|
if (ToLower)
|
||||||
else
|
for (; pos < parameters.at(nr).size(); ++pos)
|
||||||
token.insert( pos, "none" ); // zabezpieczenie przed brakiem parametru
|
token[pos] = tolower(token[pos]);
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
token.insert(pos, "none"); // zabezpieczenie przed brakiem parametru
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// launch child parser if include directive found.
|
// launch child parser if include directive found.
|
||||||
// NOTE: parameter collecting uses default set of token separators.
|
// NOTE: parameter collecting uses default set of token separators.
|
||||||
if( expandIncludes && token == "include" ) {
|
if (expandIncludes && token == "include")
|
||||||
|
{
|
||||||
std::string includefile = allowRandomIncludes ? deserialize_random_set(*this) : readToken(ToLower); // nazwa pliku
|
std::string includefile = allowRandomIncludes ? deserialize_random_set(*this) : readToken(ToLower); // nazwa pliku
|
||||||
replace_slashes(includefile);
|
replace_slashes(includefile);
|
||||||
if ((true == LoadTraction) ||
|
if ((true == LoadTraction) || ((false == contains(includefile, "tr/")) && (false == contains(includefile, "tra/"))))
|
||||||
((false == contains(includefile, "tr/")) && (false == contains(includefile, "tra/"))))
|
|
||||||
{
|
{
|
||||||
if (false == contains(includefile, "_ter.scm"))
|
if (false == contains(includefile, "_ter.scm"))
|
||||||
{
|
{
|
||||||
if (Global.ParserLogIncludes) {
|
if (Global.ParserLogIncludes)
|
||||||
|
{
|
||||||
// WriteLog("including: " + includefile);
|
// WriteLog("including: " + includefile);
|
||||||
}
|
}
|
||||||
mIncludeParser = std::make_shared<cParser>(includefile, buffer_FILE, mPath, LoadTraction, readParameters(*this));
|
mIncludeParser = std::make_shared<cParser>(includefile, buffer_FILE, mPath, LoadTraction, readParameters(*this));
|
||||||
mIncludeParser->allowRandomIncludes = allowRandomIncludes;
|
mIncludeParser->allowRandomIncludes = allowRandomIncludes;
|
||||||
mIncludeParser->autoclear(m_autoclear);
|
mIncludeParser->autoclear(m_autoclear);
|
||||||
if (mIncludeParser->mSize <= 0) {
|
if (mIncludeParser->mSize <= 0)
|
||||||
|
{
|
||||||
ErrorLog("Bad include: can't open file \"" + includefile + "\"");
|
ErrorLog("Bad include: can't open file \"" + includefile + "\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(true == Global.file_binary_terrain_state)
|
if (true == Global.file_binary_terrain_state)
|
||||||
{
|
{
|
||||||
WriteLog("SBT found, ignoring: " + includefile);
|
WriteLog("SBT found, ignoring: " + includefile);
|
||||||
readParameters(*this);
|
readParameters(*this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Global.ParserLogIncludes) {
|
if (Global.ParserLogIncludes)
|
||||||
|
{
|
||||||
WriteLog("including terrain: " + includefile);
|
WriteLog("including terrain: " + includefile);
|
||||||
}
|
}
|
||||||
mIncludeParser = std::make_shared<cParser>(includefile, buffer_FILE, mPath,
|
mIncludeParser = std::make_shared<cParser>(includefile, buffer_FILE, mPath, LoadTraction, readParameters(*this));
|
||||||
LoadTraction, readParameters(*this));
|
|
||||||
mIncludeParser->allowRandomIncludes = allowRandomIncludes;
|
mIncludeParser->allowRandomIncludes = allowRandomIncludes;
|
||||||
mIncludeParser->autoclear(m_autoclear);
|
mIncludeParser->autoclear(m_autoclear);
|
||||||
if (mIncludeParser->mSize <= 0)
|
if (mIncludeParser->mSize <= 0)
|
||||||
@@ -285,29 +309,31 @@ std::string cParser::readToken( bool ToLower, const char *Break ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
while( token != "end" ) {
|
{
|
||||||
token = readToken( true ); // minimize risk of case mismatch on comparison
|
while (token != "end")
|
||||||
}
|
{
|
||||||
}
|
token = readToken(true); // minimize risk of case mismatch on comparison
|
||||||
token = readToken(ToLower, Break);
|
}
|
||||||
}
|
}
|
||||||
else if( ( std::strcmp( Break, "\n\r" ) == 0 ) && ( token.compare( 0, 7, "include" ) == 0 ) ) {
|
token = readToken(ToLower, Break);
|
||||||
// HACK: if the parser reads full lines we expect this line to contain entire include directive, to make parsing easier
|
}
|
||||||
cParser includeparser( token.substr( 7 ) );
|
else if ((std::strcmp(Break, "\n\r") == 0) && (token.compare(0, 7, "include") == 0))
|
||||||
std::string includefile = allowRandomIncludes ? deserialize_random_set( includeparser ) : includeparser.readToken( ToLower ); // nazwa pliku
|
{
|
||||||
replace_slashes(includefile);
|
// HACK: if the parser reads full lines we expect this line to contain entire include directive, to make parsing easier
|
||||||
if ((true == LoadTraction) ||
|
cParser includeparser(token.substr(7));
|
||||||
((false == contains(includefile, "tr/")) && (false == contains(includefile, "tra/"))))
|
std::string includefile = allowRandomIncludes ? deserialize_random_set(includeparser) : includeparser.readToken(ToLower); // nazwa pliku
|
||||||
|
replace_slashes(includefile);
|
||||||
|
if ((true == LoadTraction) || ((false == contains(includefile, "tr/")) && (false == contains(includefile, "tra/"))))
|
||||||
{
|
{
|
||||||
if (false == contains(includefile, "_ter.scm"))
|
if (false == contains(includefile, "_ter.scm"))
|
||||||
{
|
{
|
||||||
if (Global.ParserLogIncludes) {
|
if (Global.ParserLogIncludes)
|
||||||
|
{
|
||||||
// WriteLog("including: " + includefile);
|
// WriteLog("including: " + includefile);
|
||||||
}
|
}
|
||||||
mIncludeParser = std::make_shared<cParser>(
|
mIncludeParser = std::make_shared<cParser>(includefile, buffer_FILE, mPath, LoadTraction, readParameters(includeparser));
|
||||||
includefile, buffer_FILE, mPath, LoadTraction, readParameters(includeparser));
|
|
||||||
mIncludeParser->allowRandomIncludes = allowRandomIncludes;
|
mIncludeParser->allowRandomIncludes = allowRandomIncludes;
|
||||||
mIncludeParser->autoclear(m_autoclear);
|
mIncludeParser->autoclear(m_autoclear);
|
||||||
if (mIncludeParser->mSize <= 0)
|
if (mIncludeParser->mSize <= 0)
|
||||||
@@ -324,52 +350,56 @@ std::string cParser::readToken( bool ToLower, const char *Break ) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Global.ParserLogIncludes) {
|
if (Global.ParserLogIncludes)
|
||||||
|
{
|
||||||
WriteLog("including terrain: " + includefile);
|
WriteLog("including terrain: " + includefile);
|
||||||
}
|
}
|
||||||
mIncludeParser =
|
mIncludeParser = std::make_shared<cParser>(includefile, buffer_FILE, mPath, LoadTraction, readParameters(includeparser));
|
||||||
std::make_shared<cParser>(includefile, buffer_FILE, mPath, LoadTraction,
|
|
||||||
readParameters(includeparser));
|
|
||||||
mIncludeParser->allowRandomIncludes = allowRandomIncludes;
|
mIncludeParser->allowRandomIncludes = allowRandomIncludes;
|
||||||
mIncludeParser->autoclear(m_autoclear);
|
mIncludeParser->autoclear(m_autoclear);
|
||||||
if (mIncludeParser->mSize <= 0)
|
if (mIncludeParser->mSize <= 0)
|
||||||
{
|
{
|
||||||
ErrorLog("Bad include: can't open file \"" + includefile + "\"");
|
ErrorLog("Bad include: can't open file \"" + includefile + "\"");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token = readToken( ToLower, Break );
|
token = readToken(ToLower, Break);
|
||||||
}
|
}
|
||||||
// all done
|
// all done
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> cParser::readParameters( cParser &Input ) {
|
std::vector<std::string> cParser::readParameters(cParser &Input)
|
||||||
|
{
|
||||||
|
|
||||||
std::vector<std::string> includeparameters;
|
std::vector<std::string> includeparameters;
|
||||||
std::string parameter = Input.readToken( false ); // w parametrach nie zmniejszamy
|
std::string parameter = Input.readToken(false); // w parametrach nie zmniejszamy
|
||||||
while( ( parameter.empty() == false )
|
while ((parameter.empty() == false) && (parameter != "end"))
|
||||||
&& ( parameter != "end" ) ) {
|
{
|
||||||
includeparameters.emplace_back( parameter );
|
includeparameters.emplace_back(parameter);
|
||||||
parameter = Input.readToken( false );
|
parameter = Input.readToken(false);
|
||||||
}
|
}
|
||||||
return includeparameters;
|
return includeparameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cParser::readQuotes(char const Quote) { // read the stream until specified char or stream end
|
std::string cParser::readQuotes(char const Quote)
|
||||||
std::string token = "";
|
{ // read the stream until specified char or stream end
|
||||||
char c { 0 };
|
std::string token = "";
|
||||||
|
char c{0};
|
||||||
bool escaped = false;
|
bool escaped = false;
|
||||||
while( mStream->peek() != EOF ) { // get all chars until the quote mark
|
while (mStream->peek() != EOF)
|
||||||
|
{ // get all chars until the quote mark
|
||||||
c = mStream->get();
|
c = mStream->get();
|
||||||
|
|
||||||
if (escaped) {
|
if (escaped)
|
||||||
|
{
|
||||||
escaped = false;
|
escaped = false;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
if (c == '\\') {
|
{
|
||||||
|
if (c == '\\')
|
||||||
|
{
|
||||||
escaped = true;
|
escaped = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -380,122 +410,153 @@ std::string cParser::readQuotes(char const Quote) { // read the stream until spe
|
|||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
++mLine; // update line counter
|
++mLine; // update line counter
|
||||||
token += c;
|
token += c;
|
||||||
}
|
}
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cParser::skipComment( std::string const &Endmark ) { // pobieranie znaków aż do znalezienia znacznika końca
|
void cParser::skipComment(std::string const &Endmark)
|
||||||
std::string input = "";
|
{ // pobieranie znaków aż do znalezienia znacznika końca
|
||||||
char c { 0 };
|
std::string input = "";
|
||||||
auto const endmarksize = Endmark.size();
|
char c{0};
|
||||||
while( mStream->peek() != EOF ) {
|
auto const endmarksize = Endmark.size();
|
||||||
// o ile nie koniec pliku
|
while (mStream->peek() != EOF)
|
||||||
c = mStream->get(); // pobranie znaku
|
{
|
||||||
if( c == '\n' ) {
|
// o ile nie koniec pliku
|
||||||
// update line counter
|
c = mStream->get(); // pobranie znaku
|
||||||
++mLine;
|
if (c == '\n')
|
||||||
}
|
{
|
||||||
input += c;
|
// update line counter
|
||||||
if( input == Endmark ) // szukanie znacznika końca
|
++mLine;
|
||||||
break;
|
}
|
||||||
if( input.size() >= endmarksize ) {
|
input += c;
|
||||||
// keep the read text short, to avoid pointless string re-allocations on longer comments
|
if (input == Endmark) // szukanie znacznika końca
|
||||||
input = input.substr( 1 );
|
break;
|
||||||
}
|
if (input.size() >= endmarksize)
|
||||||
}
|
{
|
||||||
return;
|
// keep the read text short, to avoid pointless string re-allocations on longer comments
|
||||||
|
input = input.substr(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cParser::findQuotes( std::string &String ) {
|
bool cParser::findQuotes(std::string &String)
|
||||||
|
{
|
||||||
|
|
||||||
if( String.back() == '\"' ) {
|
if (String.back() == '\"')
|
||||||
|
{
|
||||||
|
|
||||||
String.pop_back();
|
String.pop_back();
|
||||||
String += readQuotes();
|
String += readQuotes();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cParser::trimComments(std::string &String)
|
bool cParser::trimComments(std::string &String)
|
||||||
{
|
{
|
||||||
for (auto const &comment : mComments)
|
for (auto const &comment : mComments)
|
||||||
{
|
{
|
||||||
if( String.size() < comment.first.size() ) { continue; }
|
if (String.size() < comment.first.size())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (String.compare( String.size() - comment.first.size(), comment.first.size(), comment.first ) == 0)
|
if (String.compare(String.size() - comment.first.size(), comment.first.size(), comment.first) == 0)
|
||||||
{
|
{
|
||||||
skipComment(comment.second);
|
skipComment(comment.second);
|
||||||
String.resize(String.rfind(comment.first));
|
String.resize(String.rfind(comment.first));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cParser::injectString(const std::string &str)
|
void cParser::injectString(const std::string &str)
|
||||||
{
|
{
|
||||||
if (mIncludeParser) {
|
if (mIncludeParser)
|
||||||
|
{
|
||||||
mIncludeParser->injectString(str);
|
mIncludeParser->injectString(str);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
mIncludeParser = std::make_shared<cParser>( str, buffer_TEXT, "", LoadTraction, std::vector<std::string>(), allowRandomIncludes );
|
{
|
||||||
mIncludeParser->autoclear( m_autoclear );
|
mIncludeParser = std::make_shared<cParser>(str, buffer_TEXT, "", LoadTraction, std::vector<std::string>(), allowRandomIncludes);
|
||||||
|
mIncludeParser->autoclear(m_autoclear);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cParser::getProgress() const
|
int cParser::getProgress() const
|
||||||
{
|
{
|
||||||
return static_cast<int>( mStream->rdbuf()->pubseekoff(0, std::ios_base::cur) * 100 / mSize );
|
return static_cast<int>(mStream->rdbuf()->pubseekoff(0, std::ios_base::cur) * 100 / mSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cParser::getFullProgress() const {
|
int cParser::getFullProgress() const
|
||||||
|
{
|
||||||
|
|
||||||
int progress = getProgress();
|
int progress = getProgress();
|
||||||
if( mIncludeParser ) return progress + ( ( 100 - progress )*( mIncludeParser->getProgress() ) / 100 );
|
if (mIncludeParser)
|
||||||
else return progress;
|
return progress + ((100 - progress) * (mIncludeParser->getProgress()) / 100);
|
||||||
|
else
|
||||||
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t cParser::countTokens( std::string const &Stream, std::string Path ) {
|
std::size_t cParser::countTokens(std::string const &Stream, std::string Path)
|
||||||
|
{
|
||||||
|
|
||||||
return cParser( Stream, buffer_FILE, Path ).count();
|
return cParser(Stream, buffer_FILE, Path).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t cParser::count() {
|
std::size_t cParser::count()
|
||||||
|
{
|
||||||
|
|
||||||
std::string token;
|
std::string token;
|
||||||
size_t count { 0 };
|
size_t count{0};
|
||||||
do {
|
do
|
||||||
token = "";
|
{
|
||||||
token = readToken( false );
|
token = "";
|
||||||
++count;
|
token = readToken(false);
|
||||||
} while( false == token.empty() );
|
++count;
|
||||||
|
} while (false == token.empty());
|
||||||
|
|
||||||
return count - 1;
|
return count - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cParser::addCommentStyle( std::string const &Commentstart, std::string const &Commentend ) {
|
void cParser::addCommentStyle(std::string const &Commentstart, std::string const &Commentend)
|
||||||
|
{
|
||||||
|
|
||||||
mComments.insert( commentmap::value_type(Commentstart, Commentend) );
|
mComments.insert(commentmap::value_type(Commentstart, Commentend));
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns name of currently open file, or empty string for text type stream
|
// returns name of currently open file, or empty string for text type stream
|
||||||
std::string
|
std::string cParser::Name() const
|
||||||
cParser::Name() const {
|
{
|
||||||
|
|
||||||
if( mIncludeParser ) { return mIncludeParser->Name(); }
|
if (mIncludeParser)
|
||||||
else { return mPath + mFile; }
|
{
|
||||||
|
return mIncludeParser->Name();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return mPath + mFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns number of currently processed line
|
// returns number of currently processed line
|
||||||
std::size_t
|
std::size_t cParser::Line() const
|
||||||
cParser::Line() const {
|
{
|
||||||
|
|
||||||
if( mIncludeParser ) { return mIncludeParser->Line(); }
|
if (mIncludeParser)
|
||||||
else { return mLine; }
|
{
|
||||||
|
return mIncludeParser->Line();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return mLine;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cParser::LineMain() const {
|
int cParser::LineMain() const
|
||||||
|
{
|
||||||
return mIncludeParser ? -1 : mLine;
|
return mIncludeParser ? -1 : mLine;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ bool string_starts_with(const std::string &string, const std::string &begin)
|
|||||||
return string.compare(0, begin.length(), begin) == 0;
|
return string.compare(0, begin.length(), begin) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const fractionlabels[] = {" ", u8"¹", u8"²", u8"³", u8"⁴", u8"⁵", u8"⁶", u8"⁷", u8"⁸", u8"⁹"};
|
std::string const fractionlabels[] = {" ", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"};
|
||||||
|
|
||||||
std::string to_minutes_str(float const Minutes, bool const Leadingzero, int const Width)
|
std::string to_minutes_str(float const Minutes, bool const Leadingzero, int const Width)
|
||||||
{
|
{
|
||||||
@@ -376,8 +376,8 @@ void win1250_to_ascii(std::string &Input)
|
|||||||
|
|
||||||
std::string win1250_to_utf8(const std::string &Input)
|
std::string win1250_to_utf8(const std::string &Input)
|
||||||
{
|
{
|
||||||
std::unordered_map<char, std::string> const charmap{{165, u8"Ą"}, {198, u8"Ć"}, {202, u8"Ę"}, {163, u8"Ł"}, {209, u8"Ń"}, {211, u8"Ó"}, {140, u8"Ś"}, {143, u8"Ź"}, {175, u8"Ż"},
|
std::unordered_map<char, std::string> const charmap{{165, "Ą"}, {198, "Ć"}, {202, "Ę"}, {163, "Ł"}, {209, "Ń"}, {211, "Ó"}, {140, "Ś"}, {143, "Ź"}, {175, "Ż"},
|
||||||
{185, u8"ą"}, {230, u8"ć"}, {234, u8"ę"}, {179, u8"ł"}, {241, u8"ń"}, {243, u8"ó"}, {156, u8"ś"}, {159, u8"ź"}, {191, u8"ż"}};
|
{185, "ą"}, {230, "ć"}, {234, "ę"}, {179, "ł"}, {241, "ń"}, {243, "ó"}, {156, "ś"}, {159, "ź"}, {191, "ż"}};
|
||||||
std::string output;
|
std::string output;
|
||||||
std::unordered_map<char, std::string>::const_iterator lookup;
|
std::unordered_map<char, std::string>::const_iterator lookup;
|
||||||
for (auto &input : Input)
|
for (auto &input : Input)
|
||||||
|
|||||||
@@ -7,10 +7,9 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
trainingcard_panel::trainingcard_panel()
|
trainingcard_panel::trainingcard_panel() : ui_panel("Raport szkolenia", false)
|
||||||
: ui_panel("Raport szkolenia", false)
|
|
||||||
{
|
{
|
||||||
//size = {400, 500};
|
// size = {400, 500};
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,21 +57,25 @@ void trainingcard_panel::save_thread_func()
|
|||||||
std::fstream input("report_template.html", std::ios_base::in | std::ios_base::binary);
|
std::fstream input("report_template.html", std::ios_base::in | std::ios_base::binary);
|
||||||
|
|
||||||
std::string in_line;
|
std::string in_line;
|
||||||
while (std::getline(input, in_line)) {
|
while (std::getline(input, in_line))
|
||||||
|
{
|
||||||
const std::string magic("{{CONTENT}}");
|
const std::string magic("{{CONTENT}}");
|
||||||
if (in_line.compare(0, magic.size(), magic) == 0) {
|
if (in_line.compare(0, magic.size(), magic) == 0)
|
||||||
|
{
|
||||||
temp << "<div><b>Miejsce: </b>" << (std::string(place.c_str())) << "</div><br />" << std::endl;
|
temp << "<div><b>Miejsce: </b>" << (std::string(place.c_str())) << "</div><br />" << std::endl;
|
||||||
temp << "<div><b>Data: </b>" << (date) << "</div><br />" << std::endl;
|
temp << "<div><b>Data: </b>" << (date) << "</div><br />" << std::endl;
|
||||||
temp << "<div><b>Czas: </b>" << (from) << " - " << (to) << "</div><br />" << std::endl;
|
temp << "<div><b>Czas: </b>" << (from) << " - " << (to) << "</div><br />" << std::endl;
|
||||||
temp << "<div><b>Imię (imiona) i nazwisko szkolonego: </b>" << (trainee_name) << "</div><br />" << std::endl;
|
temp << "<div><b>Imię (imiona) i nazwisko szkolonego: </b>" << (trainee_name) << "</div><br />" << std::endl;
|
||||||
temp << "<div><b>Data urodzenia: </b>" << (trainee_birthdate) << "</div><br />" << std::endl;
|
temp << "<div><b>Data urodzenia: </b>" << (trainee_birthdate) << "</div><br />" << std::endl;
|
||||||
temp << "<div><b>Firma: </b>" << (trainee_company) << "</div><br />" << std::endl;
|
temp << "<div><b>Firma: </b>" << (trainee_company) << "</div><br />" << std::endl;
|
||||||
temp << "<div><b>Imię i nazwisko instruktora: </b>" << (instructor_name) << "</div><br />" << std::endl;
|
temp << "<div><b>Imię i nazwisko instruktora: </b>" << (instructor_name) << "</div><br />" << std::endl;
|
||||||
temp << "<div><b>Odcinek trasy: </b>" << (track_segment) << "</div><br />" << std::endl;
|
temp << "<div><b>Odcinek trasy: </b>" << (track_segment) << "</div><br />" << std::endl;
|
||||||
if (distance > 0.0f)
|
if (distance > 0.0f)
|
||||||
temp << "<div><b>Przebyta odległość: </b>" << std::round(distance) << " km</div><br />" << std::endl;
|
temp << "<div><b>Przebyta odległość: </b>" << std::round(distance) << " km</div><br />" << std::endl;
|
||||||
temp << "<div><b>Uwagi: </b><br />" << (remarks) << "</div>" << std::endl;
|
temp << "<div><b>Uwagi: </b><br />" << (remarks) << "</div>" << std::endl;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
temp << in_line;
|
temp << in_line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,37 +88,42 @@ void trainingcard_panel::save_thread_func()
|
|||||||
|
|
||||||
void trainingcard_panel::render_contents()
|
void trainingcard_panel::render_contents()
|
||||||
{
|
{
|
||||||
if (ImGui::BeginPopupModal("Zapisywanie danych")) {
|
if (ImGui::BeginPopupModal("Zapisywanie danych"))
|
||||||
|
{
|
||||||
ImGui::SetWindowSize(ImVec2(-1, -1));
|
ImGui::SetWindowSize(ImVec2(-1, -1));
|
||||||
int s = state.load();
|
int s = state.load();
|
||||||
|
|
||||||
if (s == 1) {
|
if (s == 1)
|
||||||
|
{
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s < 1) {
|
if (s < 1)
|
||||||
|
{
|
||||||
if (s == 0)
|
if (s == 0)
|
||||||
ImGui::TextUnformatted("Error occured please contact with administrator!");
|
ImGui::TextUnformatted("Error occured please contact with administrator!");
|
||||||
if (s == -1)
|
if (s == -1)
|
||||||
ImGui::TextUnformatted("The recording of the training has not been archived, please do not start the next training before manually archiving the file!");
|
ImGui::TextUnformatted("The recording of the training has not been archived, please do not start the next training before manually archiving the file!");
|
||||||
|
|
||||||
if (ImGui::Button("OK")) {
|
if (ImGui::Button("OK"))
|
||||||
|
{
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s == 2)
|
if (s == 2)
|
||||||
ImGui::TextUnformatted(u8"Proszę czekać, trwa archiwizacja nagrania...");
|
ImGui::TextUnformatted("Proszę czekać, trwa archiwizacja nagrania...");
|
||||||
|
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start_time_wall) {
|
if (start_time_wall)
|
||||||
|
{
|
||||||
std::tm *tm = std::localtime(&(*start_time_wall));
|
std::tm *tm = std::localtime(&(*start_time_wall));
|
||||||
std::string rep = u8"Czas rozpoczęcia: " + std::to_string(tm->tm_year + 1900) + "-" + std::to_string(tm->tm_mon + 1) + "-" + std::to_string(tm->tm_mday)
|
std::string rep = "Czas rozpoczęcia: " + std::to_string(tm->tm_year + 1900) + "-" + std::to_string(tm->tm_mon + 1) + "-" + std::to_string(tm->tm_mday) + " " + std::to_string(tm->tm_hour) +
|
||||||
+ " " + std::to_string(tm->tm_hour) + ":" + std::to_string(tm->tm_min);
|
":" + std::to_string(tm->tm_min);
|
||||||
ImGui::TextUnformatted(rep.c_str());
|
ImGui::TextUnformatted(rep.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,22 +154,27 @@ void trainingcard_panel::render_contents()
|
|||||||
ImGui::TextUnformatted("Uwagi");
|
ImGui::TextUnformatted("Uwagi");
|
||||||
ImGui::InputTextMultiline("##remarks", &remarks[0], remarks.size(), ImVec2(-1.0f, 200.0f));
|
ImGui::InputTextMultiline("##remarks", &remarks[0], remarks.size(), ImVec2(-1.0f, 200.0f));
|
||||||
|
|
||||||
if (!start_time_wall) {
|
if (!start_time_wall)
|
||||||
if (ImGui::Button("Rozpocznij szkolenie")) {
|
{
|
||||||
|
if (ImGui::Button("Rozpocznij szkolenie"))
|
||||||
|
{
|
||||||
start_time_wall = std::time(nullptr);
|
start_time_wall = std::time(nullptr);
|
||||||
std::tm *tm = std::localtime(&(*start_time_wall));
|
std::tm *tm = std::localtime(&(*start_time_wall));
|
||||||
recording_timestamp = std::to_string(tm->tm_year + 1900) + std::to_string(tm->tm_mon + 1) + std::to_string(tm->tm_mday)
|
recording_timestamp = std::to_string(tm->tm_year + 1900) + std::to_string(tm->tm_mon + 1) + std::to_string(tm->tm_mday) + std::to_string(tm->tm_hour) + std::to_string(tm->tm_min) + "_" +
|
||||||
+ std::to_string(tm->tm_hour) + std::to_string(tm->tm_min) + "_" + std::string(trainee_name.c_str()) + "_" + std::string(instructor_name.c_str());
|
std::string(trainee_name.c_str()) + "_" + std::string(instructor_name.c_str());
|
||||||
|
|
||||||
int ret = StartRecording();
|
int ret = StartRecording();
|
||||||
if (ret != 1) {
|
if (ret != 1)
|
||||||
|
{
|
||||||
state.store(ret);
|
state.store(ret);
|
||||||
ImGui::OpenPopup("Zapisywanie danych");
|
ImGui::OpenPopup("Zapisywanie danych");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
if (ImGui::Button(u8"Zakończ szkolenie")) {
|
{
|
||||||
|
if (ImGui::Button("Zakończ szkolenie"))
|
||||||
|
{
|
||||||
state.store(2);
|
state.store(2);
|
||||||
if (simulation::Trains.sequence().size() > 0)
|
if (simulation::Trains.sequence().size() > 0)
|
||||||
distance = simulation::Trains.sequence()[0]->Dynamic()->MoverParameters->DistCounter;
|
distance = simulation::Trains.sequence()[0]->Dynamic()->MoverParameters->DistCounter;
|
||||||
|
|||||||
@@ -5,27 +5,26 @@
|
|||||||
#include "Driver.h"
|
#include "Driver.h"
|
||||||
#include "Train.h"
|
#include "Train.h"
|
||||||
|
|
||||||
ui::vehicleparams_panel::vehicleparams_panel(const std::string &vehicle)
|
ui::vehicleparams_panel::vehicleparams_panel(const std::string &vehicle) : ui_panel(std::string(STR("Vehicle parameters")) + ": " + vehicle, false), m_vehicle_name(vehicle)
|
||||||
: ui_panel(std::string(STR("Vehicle parameters")) + ": " + vehicle, false), m_vehicle_name(vehicle)
|
|
||||||
{
|
{
|
||||||
vehicle_mini = GfxRenderer->Fetch_Texture("vehicle_mini");
|
vehicle_mini = GfxRenderer->Fetch_Texture("vehicle_mini");
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_window_callback(ImGuiSizeCallbackData *data) {
|
void screen_window_callback(ImGuiSizeCallbackData *data)
|
||||||
auto config = static_cast<const global_settings::pythonviewport_config*>(data->UserData);
|
{
|
||||||
|
auto config = static_cast<const global_settings::pythonviewport_config *>(data->UserData);
|
||||||
data->DesiredSize.y = data->DesiredSize.x * (float)config->size.y / (float)config->size.x;
|
data->DesiredSize.y = data->DesiredSize.x * (float)config->size.y / (float)config->size.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui::vehicleparams_panel::draw_infobutton(const char *str, ImVec2 pos, const ImVec4 color)
|
void ui::vehicleparams_panel::draw_infobutton(const char *str, ImVec2 pos, const ImVec4 color)
|
||||||
{
|
{
|
||||||
if (pos.x != -1.0f) {
|
if (pos.x != -1.0f)
|
||||||
|
{
|
||||||
ImVec2 window_size = ImGui::GetWindowSize();
|
ImVec2 window_size = ImGui::GetWindowSize();
|
||||||
|
|
||||||
ImGuiStyle &style = ImGui::GetStyle();
|
ImGuiStyle &style = ImGui::GetStyle();
|
||||||
ImVec2 text_size = ImGui::CalcTextSize(str);
|
ImVec2 text_size = ImGui::CalcTextSize(str);
|
||||||
ImVec2 button_size = ImVec2(
|
ImVec2 button_size = ImVec2(text_size.x + style.FramePadding.x * 2.0f, text_size.y + style.FramePadding.y * 2.0f);
|
||||||
text_size.x + style.FramePadding.x * 2.0f,
|
|
||||||
text_size.y + style.FramePadding.y * 2.0f);
|
|
||||||
|
|
||||||
pos.x = pos.x * window_size.x / 512.0f - button_size.x / 2.0f;
|
pos.x = pos.x * window_size.x / 512.0f - button_size.x / 2.0f;
|
||||||
pos.y = pos.y * window_size.y / 118.0f - button_size.y / 2.0f;
|
pos.y = pos.y * window_size.y / 118.0f - button_size.y / 2.0f;
|
||||||
@@ -52,7 +51,7 @@ void ui::vehicleparams_panel::draw_mini(const TMoverParameters &mover)
|
|||||||
if (vehicle_mini == null_handle)
|
if (vehicle_mini == null_handle)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto &tex = GfxRenderer->Texture(vehicle_mini);
|
auto &tex = GfxRenderer->Texture(vehicle_mini);
|
||||||
tex.create();
|
tex.create();
|
||||||
|
|
||||||
ImVec2 size = ImGui::GetContentRegionAvail();
|
ImVec2 size = ImGui::GetContentRegionAvail();
|
||||||
@@ -61,12 +60,12 @@ void ui::vehicleparams_panel::draw_mini(const TMoverParameters &mover)
|
|||||||
|
|
||||||
if (ImGui::BeginChild("mini", ImVec2(x, y)))
|
if (ImGui::BeginChild("mini", ImVec2(x, y)))
|
||||||
{
|
{
|
||||||
ImGui::Image(reinterpret_cast<void*>(tex.get_id()), ImVec2(x, y), ImVec2(0, 1), ImVec2(1, 0));
|
ImGui::Image(reinterpret_cast<void *>(tex.get_id()), ImVec2(x, y), ImVec2(0, 1), ImVec2(1, 0));
|
||||||
|
|
||||||
if (mover.Pantographs[end::rear].is_active)
|
if (mover.Pantographs[end::rear].is_active)
|
||||||
draw_infobutton(u8"╨╨╨", ImVec2(126, 10));
|
draw_infobutton("╨╨╨", ImVec2(126, 10));
|
||||||
if (mover.Pantographs[end::front].is_active)
|
if (mover.Pantographs[end::front].is_active)
|
||||||
draw_infobutton(u8"╨╨╨", ImVec2(290, 10));
|
draw_infobutton("╨╨╨", ImVec2(290, 10));
|
||||||
|
|
||||||
if (mover.Battery)
|
if (mover.Battery)
|
||||||
draw_infobutton(STR_C("bat."), ImVec2(120, 55));
|
draw_infobutton(STR_C("bat."), ImVec2(120, 55));
|
||||||
@@ -99,24 +98,28 @@ void ui::vehicleparams_panel::draw_mini(const TMoverParameters &mover)
|
|||||||
void ui::vehicleparams_panel::render_contents()
|
void ui::vehicleparams_panel::render_contents()
|
||||||
{
|
{
|
||||||
TDynamicObject *vehicle_ptr = simulation::Vehicles.find(m_vehicle_name);
|
TDynamicObject *vehicle_ptr = simulation::Vehicles.find(m_vehicle_name);
|
||||||
if (!vehicle_ptr) {
|
if (!vehicle_ptr)
|
||||||
|
{
|
||||||
is_open = false;
|
is_open = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TTrain *train_ptr = simulation::Trains.find(m_vehicle_name);
|
TTrain *train_ptr = simulation::Trains.find(m_vehicle_name);
|
||||||
if (train_ptr) {
|
if (train_ptr)
|
||||||
|
{
|
||||||
const TTrain::screenentry_sequence &screens = train_ptr->get_screens();
|
const TTrain::screenentry_sequence &screens = train_ptr->get_screens();
|
||||||
|
|
||||||
for (const auto &viewport : Global.python_viewports) {
|
for (const auto &viewport : Global.python_viewports)
|
||||||
for (auto const &entry : screens) {
|
{
|
||||||
if (entry.script != viewport.surface)
|
for (auto const &entry : screens)
|
||||||
|
{
|
||||||
|
if (entry.script != viewport.surface)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::string window_name = STR("Screen") + "##" + viewport.surface;
|
std::string window_name = STR("Screen") + "##" + viewport.surface;
|
||||||
ImGui::SetNextWindowSizeConstraints(ImVec2(200, 200), ImVec2(2500, 2500), screen_window_callback,
|
ImGui::SetNextWindowSizeConstraints(ImVec2(200, 200), ImVec2(2500, 2500), screen_window_callback, const_cast<global_settings::pythonviewport_config *>(&viewport));
|
||||||
const_cast<global_settings::pythonviewport_config*>(&viewport));
|
if (ImGui::Begin(window_name.c_str()))
|
||||||
if (ImGui::Begin(window_name.c_str())) {
|
{
|
||||||
float aspect = (float)viewport.size.y / viewport.size.x;
|
float aspect = (float)viewport.size.y / viewport.size.x;
|
||||||
|
|
||||||
glm::mat3 proj = glm::translate(glm::scale(glm::mat3(), 1.0f / viewport.scale), viewport.offset);
|
glm::mat3 proj = glm::translate(glm::scale(glm::mat3(), 1.0f / viewport.scale), viewport.offset);
|
||||||
@@ -126,7 +129,7 @@ void ui::vehicleparams_panel::render_contents()
|
|||||||
|
|
||||||
ImVec2 size = ImGui::GetContentRegionAvail();
|
ImVec2 size = ImGui::GetContentRegionAvail();
|
||||||
|
|
||||||
ImGui::Image(reinterpret_cast<void*>(entry.rt->shared_tex), size, ImVec2(uv0.x, uv0.y), ImVec2(uv1.x, uv1.y));
|
ImGui::Image(reinterpret_cast<void *>(entry.rt->shared_tex), size, ImVec2(uv0.x, uv0.y), ImVec2(uv1.x, uv1.y));
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
@@ -139,178 +142,137 @@ void ui::vehicleparams_panel::render_contents()
|
|||||||
std::vector<text_line> lines;
|
std::vector<text_line> lines;
|
||||||
std::array<char, 1024> buffer;
|
std::array<char, 1024> buffer;
|
||||||
|
|
||||||
auto const isdieselenginepowered { ( mover.EngineType == TEngineType::DieselElectric ) || ( mover.EngineType == TEngineType::DieselEngine ) };
|
auto const isdieselenginepowered{(mover.EngineType == TEngineType::DieselElectric) || (mover.EngineType == TEngineType::DieselEngine)};
|
||||||
auto const isdieselinshuntmode { mover.ShuntMode && mover.EngineType == TEngineType::DieselElectric };
|
auto const isdieselinshuntmode{mover.ShuntMode && mover.EngineType == TEngineType::DieselElectric};
|
||||||
|
|
||||||
std::snprintf(
|
std::snprintf(buffer.data(), buffer.size(), STR_C("Devices: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nPower transfers: %.0f@%.0f%s%s%s%.0f@%.0f"),
|
||||||
buffer.data(), buffer.size(),
|
// devices
|
||||||
STR_C("Devices: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nPower transfers: %.0f@%.0f%s%s%s%.0f@%.0f"),
|
(mover.Battery ? 'B' : '.'), (mover.Mains ? 'M' : '.'), (mover.FuseFlag ? '!' : '.'), (mover.Pantographs[end::rear].is_active ? (mover.PantRearVolt > 0.0 ? 'O' : 'o') : '.'),
|
||||||
// devices
|
(mover.Pantographs[end::front].is_active ? (mover.PantFrontVolt > 0.0 ? 'P' : 'p') : '.'), (mover.PantPressLockActive ? '!' : (mover.PantPressSwitchActive ? '*' : '.')),
|
||||||
( mover.Battery ? 'B' : '.' ),
|
(mover.WaterPump.is_active ? 'W' : (false == mover.WaterPump.breaker ? '-' : (mover.WaterPump.is_enabled ? 'w' : '.'))),
|
||||||
( mover.Mains ? 'M' : '.' ),
|
(true == mover.WaterHeater.is_damaged ? '!' : (mover.WaterHeater.is_active ? 'H' : (false == mover.WaterHeater.breaker ? '-' : (mover.WaterHeater.is_enabled ? 'h' : '.')))),
|
||||||
( mover.FuseFlag ? '!' : '.' ),
|
(mover.FuelPump.is_active ? 'F' : (mover.FuelPump.is_enabled ? 'f' : '.')), (mover.OilPump.is_active ? 'O' : (mover.OilPump.is_enabled ? 'o' : '.')),
|
||||||
( mover.Pantographs[end::rear].is_active ? ( mover.PantRearVolt > 0.0 ? 'O' : 'o' ) : '.' ),
|
(false == mover.ConverterAllowLocal ? '-' : (mover.ConverterAllow ? (mover.ConverterFlag ? 'X' : 'x') : '.')), (mover.ConvOvldFlag ? '!' : '.'),
|
||||||
( mover.Pantographs[end::front].is_active ? ( mover.PantFrontVolt > 0.0 ? 'P' : 'p' ) : '.' ),
|
(mover.CompressorFlag ? 'C' : (false == mover.CompressorAllowLocal ? '-' : ((mover.CompressorAllow || mover.CompressorStart == start_t::automatic) ? 'c' : '.'))),
|
||||||
( mover.PantPressLockActive ? '!' : ( mover.PantPressSwitchActive ? '*' : '.' ) ),
|
(mover.CompressorGovernorLock ? '!' : '.'), "", std::string(isdieselenginepowered ? STR(" oil pressure: ") + to_string(mover.OilPump.pressure, 2) : "").c_str(),
|
||||||
( mover.WaterPump.is_active ? 'W' : ( false == mover.WaterPump.breaker ? '-' : ( mover.WaterPump.is_enabled ? 'w' : '.' ) ) ),
|
// power transfers
|
||||||
( true == mover.WaterHeater.is_damaged ? '!' : ( mover.WaterHeater.is_active ? 'H' : ( false == mover.WaterHeater.breaker ? '-' : ( mover.WaterHeater.is_enabled ? 'h' : '.' ) ) ) ),
|
mover.Couplers[end::front].power_high.voltage, mover.Couplers[end::front].power_high.current, std::string(mover.Couplers[end::front].power_high.is_local ? "" : "-").c_str(),
|
||||||
( mover.FuelPump.is_active ? 'F' : ( mover.FuelPump.is_enabled ? 'f' : '.' ) ),
|
std::string(vehicle.DirectionGet() ? ":<<:" : ":>>:").c_str(), std::string(mover.Couplers[end::rear].power_high.is_local ? "" : "-").c_str(),
|
||||||
( mover.OilPump.is_active ? 'O' : ( mover.OilPump.is_enabled ? 'o' : '.' ) ),
|
mover.Couplers[end::rear].power_high.voltage, mover.Couplers[end::rear].power_high.current);
|
||||||
( false == mover.ConverterAllowLocal ? '-' : ( mover.ConverterAllow ? ( mover.ConverterFlag ? 'X' : 'x' ) : '.' ) ),
|
|
||||||
( mover.ConvOvldFlag ? '!' : '.' ),
|
|
||||||
( mover.CompressorFlag ? 'C' : ( false == mover.CompressorAllowLocal ? '-' : ( ( mover.CompressorAllow || mover.CompressorStart == start_t::automatic ) ? 'c' : '.' ) ) ),
|
|
||||||
( mover.CompressorGovernorLock ? '!' : '.' ),
|
|
||||||
"",
|
|
||||||
std::string( isdieselenginepowered ? STR(" oil pressure: ") + to_string( mover.OilPump.pressure, 2 ) : "" ).c_str(),
|
|
||||||
// power transfers
|
|
||||||
mover.Couplers[ end::front ].power_high.voltage,
|
|
||||||
mover.Couplers[ end::front ].power_high.current,
|
|
||||||
std::string( mover.Couplers[ end::front ].power_high.is_local ? "" : "-" ).c_str(),
|
|
||||||
std::string( vehicle.DirectionGet() ? ":<<:" : ":>>:" ).c_str(),
|
|
||||||
std::string( mover.Couplers[ end::rear ].power_high.is_local ? "" : "-" ).c_str(),
|
|
||||||
mover.Couplers[ end::rear ].power_high.voltage,
|
|
||||||
mover.Couplers[ end::rear ].power_high.current );
|
|
||||||
|
|
||||||
ImGui::TextUnformatted(buffer.data());
|
ImGui::TextUnformatted(buffer.data());
|
||||||
|
|
||||||
std::snprintf(
|
std::snprintf(buffer.data(), buffer.size(),
|
||||||
buffer.data(), buffer.size(),
|
STR_C("Controllers:\n master: %d(%d), secondary: %s\nEngine output: %.1f, current: %.0f\nRevolutions:\n engine: %.0f, motors: %.0f\n engine fans: %.0f, motor fans: %.0f+%.0f, "
|
||||||
STR_C("Controllers:\n master: %d(%d), secondary: %s\nEngine output: %.1f, current: %.0f\nRevolutions:\n engine: %.0f, motors: %.0f\n engine fans: %.0f, motor fans: %.0f+%.0f, cooling fans: %.0f+%.0f"),
|
"cooling fans: %.0f+%.0f"),
|
||||||
// controllers
|
// controllers
|
||||||
mover.MainCtrlPos,
|
mover.MainCtrlPos, mover.MainCtrlActualPos,
|
||||||
mover.MainCtrlActualPos,
|
std::string(isdieselinshuntmode ? to_string(mover.AnPos, 2) + STR(" (shunt mode)") : std::to_string(mover.ScndCtrlPos) + "(" + std::to_string(mover.ScndCtrlActualPos) + ")").c_str(),
|
||||||
std::string( isdieselinshuntmode ? to_string( mover.AnPos, 2 ) + STR(" (shunt mode)") : std::to_string( mover.ScndCtrlPos ) + "(" + std::to_string( mover.ScndCtrlActualPos ) + ")" ).c_str(),
|
// engine
|
||||||
// engine
|
mover.EnginePower, std::abs(mover.TrainType == dt_EZT ? mover.ShowCurrent(0) : mover.Im),
|
||||||
mover.EnginePower,
|
// revolutions
|
||||||
std::abs( mover.TrainType == dt_EZT ? mover.ShowCurrent( 0 ) : mover.Im ),
|
std::abs(mover.enrot) * 60, std::abs(mover.nrot) * mover.Transmision.Ratio * 60, mover.RventRot * 60, std::abs(mover.MotorBlowers[end::front].revolutions),
|
||||||
// revolutions
|
std::abs(mover.MotorBlowers[end::rear].revolutions), mover.dizel_heat.rpmw, mover.dizel_heat.rpmw2);
|
||||||
std::abs( mover.enrot ) * 60,
|
|
||||||
std::abs( mover.nrot ) * mover.Transmision.Ratio * 60,
|
|
||||||
mover.RventRot * 60,
|
|
||||||
std::abs( mover.MotorBlowers[end::front].revolutions ),
|
|
||||||
std::abs( mover.MotorBlowers[end::rear].revolutions ),
|
|
||||||
mover.dizel_heat.rpmw,
|
|
||||||
mover.dizel_heat.rpmw2 );
|
|
||||||
|
|
||||||
ImGui::TextUnformatted(buffer.data());
|
ImGui::TextUnformatted(buffer.data());
|
||||||
|
|
||||||
if( isdieselenginepowered ) {
|
if (isdieselenginepowered)
|
||||||
std::snprintf(
|
{
|
||||||
buffer.data(), buffer.size(),
|
std::snprintf(buffer.data(), buffer.size(), STR_C("\nTemperatures:\n engine: %.2f, oil: %.2f, water: %.2f%c%.2f"), mover.dizel_heat.Ts, mover.dizel_heat.To, mover.dizel_heat.temperatura1,
|
||||||
STR_C("\nTemperatures:\n engine: %.2f, oil: %.2f, water: %.2f%c%.2f"),
|
(mover.WaterCircuitsLink ? '-' : '|'), mover.dizel_heat.temperatura2);
|
||||||
mover.dizel_heat.Ts,
|
|
||||||
mover.dizel_heat.To,
|
|
||||||
mover.dizel_heat.temperatura1,
|
|
||||||
( mover.WaterCircuitsLink ? '-' : '|' ),
|
|
||||||
mover.dizel_heat.temperatura2 );
|
|
||||||
ImGui::TextUnformatted(buffer.data());
|
ImGui::TextUnformatted(buffer.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string brakedelay;
|
std::string brakedelay;
|
||||||
{
|
{
|
||||||
std::vector<std::pair<int, std::string>> delays {
|
std::vector<std::pair<int, std::string>> delays{{bdelay_G, "G"}, {bdelay_P, "P"}, {bdelay_R, "R"}, {bdelay_M, "+Mg"}};
|
||||||
{ bdelay_G, "G" },
|
|
||||||
{ bdelay_P, "P" },
|
|
||||||
{ bdelay_R, "R" },
|
|
||||||
{ bdelay_M, "+Mg" } };
|
|
||||||
|
|
||||||
for( auto const &delay : delays ) {
|
for (auto const &delay : delays)
|
||||||
if( ( mover.BrakeDelayFlag & delay.first ) == delay.first ) {
|
{
|
||||||
|
if ((mover.BrakeDelayFlag & delay.first) == delay.first)
|
||||||
|
{
|
||||||
brakedelay += delay.second;
|
brakedelay += delay.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::snprintf(
|
std::snprintf(buffer.data(), buffer.size(),
|
||||||
buffer.data(), buffer.size(),
|
STR_C("Brakes:\n train: %.2f, independent: %.2f, mode: %d, delay: %s, load flag: %d\nBrake cylinder pressures:\n train: %.2f, independent: %.2f, status: 0x%.2x\nPipe pressures:\n "
|
||||||
STR_C("Brakes:\n train: %.2f, independent: %.2f, mode: %d, delay: %s, load flag: %d\nBrake cylinder pressures:\n train: %.2f, independent: %.2f, status: 0x%.2x\nPipe pressures:\n brake: %.2f (hat: %.2f), main: %.2f, control: %.2f\nTank pressures:\n auxiliary: %.2f, main: %.2f, control: %.2f"),
|
"brake: %.2f (hat: %.2f), main: %.2f, control: %.2f\nTank pressures:\n auxiliary: %.2f, main: %.2f, control: %.2f"),
|
||||||
// brakes
|
// brakes
|
||||||
mover.fBrakeCtrlPos,
|
mover.fBrakeCtrlPos, mover.LocalBrakePosA, mover.BrakeOpModeFlag, brakedelay.c_str(), mover.LoadFlag,
|
||||||
mover.LocalBrakePosA,
|
// cylinders
|
||||||
mover.BrakeOpModeFlag,
|
mover.BrakePress, mover.LocBrakePress, mover.Hamulec->GetBrakeStatus(),
|
||||||
brakedelay.c_str(),
|
// pipes
|
||||||
mover.LoadFlag,
|
mover.PipePress, mover.BrakeCtrlPos2, mover.ScndPipePress, mover.CntrlPipePress,
|
||||||
// cylinders
|
// tanks
|
||||||
mover.BrakePress,
|
mover.Hamulec->GetBRP(), mover.Compressor, mover.Hamulec->GetCRP());
|
||||||
mover.LocBrakePress,
|
|
||||||
mover.Hamulec->GetBrakeStatus(),
|
|
||||||
// pipes
|
|
||||||
mover.PipePress,
|
|
||||||
mover.BrakeCtrlPos2,
|
|
||||||
mover.ScndPipePress,
|
|
||||||
mover.CntrlPipePress,
|
|
||||||
// tanks
|
|
||||||
mover.Hamulec->GetBRP(),
|
|
||||||
mover.Compressor,
|
|
||||||
mover.Hamulec->GetCRP() );
|
|
||||||
|
|
||||||
ImGui::TextUnformatted(buffer.data());
|
ImGui::TextUnformatted(buffer.data());
|
||||||
|
|
||||||
if( mover.EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) {
|
if (mover.EnginePowerSource.SourceType == TPowerSource::CurrentCollector)
|
||||||
std::snprintf(
|
{
|
||||||
buffer.data(), buffer.size(),
|
std::snprintf(buffer.data(), buffer.size(), STR_C(" pantograph: %.2f%cMT"), mover.PantPress, (mover.bPantKurek3 ? '-' : '|'));
|
||||||
STR_C(" pantograph: %.2f%cMT"),
|
|
||||||
mover.PantPress,
|
|
||||||
( mover.bPantKurek3 ? '-' : '|' ) );
|
|
||||||
ImGui::TextUnformatted(buffer.data());
|
ImGui::TextUnformatted(buffer.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::snprintf(
|
std::snprintf(buffer.data(), buffer.size(),
|
||||||
buffer.data(), buffer.size(),
|
STR_C("Forces:\n tractive: %.1f, brake: %.1f, friction: %.2f%s\nAcceleration:\n tangential: %.2f, normal: %.2f (path radius: %s)\nVelocity: %.2f, distance traveled: %.2f\nPosition: "
|
||||||
STR_C("Forces:\n tractive: %.1f, brake: %.1f, friction: %.2f%s\nAcceleration:\n tangential: %.2f, normal: %.2f (path radius: %s)\nVelocity: %.2f, distance traveled: %.2f\nPosition: [%.2f, %.2f, %.2f]"),
|
"[%.2f, %.2f, %.2f]"),
|
||||||
// forces
|
// forces
|
||||||
mover.Ft * 0.001f * ( mover.CabActive ? mover.CabActive : vehicle.ctOwner ? vehicle.ctOwner->Controlling()->CabActive : 1 ) + 0.001f,
|
mover.Ft * 0.001f *
|
||||||
mover.Fb * 0.001f,
|
(mover.CabActive ? mover.CabActive :
|
||||||
mover.Adhesive( mover.RunningTrack.friction ),
|
vehicle.ctOwner ? vehicle.ctOwner->Controlling()->CabActive :
|
||||||
( mover.SlippingWheels ? " (!)" : "" ),
|
1) +
|
||||||
// acceleration
|
0.001f,
|
||||||
mover.AccSVBased,
|
mover.Fb * 0.001f, mover.Adhesive(mover.RunningTrack.friction), (mover.SlippingWheels ? " (!)" : ""),
|
||||||
mover.AccN + 0.001f,
|
// acceleration
|
||||||
std::string( std::abs( mover.RunningShape.R ) > 10000.0 ? "~0" : to_string( mover.RunningShape.R, 0 ) ).c_str(),
|
mover.AccSVBased, mover.AccN + 0.001f, std::string(std::abs(mover.RunningShape.R) > 10000.0 ? "~0" : to_string(mover.RunningShape.R, 0)).c_str(),
|
||||||
// velocity
|
// velocity
|
||||||
vehicle.GetVelocity(),
|
vehicle.GetVelocity(), mover.DistCounter,
|
||||||
mover.DistCounter,
|
// position
|
||||||
// position
|
vehicle.GetPosition().x, vehicle.GetPosition().y, vehicle.GetPosition().z);
|
||||||
vehicle.GetPosition().x,
|
|
||||||
vehicle.GetPosition().y,
|
|
||||||
vehicle.GetPosition().z );
|
|
||||||
|
|
||||||
ImGui::TextUnformatted(buffer.data());
|
ImGui::TextUnformatted(buffer.data());
|
||||||
|
|
||||||
std::pair<double, double> TrainsetPowerMeter;
|
std::pair<double, double> TrainsetPowerMeter;
|
||||||
|
|
||||||
TDynamicObject *vehicle_iter = vehicle_ptr;
|
TDynamicObject *vehicle_iter = vehicle_ptr;
|
||||||
while (vehicle_iter) {
|
while (vehicle_iter)
|
||||||
if (vehicle_iter->Next())
|
{
|
||||||
vehicle_iter = vehicle_iter->Next();
|
if (vehicle_iter->Next())
|
||||||
else
|
vehicle_iter = vehicle_iter->Next();
|
||||||
break;
|
else
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
while (vehicle_iter) {
|
while (vehicle_iter)
|
||||||
TrainsetPowerMeter.first += vehicle_iter->MoverParameters->EnergyMeter.first;
|
{
|
||||||
TrainsetPowerMeter.second += vehicle_iter->MoverParameters->EnergyMeter.second;
|
TrainsetPowerMeter.first += vehicle_iter->MoverParameters->EnergyMeter.first;
|
||||||
vehicle_iter = vehicle_iter->Prev();
|
TrainsetPowerMeter.second += vehicle_iter->MoverParameters->EnergyMeter.second;
|
||||||
}
|
vehicle_iter = vehicle_iter->Prev();
|
||||||
|
}
|
||||||
|
|
||||||
if (TrainsetPowerMeter.first != 0.0 || TrainsetPowerMeter.second != 0.0) {
|
if (TrainsetPowerMeter.first != 0.0 || TrainsetPowerMeter.second != 0.0)
|
||||||
std::snprintf(buffer.data(), buffer.size(), STR_C("Electricity usage:\n drawn: %.1f kWh\n returned: %.1f kWh\n balance: %.1f kWh"),
|
{
|
||||||
TrainsetPowerMeter.first, -TrainsetPowerMeter.second, TrainsetPowerMeter.first + TrainsetPowerMeter.second);
|
std::snprintf(buffer.data(), buffer.size(), STR_C("Electricity usage:\n drawn: %.1f kWh\n returned: %.1f kWh\n balance: %.1f kWh"), TrainsetPowerMeter.first, -TrainsetPowerMeter.second,
|
||||||
|
TrainsetPowerMeter.first + TrainsetPowerMeter.second);
|
||||||
|
|
||||||
ImGui::TextUnformatted(buffer.data());
|
ImGui::TextUnformatted(buffer.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_mini(mover);
|
draw_mini(mover);
|
||||||
|
|
||||||
if (ImGui::Button(STR_C("Radiostop")))
|
if (ImGui::Button(STR_C("Radiostop")))
|
||||||
m_relay.post(user_command::radiostopsend, 0.0, 0.0, GLFW_PRESS, 0, vehicle_ptr->GetPosition());
|
m_relay.post(user_command::radiostopsend, 0.0, 0.0, GLFW_PRESS, 0, vehicle_ptr->GetPosition());
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (ImGui::Button(STR_C("Stop and repair")))
|
if (ImGui::Button(STR_C("Stop and repair")))
|
||||||
m_relay.post(user_command::resetconsist, 0.0, 0.0, GLFW_PRESS, 0, glm::vec3(0.0f), &vehicle_ptr->name());
|
m_relay.post(user_command::resetconsist, 0.0, 0.0, GLFW_PRESS, 0, glm::vec3(0.0f), &vehicle_ptr->name());
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (ImGui::Button(STR_C("Reset position"))) {
|
if (ImGui::Button(STR_C("Reset position")))
|
||||||
|
{
|
||||||
std::string payload = vehicle_ptr->name() + '%' + vehicle_ptr->initial_track->name();
|
std::string payload = vehicle_ptr->name() + '%' + vehicle_ptr->initial_track->name();
|
||||||
m_relay.post(user_command::consistteleport, 0.0, 0.0, GLFW_PRESS, 0, glm::vec3(0.0f), &payload);
|
m_relay.post(user_command::consistteleport, 0.0, 0.0, GLFW_PRESS, 0, glm::vec3(0.0f), &payload);
|
||||||
m_relay.post(user_command::resetconsist, 0.0, 0.0, GLFW_PRESS, 0, glm::vec3(0.0f), &vehicle_ptr->name());
|
m_relay.post(user_command::resetconsist, 0.0, 0.0, GLFW_PRESS, 0, glm::vec3(0.0f), &vehicle_ptr->name());
|
||||||
@@ -330,7 +292,8 @@ void ui::vehicleparams_panel::render_contents()
|
|||||||
if (ImGui::IsItemDeactivated())
|
if (ImGui::IsItemDeactivated())
|
||||||
m_relay.post(user_command::consistreleaser, 0.0, 0.0, GLFW_RELEASE, 0, glm::vec3(0.0f), &vehicle_ptr->name());
|
m_relay.post(user_command::consistreleaser, 0.0, 0.0, GLFW_RELEASE, 0, glm::vec3(0.0f), &vehicle_ptr->name());
|
||||||
|
|
||||||
if (vehicle_ptr->MoverParameters->V < 0.01) {
|
if (vehicle_ptr->MoverParameters->V < 0.01)
|
||||||
|
{
|
||||||
if (ImGui::Button(STR_C("Move +500m")))
|
if (ImGui::Button(STR_C("Move +500m")))
|
||||||
m_relay.post(user_command::dynamicmove, 500.0, 0.0, GLFW_PRESS, 0, glm::vec3(0.0f), &vehicle_ptr->name());
|
m_relay.post(user_command::dynamicmove, 500.0, 0.0, GLFW_PRESS, 0, glm::vec3(0.0f), &vehicle_ptr->name());
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|||||||
Reference in New Issue
Block a user