Skip to content

Commit

Permalink
Remove std library usage where possible
Browse files Browse the repository at this point in the history
- Deprecate & remove ILogger and string_format
- Migrate function handlers to delegate definitions, per Unreal structures
- Add [[maybe_unused]] to UnrealLogHandler to indicate the parameters may be unused
- Update parameters to const reference where possible (function handlers, etc.)
- Update map references to use Unreal's TMap, vector references to use Unreal's TArray
- Implement State::ClearStack
- Rename YarnFunction to TYarnFunction and migrate from std::function to TDelegate
  • Loading branch information
codemaster committed Jan 1, 2024
1 parent 0545771 commit e868311
Show file tree
Hide file tree
Showing 15 changed files with 469 additions and 511 deletions.
128 changes: 53 additions & 75 deletions Source/YarnSpinner/Private/DialogueRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@


#include "DialogueRunner.h"

#include "Line.h"
#include "Option.h"
#include "YarnSubsystem.h"
#include "YarnSpinner.h"
#include "Kismet/KismetInternationalizationLibrary.h"
#include "Misc/YSLogging.h"

THIRD_PARTY_INCLUDES_START
Expand Down Expand Up @@ -47,45 +46,45 @@ void ADialogueRunner::PreInitializeComponents()
}

// Create the Library
Library = TUniquePtr<Yarn::Library>(new Yarn::Library(*this));
Library = MakeUnique<Yarn::Library>();

// Create the VirtualMachine, supplying it with the loaded Program and
// configuring it to use our library, plus use this ADialogueRunner as the
// logger and the variable storage
VirtualMachine = TUniquePtr<Yarn::VirtualMachine>(new Yarn::VirtualMachine(Program, *(Library), *this, *this));
VirtualMachine = MakeUnique<Yarn::VirtualMachine>(Program, *(Library), *this);

VirtualMachine->LineHandler = [this](Yarn::Line& Line)
VirtualMachine->OnLine.AddLambda([this](const Yarn::Line& Line)
{
UE_LOG(LogYarnSpinner, Log, TEXT("Received line %s"), UTF8_TO_TCHAR(Line.LineID.c_str()));
YS_LOG("Received line %s", *Line.LineID);

// Get the Yarn line struct, and make a ULine out of it to use
ULine* LineObject = NewObject<ULine>(this);
LineObject->LineID = FName(Line.LineID.c_str());
LineObject->LineID = FName(*Line.LineID);

GetDisplayTextForLine(LineObject, Line);

const TArray<TSoftObjectPtr<UObject>> LineAssets = YarnProject->GetLineAssets(LineObject->LineID);
YS_LOG_FUNC("Got %d line assets for line '%s'", LineAssets.Num(), *LineObject->LineID.ToString())

OnRunLine(LineObject, LineAssets);
};
});

VirtualMachine->OptionsHandler = [this](Yarn::OptionSet& OptionSet)
VirtualMachine->OnOptions.AddLambda([this](const Yarn::OptionSet& OptionSet)
{
UE_LOG(LogYarnSpinner, Log, TEXT("Received %i options"), OptionSet.Options.size());
YS_LOG("Received %llu options", OptionSet.Options.Num());

// Build a TArray for every option in this OptionSet
TArray<UOption*> Options;

for (auto Option : OptionSet.Options)
for (const Yarn::Option& Option : OptionSet.Options)
{
UE_LOG(LogYarnSpinner, Log, TEXT("- %i: %s"), Option.ID, UTF8_TO_TCHAR(Option.Line.LineID.c_str()));
YS_LOG("- %i: %s", Option.ID, *Option.Line.LineID);

UOption* Opt = NewObject<UOption>(this);
Opt->OptionID = Option.ID;

Opt->Line = NewObject<ULine>(Opt);
Opt->Line->LineID = FName(Option.Line.LineID.c_str());
Opt->Line->LineID = FName(*Option.Line.LineID);

GetDisplayTextForLine(Opt->Line, Option.Line);

Expand All @@ -97,47 +96,46 @@ void ADialogueRunner::PreInitializeComponents()
}

OnRunOptions(Options);
};
});

