Skip to content

Files

Latest commit

6481a4e · Nov 25, 2021

History

History
198 lines (144 loc) · 7.76 KB

common-types.md

File metadata and controls

198 lines (144 loc) · 7.76 KB

Common Types for C++ in Flax

String

For character strings container Flax uses String class that holds a null-terminated text, encoded in UTF-16 (as Char type, 2-bytes per character) and provides extensive API for string operations like splitting, formatting, merging, etc.

#include "Engine/Core/Types/String.h"

String myText = TEXT("hello there"); // string from constant
String substring = myText.Substring(0, 5);
String connected = myText + TEXT(" ") + substring; // join strings
int32 length = connected.Length(); // access string length
const Char* str = connected.Get(); // access string memory buffer
String objectName = this->ToString(); // most of C++ types implement ToString() method
String formatted = String::Format(TEXT("my custom message number {0}"), 11); // format strings like a pro
LOG(Info, "Connected: {0}", connected); // print to log

For ANSI and UTF-8 strings use StringAnsi that holds characters in char format (1 byte per-char).

To learn more about string formatting see this documentation.

StringView

StringView holds information about a text, except it's not allocated inside it (unlike String does) but just provided as a view to a characters sequence with it's length. It doesn't have to be null-terminated. It's used in various Engine APIs and gets implicitly created from String or constant strings.

#include "Engine/Core/Types/StringView.h"

StringView myText = TEXT("hello there"); // string view from constant
StringView fromStr = this->ToString(); // string view from string
LOG(Info, "Connected: {0}", myText); // print to log

For ANSI and UTF-8 strings use StringAnsiView that uses characters in char format (1 byte per-char).

StringBuilder

StringBuilder is just like String except it uses resizable Array under the hood to provide better performance when generating longer strings (eg. generating log message).

#include "Engine/Core/Types/StringBuilder.h"

StringBuilder sb;
sb.Append(TEXT("here")); // append strings to the buffer
sb.Append(TEXT(" comes "));
sb.Append(11); // automatic formatting of basic types
sb.AppendFormat(TEXT(" and {0}"), 12); // append formatted text
String str = sb.ToString(); // extract String (or use ToStringView)
LOG(Info, "sb: {0}", str); // print to log

Variant

Variant is a multi-purpose value container for generic data types including:

  • basic types (eg. int, float, bool)
  • common types (eg. String, Guid)
  • math types (eg. Vector3, Transform, BoundingBox)
  • collections (eg. Array<>, Dictionary<>)
  • object references (eg. Asset*, Actor*)
  • enum types (eg. ShadowsCastingMode)
  • structure types (eg. RayCastHit)
  • raw data (eg. byte[])
  • C# objects references (eg. MonoObject*)

It contains wide scripting API for accessing data and querying the value type including casting and comparisions. It can be serialized to raw bytes stream or to json (and loaded back). Scripting API supports automatic translation between Variant in C++ and object in C#.

#include "Engine/Core/Types/Variant.h"

Variant myValue = 11; // store int
LOG(Info, "Variant type: {0}, value: {1}", myValue.Type.ToString(), myValue.ToString());
float asFloat = (float)myValue;
myValue = Vector3(1, 2, 3); // store Vector3
LOG(Info, "Variant type: {0}, value: {1}", myValue.Type.ToString(), myValue.ToString());
myValue = this; // store object reference
LOG(Info, "Variant type: {0}, value: {1}", myValue.Type.ToString(), myValue.ToString());

Guid

Guid is Globally Unique Identifier that uses 128 bits to encode a number that is meant to be unique. Guids are used for objects identification - each Asset has unique ID and every scripting object uses it too. This allows to reference objects and assets by their ID rather than name. It also means fast objects searching via quick lookup.

#include "Engine/Core/Types/Guid.h"

Guid objId = this->GetID(); // get this object id
auto obj = Scripting::FindObject<ScriptingObject>(objId); // find object by id
LOG(Info, "id: {0}", objId); // print to log

