mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-23 06:44:38 +01:00
Improve string handling and allow window update
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
# include <openrct2-ui/interface/Widget.h>
|
||||
# include <openrct2-ui/windows/Window.h>
|
||||
# include <openrct2/drawing/Drawing.h>
|
||||
# include <openrct2/localisation/Language.h>
|
||||
# include <openrct2/localisation/Localisation.h>
|
||||
# include <openrct2/localisation/StringIds.h>
|
||||
# include <openrct2/scripting/Plugin.h>
|
||||
@@ -109,28 +110,10 @@ namespace OpenRCT2::Ui::Windows
|
||||
static std::string ProcessString(const DukValue& value)
|
||||
{
|
||||
if (value.type() == DukValue::Type::STRING)
|
||||
return ProcessString(value.as_string());
|
||||
return language_convert_string(value.as_string());
|
||||
return {};
|
||||
}
|
||||
|
||||
static std::string ProcessString(const std::string_view& s)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(s.size());
|
||||
for (char c : s)
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
result.push_back(FORMAT_NEWLINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(c);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static CustomWidgetDesc FromDukValue(DukValue desc)
|
||||
{
|
||||
CustomWidgetDesc result;
|
||||
@@ -228,7 +211,7 @@ namespace OpenRCT2::Ui::Windows
|
||||
result.MaxWidth = GetOptionalInt(desc["maxWidth"]);
|
||||
result.MinHeight = GetOptionalInt(desc["minHeight"]);
|
||||
result.MaxHeight = GetOptionalInt(desc["maxHeight"]);
|
||||
result.Title = desc["title"].as_string();
|
||||
result.Title = language_convert_string(desc["title"].as_string());
|
||||
result.Id = GetOptionalInt(desc["id"]);
|
||||
|
||||
if (desc["widgets"].is_array())
|
||||
@@ -742,6 +725,25 @@ namespace OpenRCT2::Ui::Windows
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetWindowTitle(rct_window* w)
|
||||
{
|
||||
if (w->custom_info != nullptr)
|
||||
{
|
||||
auto& customInfo = GetInfo(w);
|
||||
return customInfo.Desc.Title;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void UpdateWindowTitle(rct_window* w, const std::string_view& value)
|
||||
{
|
||||
if (w->custom_info != nullptr)
|
||||
{
|
||||
auto& customInfo = GetInfo(w);
|
||||
customInfo.Desc.Title = value;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateWidgetText(rct_window* w, rct_widgetindex widgetIndex, const std::string_view& value)
|
||||
{
|
||||
if (w->custom_info != nullptr)
|
||||
@@ -750,7 +752,7 @@ namespace OpenRCT2::Ui::Windows
|
||||
auto customWidgetInfo = customInfo.GetCustomWidgetDesc(widgetIndex);
|
||||
if (customWidgetInfo != nullptr)
|
||||
{
|
||||
customWidgetInfo->Text = CustomWidgetDesc::ProcessString(value);
|
||||
customWidgetInfo->Text = language_convert_string(value);
|
||||
w->widgets[widgetIndex].string = customWidgetInfo->Text.data();
|
||||
widget_invalidate(w, widgetIndex);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
namespace OpenRCT2::Ui::Windows
|
||||
{
|
||||
std::string GetWindowTitle(rct_window* w);
|
||||
void UpdateWindowTitle(rct_window* w, const std::string_view& value);
|
||||
void UpdateWidgetText(rct_window* w, rct_widgetindex widget, const std::string_view& string_view);
|
||||
rct_window* FindCustomWindowByClassification(const std::string_view& classification);
|
||||
std::optional<rct_widgetindex> FindWidgetIndexByName(rct_window* w, const std::string_view& name);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# include <openrct2/common.h>
|
||||
# include <openrct2/interface/Window.h>
|
||||
# include <openrct2/interface/Window_internal.h>
|
||||
# include <openrct2/localisation/Language.h>
|
||||
# include <openrct2/scripting/Duktape.hpp>
|
||||
|
||||
namespace OpenRCT2::Scripting
|
||||
@@ -125,6 +126,24 @@ namespace OpenRCT2::Scripting
|
||||
}
|
||||
}
|
||||
|
||||
std::string title_get()
|
||||
{
|
||||
auto w = GetWindow();
|
||||
if (w != nullptr && w->classification == WC_CUSTOM)
|
||||
{
|
||||
return GetWindowTitle(w);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
void title_set(std::string value)
|
||||
{
|
||||
auto w = GetWindow();
|
||||
if (w != nullptr && w->classification == WC_CUSTOM)
|
||||
{
|
||||
UpdateWindowTitle(w, language_convert_string(value));
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
auto w = GetWindow();
|
||||
@@ -169,6 +188,7 @@ namespace OpenRCT2::Scripting
|
||||
dukglue_register_property(ctx, &ScWindow::isSticky_get, nullptr, "isSticky");
|
||||
dukglue_register_property(ctx, &ScWindow::widgets_get, nullptr, "widgets");
|
||||
dukglue_register_property(ctx, &ScWindow::colours_get, &ScWindow::colours_set, "colours");
|
||||
dukglue_register_property(ctx, &ScWindow::title_get, &ScWindow::title_set, "title");
|
||||
|
||||
dukglue_register_method(ctx, &ScWindow::close, "close");
|
||||
dukglue_register_method(ctx, &ScWindow::findWidget, "findWidget");
|
||||
|
||||
@@ -136,3 +136,78 @@ rct_string_id language_allocate_object_string(const std::string& target)
|
||||
auto& localisationService = OpenRCT2::GetContext()->GetLocalisationService();
|
||||
return localisationService.AllocateObjectString(target);
|
||||
}
|
||||
|
||||
std::string language_convert_string(const std::string_view& s)
|
||||
{
|
||||
enum class PARSE_STATE
|
||||
{
|
||||
DEFAULT,
|
||||
CR,
|
||||
TOKEN,
|
||||
};
|
||||
|
||||
std::string result;
|
||||
std::string token;
|
||||
PARSE_STATE state{};
|
||||
token.reserve(64);
|
||||
result.reserve(s.size() * 2);
|
||||
for (char c : s)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case PARSE_STATE::CR:
|
||||
result.push_back(FORMAT_NEWLINE);
|
||||
state = PARSE_STATE::DEFAULT;
|
||||
[[fallthrough]];
|
||||
case PARSE_STATE::DEFAULT:
|
||||
switch (c)
|
||||
{
|
||||
case '\r':
|
||||
state = PARSE_STATE::CR;
|
||||
break;
|
||||
case '\n':
|
||||
result.push_back(FORMAT_NEWLINE);
|
||||
break;
|
||||
case '{':
|
||||
token.clear();
|
||||
state = PARSE_STATE::TOKEN;
|
||||
break;
|
||||
default:
|
||||
if (c >= 32)
|
||||
{
|
||||
result.push_back(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PARSE_STATE::TOKEN:
|
||||
if (c == '}')
|
||||
{
|
||||
auto code = format_get_code(token.c_str());
|
||||
if (code == 0)
|
||||
{
|
||||
int32_t number{};
|
||||
if (sscanf(token.c_str(), "%d", &number) == 1)
|
||||
{
|
||||
auto b = static_cast<uint8_t>(std::clamp(number, 0, 255));
|
||||
token.push_back(b);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char buffer[8]{};
|
||||
utf8_write_codepoint(buffer, code);
|
||||
result.append(buffer);
|
||||
}
|
||||
state = PARSE_STATE::DEFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
token.push_back(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.shrink_to_fit();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ bool language_get_localised_scenario_strings(const utf8* scenarioFilename, rct_s
|
||||
void language_free_object_string(rct_string_id stringId);
|
||||
rct_string_id language_get_object_override_string_id(const char* identifier, uint8_t index);
|
||||
rct_string_id language_allocate_object_string(const std::string& target);
|
||||
std::string language_convert_string(const std::string_view& s);
|
||||
|
||||
constexpr utf8* utf8_write_codepoint(utf8* dst, uint32_t codepoint)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user