VirtualMachine->DoesFunctionExist = [this](const std::string& FunctionName) -> bool
VirtualMachine->OnCheckFunctionExist.BindLambda([this](const FString& FunctionName) -> bool
{
return YarnSubsystem()->GetYarnLibraryRegistry()->HasFunction(FName(UTF8_TO_TCHAR(FunctionName.c_str())));
};
return YarnSubsystem()->GetYarnLibraryRegistry()->HasFunction(FName(*FunctionName));
});

VirtualMachine->GetExpectedFunctionParamCount = [this](const std::string& FunctionName) -> int
VirtualMachine->OnGetFunctionParamNum.BindLambda([this](const FString& FunctionName) -> int
{
return YarnSubsystem()->GetYarnLibraryRegistry()->GetExpectedFunctionParamCount(FName(UTF8_TO_TCHAR(FunctionName.c_str())));
};
return YarnSubsystem()->GetYarnLibraryRegistry()->GetExpectedFunctionParamCount(FName(*FunctionName));
});

VirtualMachine->CallFunction = [this](const std::string& FunctionName, const std::vector<Yarn::FValue>& Parameters) -> Yarn::FValue
VirtualMachine->OnCallFunction.BindLambda([this](const FString& FunctionName, const TArray<Yarn::FValue>& Parameters) -> Yarn::FValue
{
return YarnSubsystem()->GetYarnLibraryRegistry()->CallFunction(
FName(UTF8_TO_TCHAR(FunctionName.c_str())),
TArray<Yarn::FValue>(Parameters.data(), Parameters.size())
FName(*FunctionName),
Parameters
);
};
});

VirtualMachine->CommandHandler = [this](Yarn::Command& Command)
VirtualMachine->OnCommand.AddLambda([this](const Yarn::Command& Command)
{
UE_LOG(LogYarnSpinner, Log, TEXT("Received command \"%s\""), UTF8_TO_TCHAR(Command.Text.c_str()));
YS_LOG("Received command \"%s\"", *Command.Text);

FString CommandText = FString(UTF8_TO_TCHAR(Command.Text.c_str()));
const FString& CommandText = Command.Text;

TArray<FString> CommandElements;
CommandText.ParseIntoArray(CommandElements, TEXT(" "));

if (CommandElements.Num() == 0)
{
TArray<FString> EmptyParameters;
UE_LOG(LogYarnSpinner, Error, TEXT("Command received, but was unable to parse it."));
OnRunCommand(FString("(unknown)"), EmptyParameters);
OnRunCommand(FString("(unknown)"), TArray<FString>());
return;
}

FName CommandName = FName(CommandElements[0]);
const FName CommandName = FName(CommandElements[0]);
CommandElements.RemoveAt(0);

auto Lib = YarnSubsystem()->GetYarnLibraryRegistry();
const UYarnLibraryRegistry* const Lib = YarnSubsystem()->GetYarnLibraryRegistry();

if (Lib->HasCommand(CommandName))
{
Expand All @@ -150,23 +148,23 @@ void ADialogueRunner::PreInitializeComponents()

// Haven't handled the function yet, so call the DialogueRunner's handler
OnRunCommand(CommandName.ToString(), CommandElements);
};
});

VirtualMachine->NodeStartHandler = [this](std::string NodeName)
VirtualMachine->OnNodeStart.AddLambda( [this](const FString& NodeName)
{
UE_LOG(LogYarnSpinner, Log, TEXT("Received node start \"%s\""), UTF8_TO_TCHAR(NodeName.c_str()));
};
UE_LOG(LogYarnSpinner, Log, TEXT("Received node start \"%s\""), *NodeName);
});

