Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
6.0 kB · 181 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182#ifndef INTERPRETER_MISCOPCODES_H_INCLUDED#define INTERPRETER_MISCOPCODES_H_INCLUDED
#include <algorithm>#include <format>#include <string>#include <vector>
#include "defines.hpp"#include "opcodes.hpp"#include "runtime.hpp"
#include <components/misc/messageformatparser.hpp>
namespace Interpreter{ class RuntimeMessageFormatter : public Misc::MessageFormatParser { private: std::string mFormattedMessage; Runtime& mRuntime;
protected: void visitedPlaceholder( Placeholder placeholder, int flags, int width, int precision, Notation notation) override { std::string formatString;
if (placeholder == StringPlaceholder) { int index = mRuntime[0].mInteger; mRuntime.pop();
std::string_view value = mRuntime.getStringLiteral(index); if (precision >= 0) value = value.substr(0, static_cast<std::size_t>(precision)); if (width < 0) mFormattedMessage += value; else { formatString = "{:"; if (flags & PrependZero) formatString += '0'; if (flags & AlignLeft) formatString += '<'; else formatString += '>'; formatString += "{}}"; std::vformat_to( std::back_inserter(mFormattedMessage), formatString, std::make_format_args(value, width)); } } else { formatString = "{:"; if (flags & AlignLeft) formatString += '<'; if (flags & PositiveSign) formatString += '+'; else if (flags & PositiveSpace) formatString += ' '; if (flags & AlternateForm) formatString += '#'; if (flags & PrependZero) formatString += '0'; if (width >= 0) formatString += "{}"; if (placeholder == FloatPlaceholder) { if (precision >= 0) formatString += ".{}"; formatString += static_cast<char>(notation); } else precision = -1; formatString += '}'; const auto appendMessage = [&](auto value) { if (width >= 0 && precision >= 0) std::vformat_to(std::back_inserter(mFormattedMessage), formatString, std::make_format_args(value, width, precision)); else if (width >= 0) std::vformat_to( std::back_inserter(mFormattedMessage), formatString, std::make_format_args(value, width)); else if (precision >= 0) std::vformat_to(std::back_inserter(mFormattedMessage), formatString, std::make_format_args(value, precision)); else std::vformat_to( std::back_inserter(mFormattedMessage), formatString, std::make_format_args(value)); }; if (placeholder == FloatPlaceholder) { float value = mRuntime[0].mFloat; mRuntime.pop(); appendMessage(value); } else { Type_Integer value = mRuntime[0].mInteger; mRuntime.pop(); appendMessage(value); } } }
void visitedCharacter(char c) override { mFormattedMessage += c; }
public: RuntimeMessageFormatter(Runtime& runtime) : mRuntime(runtime) { }
void process(std::string_view message) override { mFormattedMessage.clear(); MessageFormatParser::process(message); }
std::string getFormattedMessage() const { return mFormattedMessage; } };
inline std::string formatMessage(std::string_view message, Runtime& runtime) { RuntimeMessageFormatter formatter(runtime); formatter.process(message);
std::string formattedMessage = formatter.getFormattedMessage(); formattedMessage = fixDefinesMsgBox(formattedMessage, runtime.getContext()); return formattedMessage; }
class OpMessageBox : public Opcode1 { public: void execute(Runtime& runtime, unsigned int arg0) override { // message int index = runtime[0].mInteger; runtime.pop(); std::string_view message = runtime.getStringLiteral(index);
// buttons std::vector<std::string> buttons;
for (std::size_t i = 0; i < arg0; ++i) { index = runtime[0].mInteger; runtime.pop(); buttons.emplace_back(runtime.getStringLiteral(index)); }
std::reverse(buttons.begin(), buttons.end());
// handle additional parameters std::string formattedMessage = formatMessage(message, runtime);
runtime.getContext().messageBox(formattedMessage, buttons); } };
class OpReport : public Opcode0 { public: void execute(Runtime& runtime) override { // message int index = runtime[0].mInteger; runtime.pop(); std::string_view message = runtime.getStringLiteral(index);
// handle additional parameters std::string formattedMessage = formatMessage(message, runtime);
runtime.getContext().report(formattedMessage); } };
}
#endif