Tip

Flax Guid uses different string represenation compared to .Net Guid. In C# use FlaxEngine.Json.JsonSerializer.GetStringID(id) to print System.Guid to string in Flax-format (and ParseID to parse it back).

Nullable

For optional values use Nullable<> type that supports holding value that can be undefined (not specified).

#include "Engine/Core/Types/Nullable.h"

Nullable<int32> optionA;
LOG(Info, "Is Set? {0}", optionA.HasValue());
if (optionA.HasValue())
	LOG(Info, "Value {0}", optionA.GetValue());
optionA = 11;
LOG(Info, "Is Set? {0}", optionA.HasValue());
if (optionA.HasValue())
	LOG(Info, "Value {0}", optionA.GetValue());

Pair

Pair<Key, Value> is a structure that wraps the Key and Value together and can be used to easily connect two values together. Utility method ToPair converts two values into a pair structure.

#include "Engine/Core/Types/Pair.h"

Pair<int32, float> pair1(11, 200.0f);
int32 key = pair1.First;
float value = pair1.Second;
auto pair2 = ToPair(12, 230.0f);

Span

Span<> is a small container for raw data pointer and data length.

#include "Engine/Core/Types/Span.h"

byte rawData[] = { 1, 2, 3, 4, 5};
Span<byte> span1(rawData, ARRAY_COUNT(rawData));
byte* ptr = span1.Get(); // memory pointer
int32 length = span1.Length(); // amount of items

DataContainer

DataContainer<> works just like Span<> except it can contain self allocated memory block and supports easy data serialization and operation with other types. Can be used to manage raw data in memory with an ease. Also, BytesContainer which is DataContainer<byte> can be used to hold pure bytes data.

#include "Engine/Core/Types/DataContainer.h"

DataContainer<float> someFloats;
someFloats.Allocate(10); // Allocate memory for 10 floats
for (int32 i = 0; i < someFloats.Length(); i++)
	someFloats.Get()[i] = 11.0f;

byte rawData[] = { 1, 2, 3, 4, 5};
BytesContainer rawBytes;
rawBytes.Link(rawData, ARRAY_COUNT(rawData)); // Link static data without allocating
rawBytes.Copy(rawData, ARRAY_COUNT(rawData)); // Copy static data into self allocated memory

DateTime

To perform operations based date and calendar use in-built DateTime type which contains numerous functionalities such as: date math operations and conversion to string. It uses ticks in 100 nanoseconds resolution since January 1, 0001 A.D. to represent the date and time. Flax also supports accessing current system time in both Local and UTC time (implemented on all supported platforms).

#include "Engine/Core/Types/DateTime.h"

DateTime currentDateTime = DateTime::Now();
LOG(Info, "Date and time: {0}", currentDateTime); // print to log
int32 year = currentDateTime.GetYear();
int32 hour = currentDateTime.GetHour();
int32 minute = currentDateTime.GetMinute();

TimeSpan

TimeSpan defines a difference between two moments in time. For instance it can be used to perform math on DateTime or to perform conversion between seconds and milliseconds. It offers wide scripting API for timespan calculations.

#include "Engine/Core/Types/TimeSpan.h"
#include "Engine/Core/Types/DateTime.h"

auto time1 = DateTime::Now();
Platform::Sleep(10);
auto time2 = DateTime::Now();
TimeSpan timeDiff = time2 - time1; // compute time difference
LOG(Info, "Time diff: {0}", timeDiff); // print to log
double miliseconds = timeDiff.GetTotalMilliseconds();

Version

Version represents the version number made of major, minor, build and revision numbers. Can be easily parsed from string, compared or converted into string.

#include "Engine/Core/Types/Version.h"

Version version1(1, 0);
Version version2(1, 3, 323, 15);
LOG(Info, "Version1: {0}", version1.ToString());
LOG(Info, "Version2: {0}", version2.ToString());