VirtualMachine->NodeCompleteHandler = [this](std::string NodeName)
VirtualMachine->OnNodeComplete.AddLambda([this](const FString& NodeName)
{
UE_LOG(LogYarnSpinner, Log, TEXT("Received node complete \"%s\""), UTF8_TO_TCHAR(NodeName.c_str()));
};
UE_LOG(LogYarnSpinner, Log, TEXT("Received node complete \"%s\""), *NodeName);
});

VirtualMachine->DialogueCompleteHandler = [this]()
VirtualMachine->OnDialogueComplete.AddLambda([this]()
{
UE_LOG(LogYarnSpinner, Log, TEXT("Received dialogue complete"));
OnDialogueEnded();
};
});
}


Expand Down Expand Up @@ -223,7 +221,7 @@ void ADialogueRunner::StartDialogue(FName NodeName)
return;
}

bool bNodeSelected = VirtualMachine->SetNode(TCHAR_TO_UTF8(*NodeName.ToString()));
bool bNodeSelected = VirtualMachine->SetNode(NodeName.ToString());

if (bNodeSelected)
{
Expand Down Expand Up @@ -289,64 +287,44 @@ void ADialogueRunner::SelectOption(UOption* Option)
}
}


void ADialogueRunner::Log(std::string Message, Type Severity)
{
FString MessageText = FString(UTF8_TO_TCHAR(Message.c_str()));

switch (Severity)
{
case Type::INFO:
YS_LOG("YarnSpinner: %s", *MessageText);
break;
case Type::WARNING:
YS_WARN("YarnSpinner: %s", *MessageText);
break;
case Type::ERROR:
YS_ERR("YarnSpinner: %s", *MessageText);
break;
}
}


void ADialogueRunner::SetValue(std::string Name, bool bValue)
void ADialogueRunner::SetValue(const FString& Name, bool bValue)
{
YS_LOG("Setting variable %s to bool %i", UTF8_TO_TCHAR(Name.c_str()), bValue)
YS_LOG("Setting variable %s to bool %i", *Name, bValue);
YarnSubsystem()->SetValue(Name, bValue);
}


void ADialogueRunner::SetValue(std::string Name, float Value)
void ADialogueRunner::SetValue(const FString& Name, float Value)
{
YS_LOG("Setting variable %s to float %f", UTF8_TO_TCHAR(Name.c_str()), Value)
YS_LOG("Setting variable %s to float %f", *Name, Value);
YarnSubsystem()->SetValue(Name, Value);
}


void ADialogueRunner::SetValue(std::string Name, std::string Value)
void ADialogueRunner::SetValue(const FString& Name, const FString& Value)
{
YS_LOG("Setting variable %s to string %s", UTF8_TO_TCHAR(Name.c_str()), UTF8_TO_TCHAR(Value.c_str()))
YS_LOG("Setting variable %s to string %s", *Name, *Value);
YarnSubsystem()->SetValue(Name, Value);
}


bool ADialogueRunner::HasValue(std::string Name)
bool ADialogueRunner::HasValue(const FString& Name)
{
return YarnSubsystem()->HasValue(Name);
}


Yarn::FValue ADialogueRunner::GetValue(std::string Name)
Yarn::FValue ADialogueRunner::GetValue(const FString& Name)
{
Yarn::FValue Value = YarnSubsystem()->GetValue(Name);
YS_LOG("Retrieving variable %s with value %s", UTF8_TO_TCHAR(Name.c_str()), *Value.ConvertToString());
YS_LOG("Retrieving variable %s with value %s", *Name, *Value.ConvertToString());
return Value;
}


void ADialogueRunner::ClearValue(std::string Name)
void ADialogueRunner::ClearValue(const FString& Name)
{
YS_LOG("Clearing variable %s", UTF8_TO_TCHAR(Name.c_str()))
YS_LOG("Clearing variable %s", *Name);
YarnSubsystem()->ClearValue(Name);
}

