Upgrade to 5.8

This commit is contained in:
Ado
2026-07-04 21:15:59 +02:00
parent 4cf4176d57
commit 9f3051d68e
55 changed files with 5495 additions and 77 deletions

View File

@@ -0,0 +1,6 @@
{
"cSpell.words": [
"speakerline",
"squarebrackets"
]
}

View File

@@ -0,0 +1,12 @@
from setuptools import setup, find_packages
setup (
name='sudslexer',
packages=find_packages(),
version="0.4.0",
entry_points =
"""
[pygments.lexers]
sudslexer = sudslexer.lexer:SudsLexer
""",
)

View File

@@ -0,0 +1,71 @@
from pygments.lexer import RegexLexer, bygroups
from pygments.token import *
class SudsLexer(RegexLexer):
name = 'SUDS'
aliases = ['suds']
filenames = ['*.sud']
tokens = {
'root': [
(r'===\s*\n', Generic.Heading),
# Choices
(r'\s*\*\-?\s+[^\@\n]+[\@\n]', Generic.Subheading),
(r'\s*#.*\n', Comment),
# Speaker lines
(r'\s*\S+\:', Name.Class, 'speakerline'),
# Open brackets for special functions
(r'\[', Operator, 'squarebrackets'),
# Variables
(r'(\{)([\w\.]+)(\})', bygroups(Operator, Name.Variable, Operator)),
(r'(\|)(plural|gender)(\()(.*?)(\))', bygroups(Operator, Keyword, Operator, Keyword, Operator)),
(r'\b([tT]rue|[fF]alse|[mM]asculine|[fF]eminine|[nN]euter)\b', Name.Constant),
# Line IDs
(r'\@[0-9a-fA-F]+\@', Comment.Special),
# Embedded markup
(r'\<\w+\>', Name.Decorator),
(r'\<\/\>', Name.Decorator),
# Goto labels
(r'\s*:\S+\n', Name.Label),
# Comments
(r'\s*\#[\=\+\%]?.*\n', Comment.Special),
# Fallback for all other text
# Needs an optional \n on the end to finish lines correctly
(r'\s+[\n]?', Text),
(r'\S+?[\n]?', Text), # non-greedy so we don't consume all non-whitespace
],
# While in a speaker line, we ignore everything else except variables & markup
'speakerline' : [
# Variables
(r'(\{)([\w\.]+)(\})', bygroups(Operator, Name.Variable, Operator)),
(r'(\|)(plural|gender)(\()(.*?)(\))', bygroups(Operator, Keyword, Operator, Keyword, Operator)),
(r'[\@\n]', Text, '#pop'),
# Embedded markup
(r'\<\w+\>', Name.Decorator),
(r'\<\/\>', Name.Decorator),
(r'[^\@\n\<\{]+', Text),
],
# While in a [] block, highlight operators etc (don't do it elsewhere)
'squarebrackets' : [
# Close bracket finishes
(r'\]\s*[\n]?', Operator, '#pop'),
# Variables
(r'(\{)([\w\.]+)(\})', bygroups(Operator, Name.Variable, Operator)),
(r'\+\/\-\*\!\%', Operator),
(r'\"[^\"]*\"', String.Double),
(r'\`[^\`]*\`', String.Escape),
(r'\d+(\.\d+)?', Number),
(r'\b([tT]rue|[fF]alse|[mM]asculine|[fF]eminine|[nN]euter)\b', Name.Constant),
# Set, event commands so we can highlight variable/event differently
(r'\s*(set|event)(\s+)([^\]\s]+)', bygroups(Keyword, Text, Name.Variable)),
(r'\s*(if|else|elseif|endif|event|return|goto|gosub|go to|go sub|random|endrandom)\b', Keyword),
(r'\b(and|or|&&|\|\||not)\b', Operator),
(r'[,]', Punctuation),
(r'\s+', Text), # whitespace OK
]
}

View File

