mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-20 15:40:32 +00:00
Show logs in the debug window
Some part of UI code is written by @andrew-app
This commit is contained in:
parent
5110c4a50e
commit
cf49b46d64
@ -143,6 +143,7 @@
|
||||
Feature #6128: Soft Particles
|
||||
Feature #6161: Refactor Sky to use shaders and GLES/GL3 friendly
|
||||
Feature #6162: Refactor GUI to use shaders and to be GLES and GL3+ friendly
|
||||
Feature #6171: In-game log viewer
|
||||
Feature #6189: Navigation mesh disk cache
|
||||
Feature #6199: Support FBO Rendering
|
||||
Feature #6248: Embedded error marker mesh
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <MyGUI_EditBox.h>
|
||||
|
||||
#include <LinearMath/btQuickprof.h>
|
||||
#include <components/debug/debugging.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#ifndef BT_NO_PROFILE
|
||||
|
||||
@ -84,28 +86,105 @@ namespace MWGui
|
||||
|
||||
// Ideas for other tabs:
|
||||
// - Texture / compositor texture viewer
|
||||
// - Log viewer
|
||||
// - Material editor
|
||||
// - Shader editor
|
||||
|
||||
initLogView();
|
||||
|
||||
#ifndef BT_NO_PROFILE
|
||||
MyGUI::TabItem* item = mTabControl->addItem("Physics Profiler");
|
||||
mBulletProfilerEdit = item->createWidgetReal<MyGUI::EditBox>
|
||||
("LogEdit", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Stretch);
|
||||
#else
|
||||
mBulletProfilerEdit = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void DebugWindow::onFrame(float dt)
|
||||
void DebugWindow::initLogView()
|
||||
{
|
||||
MyGUI::TabItem* itemLV = mTabControl->addItem("Log Viewer");
|
||||
mLogView = itemLV->createWidgetReal<MyGUI::EditBox>
|
||||
("LogEdit", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Stretch);
|
||||
mLogView->setEditReadOnly(true);
|
||||
|
||||
mLogCircularBuffer.resize(std::max<int64_t>(0, Settings::Manager::getInt64("log buffer size", "General")));
|
||||
Debug::setLogListener([this](Debug::Level level, std::string_view prefix, std::string_view msg)
|
||||
{
|
||||
if (mLogCircularBuffer.empty())
|
||||
return; // Log viewer is disabled.
|
||||
std::string_view color;
|
||||
switch (level)
|
||||
{
|
||||
case Debug::Error: color = "#FF0000"; break;
|
||||
case Debug::Warning: color = "#FFFF00"; break;
|
||||
case Debug::Info: color = "#FFFFFF"; break;
|
||||
case Debug::Verbose:
|
||||
case Debug::Debug: color = "#666666"; break;
|
||||
default: color = "#FFFFFF";
|
||||
}
|
||||
bool bufferOverflow = false;
|
||||
const int64_t bufSize = mLogCircularBuffer.size();
|
||||
auto addChar = [&](char c)
|
||||
{
|
||||
mLogCircularBuffer[mLogEndIndex++] = c;
|
||||
if (mLogEndIndex == bufSize)
|
||||
mLogEndIndex = 0;
|
||||
bufferOverflow = bufferOverflow || mLogEndIndex == mLogStartIndex;
|
||||
};
|
||||
auto addShieldedStr = [&](std::string_view s)
|
||||
{
|
||||
for (char c : s)
|
||||
{
|
||||
addChar(c);
|
||||
if (c == '#')
|
||||
addChar(c);
|
||||
}
|
||||
};
|
||||
for (char c : color)
|
||||
addChar(c);
|
||||
addShieldedStr(prefix);
|
||||
addShieldedStr(msg);
|
||||
if (bufferOverflow)
|
||||
mLogStartIndex = (mLogEndIndex + 1) % bufSize;
|
||||
});
|
||||
}
|
||||
|
||||
void DebugWindow::updateLogView()
|
||||
{
|
||||
if (!mLogView || mLogCircularBuffer.empty() || mLogStartIndex == mLogEndIndex)
|
||||
return;
|
||||
if (mLogView->isTextSelection())
|
||||
return; // Don't change text while player is trying to copy something
|
||||
|
||||
std::string addition;
|
||||
const int64_t bufSize = mLogCircularBuffer.size();
|
||||
{
|
||||
std::unique_lock<std::mutex> lock = Log::lock();
|
||||
if (mLogStartIndex < mLogEndIndex)
|
||||
addition = std::string(mLogCircularBuffer.data() + mLogStartIndex, mLogEndIndex - mLogStartIndex);
|
||||
else
|
||||
{
|
||||
addition = std::string(mLogCircularBuffer.data() + mLogStartIndex, bufSize - mLogStartIndex);
|
||||
addition.append(mLogCircularBuffer.data(), mLogEndIndex);
|
||||
}
|
||||
mLogStartIndex = mLogEndIndex;
|
||||
}
|
||||
|
||||
size_t scrollPos = mLogView->getVScrollPosition();
|
||||
bool scrolledToTheEnd = scrollPos+1 >= mLogView->getVScrollRange();
|
||||
int64_t newSizeEstimation = mLogView->getTextLength() + addition.size();
|
||||
if (newSizeEstimation > bufSize)
|
||||
mLogView->eraseText(0, newSizeEstimation - bufSize);
|
||||
mLogView->addText(addition);
|
||||
if (scrolledToTheEnd && mLogView->getVScrollRange() > 0)
|
||||
mLogView->setVScrollPosition(mLogView->getVScrollRange() - 1);
|
||||
else
|
||||
mLogView->setVScrollPosition(scrollPos);
|
||||
}
|
||||
|
||||
void DebugWindow::updateBulletProfile()
|
||||
{
|
||||
#ifndef BT_NO_PROFILE
|
||||
if (!isVisible())
|
||||
return;
|
||||
|
||||
static float timer = 0;
|
||||
timer -= dt;
|
||||
|
||||
if (timer > 0)
|
||||
return;
|
||||
timer = 1;
|
||||
|
||||
std::stringstream stream;
|
||||
bulletDumpAll(stream);
|
||||
|
||||
@ -118,4 +197,17 @@ namespace MWGui
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
void DebugWindow::onFrame(float dt)
|
||||
{
|
||||
static float timer = 0;
|
||||
timer -= dt;
|
||||
if (timer > 0 || !isVisible())
|
||||
return;
|
||||
timer = 0.25;
|
||||
|
||||
if (mTabControl->getIndexSelected() == 0)
|
||||
updateLogView();
|
||||
else
|
||||
updateBulletProfile();
|
||||
}
|
||||
}
|
@ -14,8 +14,17 @@ namespace MWGui
|
||||
void onFrame(float dt) override;
|
||||
|
||||
private:
|
||||
void initLogView();
|
||||
void updateLogView();
|
||||
void updateBulletProfile();
|
||||
|
||||
MyGUI::TabControl* mTabControl;
|
||||
|
||||
MyGUI::EditBox* mLogView;
|
||||
std::vector<char> mLogCircularBuffer;
|
||||
int64_t mLogStartIndex = 0;
|
||||
int64_t mLogEndIndex = 0;
|
||||
|
||||
MyGUI::EditBox* mBulletProfilerEdit;
|
||||
};
|
||||
|
||||
|
@ -884,6 +884,8 @@ namespace MWGui
|
||||
if (mLocalMapRender)
|
||||
mLocalMapRender->cleanupCameras();
|
||||
|
||||
mDebugWindow->onFrame(frameDuration);
|
||||
|
||||
if (!gameRunning)
|
||||
return;
|
||||
|
||||
@ -903,8 +905,6 @@ namespace MWGui
|
||||
|
||||
mHud->onFrame(frameDuration);
|
||||
|
||||
mDebugWindow->onFrame(frameDuration);
|
||||
|
||||
mPostProcessorHud->onFrame(frameDuration);
|
||||
|
||||
if (mCharGen)
|
||||
@ -2061,9 +2061,7 @@ namespace MWGui
|
||||
|
||||
void WindowManager::toggleDebugWindow()
|
||||
{
|
||||
#ifndef BT_NO_PROFILE
|
||||
mDebugWindow->setVisible(!mDebugWindow->isVisible());
|
||||
#endif
|
||||
}
|
||||
|
||||
void WindowManager::togglePostProcessorHud()
|
||||
|
@ -61,6 +61,9 @@ namespace Debug
|
||||
}
|
||||
#endif
|
||||
|
||||
static LogListener logListener;
|
||||
void setLogListener(LogListener listener) { logListener = std::move(listener); }
|
||||
|
||||
std::streamsize DebugOutputBase::write(const char *str, std::streamsize size)
|
||||
{
|
||||
if (size <= 0)
|
||||
@ -94,6 +97,8 @@ namespace Debug
|
||||
lineSize++;
|
||||
writeImpl(prefix, prefixSize, level);
|
||||
writeImpl(msg.data(), lineSize, level);
|
||||
if (logListener)
|
||||
logListener(level, std::string_view(prefix, prefixSize), std::string_view(msg.data(), lineSize));
|
||||
msg = msg.substr(lineSize);
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,8 @@ namespace Debug
|
||||
};
|
||||
#endif
|
||||
|
||||
using LogListener = std::function<void(Debug::Level, std::string_view prefix, std::string_view msg)>;
|
||||
void setLogListener(LogListener);
|
||||
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
return;
|
||||
|
||||
// Locks a global lock while the object is alive
|
||||
mLock = std::unique_lock<std::mutex>(sLock);
|
||||
mLock = lock();
|
||||
|
||||
// If the app has no logging system enabled, log level is not specified.
|
||||
// Show all messages without marker - we just use the plain cout in this case.
|
||||
@ -61,6 +61,8 @@ public:
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
static std::unique_lock<std::mutex> lock() { return std::unique_lock<std::mutex>(sLock); }
|
||||
|
||||
private:
|
||||
const bool mShouldLog;
|
||||
};
|
||||
|
@ -86,3 +86,17 @@ since if the country code isn't specified the generic language-code only locale
|
||||
refer to any of the country-specific variants.
|
||||
|
||||
This setting can only be configured by editing the settings configuration file.
|
||||
|
||||
log buffer size
|
||||
---------------
|
||||
|
||||
:Type: integer
|
||||
:Range: >= 0
|
||||
:Default: 65536
|
||||
|
||||
Buffer size for the in-game log viewer (press F10 to toggle the log viewer).
|
||||
When the log doesn't fit into the buffer, only the end of the log is visible in the log viewer.
|
||||
Zero disables the log viewer.
|
||||
|
||||
This setting can only be configured by editing the settings configuration file.
|
||||
|
||||
|
@ -8,14 +8,14 @@
|
||||
<Property key="Size" value="600 520"/>
|
||||
</Layer>
|
||||
<Layer name="Windows" overlapped="true" pick="true"/>
|
||||
<Layer name="Debug" overlapped="true" pick="true"/>
|
||||
<Layer name="DragAndDrop" overlapped="false" pick="false"/>
|
||||
<Layer name="DrowningBar" overlapped="false" pick="false"/>
|
||||
<Layer name="MainMenuBackground" overlapped="true" pick="true"/>
|
||||
<Layer name="MainMenu" overlapped="true" pick="true"/>
|
||||
<Layer name="Console" overlapped="true" pick="true"/>
|
||||
<Layer name="LoadingScreenBackground" overlapped="false" pick="true"/>
|
||||
<Layer name="LoadingScreen" overlapped="false" pick="true"/>
|
||||
<Layer name="Debug" overlapped="true" pick="true"/>
|
||||
<Layer name="Console" overlapped="true" pick="true"/>
|
||||
<Layer name="Modal" overlapped="true" pick="true"/>
|
||||
<Layer name="Popup" overlapped="true" pick="true"/>
|
||||
<Layer name="Notification" overlapped="false" pick="false"/>
|
||||
|
@ -400,6 +400,9 @@ notify on saved screenshot = false
|
||||
# For example "de,en" means German as the first prority and English as a fallback.
|
||||
preferred locales = en
|
||||
|
||||
# Buffer size for the in-game log viewer (press F10 to toggle). Zero disables the log viewer.
|
||||
log buffer size = 65536
|
||||
|
||||
[Shaders]
|
||||
|
||||
# Force rendering with shaders. By default, only bump-mapped objects will use shaders.
|
||||
|
Loading…
x
Reference in New Issue
Block a user