Expand All @@ -364,7 +342,7 @@ UYarnSubsystem* ADialogueRunner::YarnSubsystem() const

void ADialogueRunner::GetDisplayTextForLine(ULine* Line, const Yarn::Line& YarnLine)
{
const FName LineID = FName(YarnLine.LineID.c_str());
const FName LineID = FName(*YarnLine.LineID);

// This assumes that we only ever care about lines that actually exist in .yarn files (rather than allowing extra lines in .csv files)
if (!YarnProject || !YarnProject->Lines.Contains(LineID))
Expand All @@ -379,9 +357,9 @@ void ADialogueRunner::GetDisplayTextForLine(ULine* Line, const Yarn::Line& YarnL

// Apply substitutions
FFormatOrderedArguments FormatArgs;
for (auto Substitution : YarnLine.Substitutions)
for (const FString& Substitution : YarnLine.Substitutions)
{
FormatArgs.Emplace(FText::FromString(UTF8_TO_TCHAR(Substitution.c_str())));
FormatArgs.Emplace(FText::FromString(Substitution));
}

const FText TextWithSubstitutions = (LocalisedDisplayText.IsEmptyOrWhitespace()) ? FText::Format(NonLocalisedDisplayText, FormatArgs) : FText::Format(LocalisedDisplayText, FormatArgs);
Expand Down
2 changes: 1 addition & 1 deletion Source/YarnSpinner/Private/Library/YarnFunctionLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ TOptional<Yarn::FValue> UYarnFunctionLibrary::CallFunction(FName FunctionName, T
YS_WARN_FUNC("Could not get return parameter '%s' for function '%s'", *ReturnValue->Name.ToString(), *FunctionName.ToString())
return Result;
}
Result = Yarn::FValue(TCHAR_TO_UTF8(*StringParam->GetPropertyValue_InContainer(FuncParams.GetStructMemory())));
Result = Yarn::FValue(StringParam->GetPropertyValue_InContainer(FuncParams.GetStructMemory()));
break;
}
}
Expand Down
4 changes: 2 additions & 2 deletions Source/YarnSpinner/Private/Library/YarnLibraryRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ void UYarnLibraryRegistry::AddFunction(const FYSLSAction& Func)
}
else
{
Param.Value = Yarn::FValue(TCHAR_TO_UTF8(*InParam.DefaultValue));
Param.Value = Yarn::FValue(InParam.DefaultValue);
}

FuncDetail.InParams.Add(Param);
Expand Down Expand Up @@ -355,7 +355,7 @@ void UYarnLibraryRegistry::AddCommand(const FYSLSAction& Cmd)
}
else
{
Param.Value = Yarn::FValue(TCHAR_TO_UTF8(*InParam.DefaultValue));
Param.Value = InParam.DefaultValue;
}

CmdDetail.InParams.Add(Param);
Expand Down
10 changes: 5 additions & 5 deletions Source/YarnSpinner/Private/YarnSpinner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

#include "YarnSpinner.h"

#include "Modules/ModuleManager.h"
#include "Interfaces/IPluginManager.h"
#include "Misc/MessageDialog.h"
#include "Misc/YSLogging.h"
#include "Modules/ModuleManager.h"

THIRD_PARTY_INCLUDES_START
#include <google/protobuf/stubs/logging.h>
Expand All @@ -16,9 +15,10 @@ THIRD_PARTY_INCLUDES_END



void UnrealLogHandler(google::protobuf::LogLevel level, const char* filename, int line,
const std::string& message) {
UE_LOG(LogYarnSpinner, Warning, TEXT("Protobuf: %s"), message.c_str());
void UnrealLogHandler([[maybe_unused]] google::protobuf::LogLevel Level, [[maybe_unused]] const char* Filename,
[[maybe_unused]] int Line, const std::string& Message)
{
YS_WARN("Protobuf: %hs", Message.c_str());
}


Expand Down
Loading

0 comments on commit e868311

Please sign in to comment.