@@ -2,6 +2,9 @@
// Released under the MIT license https://opensource.org/license/MIT/
#include "SUDSValue.h"
#include "UObject/Class.h"
#include "Internationalization/Text.h"
FArchive& operator<<(FArchive& Ar, FSUDSValue& Value)
{
// Custom serialisation since we can't auto-serialise union, TOptional
@@ -62,7 +65,11 @@ FString FSUDSValue::ToString() const
case ESUDSValueType::Boolean:
return GetBooleanValue() ? "True" : "False";
case ESUDSValueType::Gender:
return StaticEnum<ETextGender>()->GetNameStringByValue((int64)GetGenderValue());
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
return LexToString(GetGenderValue());
#else
return *StaticEnum<ETextGender>()->GetNameStringByValue((int64)GetGenderValue());
#endif
case ESUDSValueType::Name:
return GetNameValue().ToString();
case ESUDSValueType::Variable:

View File

@@ -706,7 +706,11 @@ void FSUDSEditorToolkit::OnDialogueChoice(USUDSDialogue* D, int ChoiceIndex, int
void FSUDSEditorToolkit::OnDialogueEvent(USUDSDialogue* D, FName EventName, const TArray<FSUDSValue>& Args, int LineNo)
{
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
TStringBuilder<256> B;
#else
FStringBuilderBase B;
#endif
if (Args.Num() > 0)
{
for (auto& Arg : Args)
@@ -1372,6 +1376,24 @@ TSharedRef<SWidget> SSUDSEditorVariableItem::GetGenderMenu()
{
FMenuBuilder MenuBuilder(true, NULL);
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
// StaticEnum<ETextGender>() doesn't exist anymore so we have to do this manually
const FUIAction Action0(FExecuteAction::CreateSP(this, &SSUDSEditorVariableItem::OnGenderSelected, ETextGender::Feminine));
MenuBuilder.AddMenuEntry(FText::FromString(LexToString(ETextGender::Feminine)),
FText(),
FSlateIcon(),
Action0);
const FUIAction Action1(FExecuteAction::CreateSP(this, &SSUDSEditorVariableItem::OnGenderSelected, ETextGender::Masculine));
MenuBuilder.AddMenuEntry(FText::FromString(LexToString(ETextGender::Masculine)),
FText(),
FSlateIcon(),
Action1);
const FUIAction Action2(FExecuteAction::CreateSP(this, &SSUDSEditorVariableItem::OnGenderSelected, ETextGender::Neuter));
MenuBuilder.AddMenuEntry(FText::FromString(LexToString(ETextGender::Neuter)),
FText(),
FSlateIcon(),
Action2);
#else
// NumEnums() - 1 because the last value is the autogen _MAX value
for (int i = 0; i < StaticEnum<ETextGender>()->NumEnums() - 1; ++i)
{
@@ -1383,6 +1405,7 @@ TSharedRef<SWidget> SSUDSEditorVariableItem::GetGenderMenu()
Action);
}
#endif
return MenuBuilder.MakeWidget();

View File

@@ -1772,7 +1772,11 @@ FString FSUDSScriptImporter::GetCurrentTreePath(const FSUDSScriptImporter::Parse
// Do NOT fallthrough to here
// Fallthrough to here instead (/)
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
TStringBuilder<256> B;
#else
FStringBuilderBase B;
#endif
for (auto Indent : Tree.IndentLevelStack)
{
B.Appendf(TEXT("%s%s"), *Indent.PathEntry, *TreePathSeparator);
@@ -1784,7 +1788,11 @@ FString FSUDSScriptImporter::GetCurrentTreeConditionalPath(const FSUDSScriptImpo
{
// Like GetCurrentTreePath, but for conditional blocks
// Cannot fall through to blocks that aren't on the same conditional path
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
TStringBuilder<256> B;
#else
FStringBuilderBase B;
#endif
int BlockIdx = Tree.CurrentConditionalBlockIdx;
B.Append(TreePathSeparator);
// work backwards, hence prepend
@@ -1803,7 +1811,11 @@ FString FSUDSScriptImporter::GetCurrentTreeConditionalPath(const FSUDSScriptImpo
FString FSUDSScriptImporter::GetTreeConditionalPath(const FSUDSScriptImporter::ParsedTree& Tree, int NodeIndex)
{
// Like GetCurrentTreeConditionalPath, but we're not in the block context. Follow the nodes back up
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
TStringBuilder<256> B;
#else
FStringBuilderBase B;
#endif
B.Append(TreePathSeparator);
while (Tree.Nodes.IsValidIndex(NodeIndex))
@@ -2543,7 +2555,11 @@ void FSUDSScriptImporter::PopulateAssetFromTree(USUDSScript* Asset,
{
case ESUDSParsedNodeType::Text:
{
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
StringTable->GetMutableStringTable()->SetSourceString(InNode.TextID, InNode.Text, "");
#else
StringTable->GetMutableStringTable()->SetSourceString(InNode.TextID, InNode.Text);
#endif
// Always include speaker metadata
StringTable->GetMutableStringTable()->SetMetaData(InNode.TextID, FName("Speaker"), InNode.Identifier);
// Other metadata
@@ -2579,7 +2595,11 @@ void FSUDSScriptImporter::PopulateAssetFromTree(USUDSScript* Asset,
FSUDSExpression Expr = InNode.Expression;
if (Expr.IsTextLiteral())
{
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
StringTable->GetMutableStringTable()->SetSourceString(InNode.TextID, Expr.GetTextLiteralValue().ToString(), "");
#else
StringTable->GetMutableStringTable()->SetSourceString(InNode.TextID, Expr.GetTextLiteralValue().ToString());
#endif
Expr.SetTextLiteralValue(FText::FromStringTable (StringTable->GetStringTableId(), InNode.TextID));
}
SetNode->Init(InNode.Identifier, Expr, InNode.SourceLineNo);
@@ -2707,7 +2727,11 @@ void FSUDSScriptImporter::PopulateAssetFromTree(USUDSScript* Asset,
if (!InEdge.TextID.IsEmpty() && !InEdge.Text.IsEmpty())
{
#if ENGINE_MAJOR_VERSION ==5 && ENGINE_MINOR_VERSION >= 8
StringTable->GetMutableStringTable()->SetSourceString(InEdge.TextID, InEdge.Text, "");
#else
StringTable->GetMutableStringTable()->SetSourceString(InEdge.TextID, InEdge.Text);
#endif
NewEdge.SetText(FText::FromStringTable(StringTable->GetStringTableId(), InEdge.TextID));
// Always include speaker metadata, always the player in a choice
// Identify that it's a choice so translators know that there may be more limited space