1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 00:37:15 +01:00

Implement formatting on math types.

Just a helper method to help you generate strings from math types more easilly. A bit risky if you're dumb and don't know how format specifiers work in C because it provides direct access to those.
This commit is contained in:
Sandu Liviu Catalin 2020-09-03 20:33:51 +03:00
parent db6cf1cdde
commit b18d0a129a
22 changed files with 397 additions and 0 deletions

View File

@ -3,6 +3,7 @@
#include "Base/Sphere.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
#include "Base/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
@ -733,6 +734,33 @@ Int32 AABB::IsSphereInsideFastEx(Value x, Value y, Value z, Value r) const
return IsSphereInsideFast(Sphere(x, y, z, r));
}
// ------------------------------------------------------------------------------------------------
LightObj AABB::Format(const String & spec, StackStrF & fmt) const
{
String out;
// Attempt to build the format string
if (!BuildFormatString(out, fmt, 6, spec))
{
return LightObj{}; // Default to null
}
// Empty string is unacceptable
else if (out.empty())
{
STHROWF("Unable to build a valid format string.");
}
// Grab a temporary buffer
Buffer buff(out.size());
// Generate the string
Buffer::SzType n = buff.WriteF(0, out.c_str(), min.x, min.y, min.z, max.x, max.y, max.z);
// Did the format failed?
if (!n && !out.empty())
{
STHROWF("Format failed. Please check format specifier and parameter count.");
}
// Return the resulted string
return LightObj{buff.Begin< SQChar >(), static_cast< SQInteger >(n)};
}
// ------------------------------------------------------------------------------------------------
const AABB & AABB::Get(StackStrF & str)
{
@ -810,6 +838,7 @@ void Register_AABB(HSQUIRRELVM vm)
// Member Methods
.FmtFunc(_SC("SetStr"), &AABB::SetStr)
.Func(_SC("Clear"), &AABB::Clear)
.FmtFunc(_SC("Format"), &AABB::Format)
.Func(_SC("DefineScalar"), &AABB::DefineScalar)
.Func(_SC("DefineVector3"), &AABB::DefineVector3)
.Func(_SC("DefineVector3Ex"), &AABB::DefineVector3Ex)

View File

@ -466,6 +466,11 @@ struct AABB
*/
Int32 IsSphereInsideFastEx(Value x, Value y, Value z, Value r) const;
/* --------------------------------------------------------------------------------------------
* Generate a formatted string with the values from this instance.
*/
LightObj Format(const String & spec, StackStrF & fmt) const;
/* --------------------------------------------------------------------------------------------
* Extract the values for components of the AABB type from a string.
*/

View File

@ -2,6 +2,7 @@
#include "Base/Circle.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
#include "Base/Buffer.hpp"
#include "Library/Numeric/Random.hpp"
// ------------------------------------------------------------------------------------------------
@ -494,6 +495,33 @@ Array Circle::ToPointsArray(SQInteger num_segments) const
return arr;
}
// ------------------------------------------------------------------------------------------------
LightObj Circle::Format(const String & spec, StackStrF & fmt) const
{
String out;
// Attempt to build the format string
if (!BuildFormatString(out, fmt, 3, spec))
{
return LightObj{}; // Default to null
}
// Empty string is unacceptable
else if (out.empty())
{
STHROWF("Unable to build a valid format string.");
}
// Grab a temporary buffer
Buffer buff(out.size());
// Generate the string
Buffer::SzType n = buff.WriteF(0, out.c_str(), pos.x, pos.y, rad);
// Did the format failed?
if (!n && !out.empty())
{
STHROWF("Format failed. Please check format specifier and parameter count.");
}
// Return the resulted string
return LightObj{buff.Begin< SQChar >(), static_cast< SQInteger >(n)};
}
// ------------------------------------------------------------------------------------------------
const Circle & Circle::Get(StackStrF & str)
{
@ -566,6 +594,7 @@ void Register_Circle(HSQUIRRELVM vm)
.Func(_SC("SetPositionEx"), &Circle::SetPositionEx)
.FmtFunc(_SC("SetStr"), &Circle::SetStr)
.Func(_SC("Clear"), &Circle::Clear)
.FmtFunc(_SC("Format"), &Circle::Format)
.Func(_SC("ToPointsArray"), &Circle::ToPointsArray)
// Member Overloads
.Overload< void (Circle::*)(void) >(_SC("Generate"), &Circle::Generate)

View File

@ -416,6 +416,11 @@ struct Circle
*/
Array ToPointsArray(SQInteger num_segments) const;
/* --------------------------------------------------------------------------------------------
* Generate a formatted string with the values from this instance.
*/
LightObj Format(const String & spec, StackStrF & fmt) const;
/* --------------------------------------------------------------------------------------------
* Extract the values for components of the Circle type from a string.
*/

View File

@ -3,6 +3,7 @@
#include "Base/Color4.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
#include "Base/Buffer.hpp"
#include "Library/Numeric/Random.hpp"
// ------------------------------------------------------------------------------------------------
@ -631,6 +632,33 @@ void Color3::Inverse()
b = static_cast< Value >(~b);
}
// ------------------------------------------------------------------------------------------------
LightObj Color3::Format(const String & spec, StackStrF & fmt) const
{
String out;
// Attempt to build the format string
if (!BuildFormatString(out, fmt, 3, spec))
{
return LightObj{}; // Default to null
}
// Empty string is unacceptable
else if (out.empty())
{
STHROWF("Unable to build a valid format string.");
}
// Grab a temporary buffer
Buffer buff(out.size());
// Generate the string
Buffer::SzType n = buff.WriteF(0, out.c_str(), r, g, b);
// Did the format failed?
if (!n && !out.empty())
{
STHROWF("Format failed. Please check format specifier and parameter count.");
}
// Return the resulted string
return LightObj{buff.Begin< SQChar >(), static_cast< SQInteger >(n)};
}
// ------------------------------------------------------------------------------------------------
const Color3 & Color3::Get(StackStrF & str)
{
@ -714,6 +742,7 @@ void Register_Color3(HSQUIRRELVM vm)
.FmtFunc(_SC("SetStr"), &Color3::SetStr)
.FmtFunc(_SC("SetName"), &Color3::SetName)
.Func(_SC("Clear"), &Color3::Clear)
.FmtFunc(_SC("Format"), &Color3::Format)
.Func(_SC("Random"), &Color3::Random)
.Func(_SC("Inverse"), &Color3::Inverse)
// Member Overloads

View File

@ -498,6 +498,11 @@ struct Color3
*/
void Inverse();
/* --------------------------------------------------------------------------------------------
* Generate a formatted string with the values from this instance.
*/
LightObj Format(const String & spec, StackStrF & fmt) const;
/* --------------------------------------------------------------------------------------------
* Extract the values for components of the Color3 type from a string.
*/

View File

@ -3,6 +3,7 @@
#include "Base/Color3.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
#include "Base/Buffer.hpp"
#include "Library/Numeric/Random.hpp"
// ------------------------------------------------------------------------------------------------
@ -666,6 +667,33 @@ void Color4::Inverse()
a = static_cast< Value >(~a);
}
// ------------------------------------------------------------------------------------------------
LightObj Color4::Format(const String & spec, StackStrF & fmt) const
{
String out;
// Attempt to build the format string
if (!BuildFormatString(out, fmt, 4, spec))
{
return LightObj{}; // Default to null
}
// Empty string is unacceptable
else if (out.empty())
{
STHROWF("Unable to build a valid format string.");
}
// Grab a temporary buffer
Buffer buff(out.size());
// Generate the string
Buffer::SzType n = buff.WriteF(0, out.c_str(), r, g, b, a);
// Did the format failed?
if (!n && !out.empty())
{
STHROWF("Format failed. Please check format specifier and parameter count.");
}
// Return the resulted string
return LightObj{buff.Begin< SQChar >(), static_cast< SQInteger >(n)};
}
// ------------------------------------------------------------------------------------------------
const Color4 & Color4::Get(StackStrF & str)
{
@ -753,6 +781,7 @@ void Register_Color4(HSQUIRRELVM vm)
.FmtFunc(_SC("SetStr"), &Color4::SetStr)
.FmtFunc(_SC("SetName"), &Color4::SetName)
.Func(_SC("Clear"), &Color4::Clear)
.FmtFunc(_SC("Format"), &Color4::Format)
.Func(_SC("Random"), &Color4::Random)
.Func(_SC("Inverse"), &Color4::Inverse)
// Member Overloads

View File

@ -507,6 +507,11 @@ struct Color4
* Extract the values for components of the Color4 type from a string.
*/
static const Color4 & GetEx(SQChar delim, StackStrF & str);
/* --------------------------------------------------------------------------------------------
* Generate a formatted string with the values from this instance.
*/
LightObj Format(const String & spec, StackStrF & fmt) const;
};
} // Namespace:: SqMod

View File

@ -4,6 +4,7 @@
#include "Base/Vector4.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
#include "Base/Buffer.hpp"
#include "Library/Numeric/Random.hpp"
// ------------------------------------------------------------------------------------------------
@ -719,6 +720,33 @@ const Quaternion & Quaternion::Get(StackStrF & str)
return Quaternion::GetEx(Quaternion::Delim, str);
}
// ------------------------------------------------------------------------------------------------
LightObj Quaternion::Format(const String & spec, StackStrF & fmt) const
{
String out;
// Attempt to build the format string
if (!BuildFormatString(out, fmt, 4, spec))
{
return LightObj{}; // Default to null
}
// Empty string is unacceptable
else if (out.empty())
{
STHROWF("Unable to build a valid format string.");
}
// Grab a temporary buffer
Buffer buff(out.size());
// Generate the string
Buffer::SzType n = buff.WriteF(0, out.c_str(), x, y, z, w);
// Did the format failed?
if (!n && !out.empty())
{
STHROWF("Format failed. Please check format specifier and parameter count.");
}
// Return the resulted string
return LightObj{buff.Begin< SQChar >(), static_cast< SQInteger >(n)};
}
// ------------------------------------------------------------------------------------------------
const Quaternion & Quaternion::GetEx(SQChar delim, StackStrF & str)
{
@ -797,6 +825,7 @@ void Register_Quaternion(HSQUIRRELVM vm)
.Func(_SC("SetVector4"), &Quaternion::SetVector4)
.FmtFunc(_SC("SetStr"), &Quaternion::SetStr)
.Func(_SC("Clear"), &Quaternion::Clear)
.FmtFunc(_SC("Format"), &Quaternion::Format)
.Func(_SC("DotProduct"), &Quaternion::DotProduct)
.Func(_SC("Normalize"), &Quaternion::Normalize)
.Func(_SC("FromAngleAxis"), &Quaternion::FromAngleAxis)

View File

@ -439,6 +439,11 @@ struct Quaternion
*/
Quaternion NlerpEx(const Quaternion & quat, Value t, bool shortest_path) const;
/* --------------------------------------------------------------------------------------------
* Generate a formatted string with the values from this instance.
*/
LightObj Format(const String & spec, StackStrF & fmt) const;
/* --------------------------------------------------------------------------------------------
* Extract the values for components of the Quaternion type from a string.
*/

View File

@ -889,6 +889,58 @@ Color3 GetColorStr(CSStr name)
}
}
// ------------------------------------------------------------------------------------------------
bool BuildFormatString(String & out, StackStrF & fmt, Uint32 arg, const String & spec)
{
// Is the specified string empty?
if (fmt.mLen <= 0)
{
return false; // Nothing to parse
}
// Backup current string size so we can revert back if anything
const size_t size = out.size();
// Number of processed arguments
Uint32 count = 0;
// Attempt to predict the required space
out.reserve(size + static_cast< size_t >(fmt.mLen) + arg * 2);
// Previously processed characters and the current one
SQChar p2, p1=0, c=0;
// Look for the value specifier in the specified string
for (SQInteger i = 0; i <= fmt.mLen; ++i) {
// Advance to the peaked character
p2 = p1, p1 = c, c = fmt.mPtr[i];
// The escape character is literal?
if (p1 == '\\' && p2 == '\\')
{
out.push_back('\\');
// Safeguard against a sequence of escape characters
p1 = 0;
}
// The marker is literal?
if (p1 == '\\' && c == '$')
{
out.push_back('$');
}
// Is this a marker?
else if (c == '$') {
// Did we run out of allowed arguments?
if (count++ < arg) {
out.append(spec); // Append the format specifier to the string
} else {
// Discard everything so far
out.resize(size);
// Signal failure
SqThrowF("Requested (%u) values but only (%u) available", count, arg);
}
} else if (c != '\\') {
// Append the current character to the string
out.push_back(c);
}
}
// Parsed successfully
return true;
}
// ------------------------------------------------------------------------------------------------
void SqThrowLastF(CSStr msg, ...)
{

View File

@ -170,4 +170,9 @@ template < typename T > inline void SqSetDelimiter(SQInteger c)
T::Delim = ConvTo< SQChar >::From(c);
}
/* ------------------------------------------------------------------------------------------------
* Used internally to build format strings for math types.
*/
bool BuildFormatString(String & out, StackStrF & fmt, Uint32 arg, const String & spec);
} // Namespace:: SqMod

View File

@ -2,6 +2,7 @@
#include "Base/Sphere.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
#include "Base/Buffer.hpp"
#include "Library/Numeric/Random.hpp"
// ------------------------------------------------------------------------------------------------
@ -467,6 +468,33 @@ Sphere Sphere::Abs() const
return {pos.Abs(), std::fabs(rad)};
}
// ------------------------------------------------------------------------------------------------
LightObj Sphere::Format(const String & spec, StackStrF & fmt) const
{
String out;
// Attempt to build the format string
if (!BuildFormatString(out, fmt, 4, spec))
{
return LightObj{}; // Default to null
}
// Empty string is unacceptable
else if (out.empty())
{
STHROWF("Unable to build a valid format string.");
}
// Grab a temporary buffer
Buffer buff(out.size());
// Generate the string
Buffer::SzType n = buff.WriteF(0, out.c_str(), pos.x, pos.y, pos.z, rad);
// Did the format failed?
if (!n && !out.empty())
{
STHROWF("Format failed. Please check format specifier and parameter count.");
}
// Return the resulted string
return LightObj{buff.Begin< SQChar >(), static_cast< SQInteger >(n)};
}
// ------------------------------------------------------------------------------------------------
const Sphere & Sphere::Get(StackStrF & str)
{
@ -538,6 +566,7 @@ void Register_Sphere(HSQUIRRELVM vm)
.Func(_SC("SetPositionEx"), &Sphere::SetPositionEx)
.FmtFunc(_SC("SetStr"), &Sphere::SetStr)
.Func(_SC("Clear"), &Sphere::Clear)
.FmtFunc(_SC("Format"), &Sphere::Format)
// Member Overloads
.Overload< void (Sphere::*)(void) >(_SC("Generate"), &Sphere::Generate)
.Overload< void (Sphere::*)(Val, Val, bool) >(_SC("Generate"), &Sphere::Generate)

View File

@ -410,6 +410,11 @@ struct Sphere
*/
Sphere Abs() const;
/* --------------------------------------------------------------------------------------------
* Generate a formatted string with the values from this instance.
*/
LightObj Format(const String & spec, StackStrF & fmt) const;
/* --------------------------------------------------------------------------------------------
* Extract the values for components of the Sphere type from a string.
*/

View File

@ -3,6 +3,7 @@
#include "Base/Vector2i.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
#include "Base/Buffer.hpp"
#include "Library/Numeric/Random.hpp"
// ------------------------------------------------------------------------------------------------
@ -375,6 +376,33 @@ Vector2 Vector2::Abs() const
return {std::fabs(x), std::fabs(y)};
}
// ------------------------------------------------------------------------------------------------
LightObj Vector2::Format(const String & spec, StackStrF & fmt) const
{
String out;
// Attempt to build the format string
if (!BuildFormatString(out, fmt, 2, spec))
{
return LightObj{}; // Default to null
}
// Empty string is unacceptable
else if (out.empty())
{
STHROWF("Unable to build a valid format string.");
}
// Grab a temporary buffer
Buffer buff(out.size());
// Generate the string
Buffer::SzType n = buff.WriteF(0, out.c_str(), x, y);
// Did the format failed?
if (!n && !out.empty())
{
STHROWF("Format failed. Please check format specifier and parameter count.");
}
// Return the resulted string
return LightObj{buff.Begin< SQChar >(), static_cast< SQInteger >(n)};
}
// ------------------------------------------------------------------------------------------------
const Vector2 & Vector2::Get(StackStrF & str)
{
@ -441,6 +469,7 @@ void Register_Vector2(HSQUIRRELVM vm)
.Func(_SC("SetVector2i"), &Vector2::SetVector2i)
.FmtFunc(_SC("SetStr"), &Vector2::SetStr)
.Func(_SC("Clear"), &Vector2::Clear)
.FmtFunc(_SC("Format"), &Vector2::Format)
// Member Overloads
.Overload< void (Vector2::*)(void) >(_SC("Generate"), &Vector2::Generate)
.Overload< void (Vector2::*)(Val, Val) >(_SC("Generate"), &Vector2::Generate)

View File

@ -338,6 +338,11 @@ struct Vector2
*/
Vector2 Abs() const;
/* --------------------------------------------------------------------------------------------
* Generate a formatted string with the values from this instance.
*/
LightObj Format(const String & spec, StackStrF & fmt) const;
/* --------------------------------------------------------------------------------------------
* Extract the values for components of the Vector2 type from a string.
*/

View File

@ -3,6 +3,7 @@
#include "Base/Vector2.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
#include "Base/Buffer.hpp"
#include "Library/Numeric/Random.hpp"
// ------------------------------------------------------------------------------------------------
@ -521,6 +522,33 @@ Vector2i Vector2i::Abs() const
return {std::abs(x), std::abs(y)};
}
// ------------------------------------------------------------------------------------------------
LightObj Vector2i::Format(const String & spec, StackStrF & fmt) const
{
String out;
// Attempt to build the format string
if (!BuildFormatString(out, fmt, 2, spec))
{
return LightObj{}; // Default to null
}
// Empty string is unacceptable
else if (out.empty())
{
STHROWF("Unable to build a valid format string.");
}
// Grab a temporary buffer
Buffer buff(out.size());
// Generate the string
Buffer::SzType n = buff.WriteF(0, out.c_str(), x, y);
// Did the format failed?
if (!n && !out.empty())
{
STHROWF("Format failed. Please check format specifier and parameter count.");
}
// Return the resulted string
return LightObj{buff.Begin< SQChar >(), static_cast< SQInteger >(n)};
}
// ------------------------------------------------------------------------------------------------
const Vector2i & Vector2i::Get(StackStrF & str)
{
@ -587,6 +615,7 @@ void Register_Vector2i(HSQUIRRELVM vm)
.Func(_SC("SetVector2"), &Vector2i::SetVector2)
.FmtFunc(_SC("SetStr"), &Vector2i::SetStr)
.Func(_SC("Clear"), &Vector2i::Clear)
.FmtFunc(_SC("Format"), &Vector2i::Format)
// Member Overloads
.Overload< void (Vector2i::*)(void) >(_SC("Generate"), &Vector2i::Generate)
.Overload< void (Vector2i::*)(Val, Val) >(_SC("Generate"), &Vector2i::Generate)

View File

@ -443,6 +443,11 @@ struct Vector2i
*/
Vector2i Abs() const;
/* --------------------------------------------------------------------------------------------
* Generate a formatted string with the values from this instance.
*/
LightObj Format(const String & spec, StackStrF & fmt) const;
/* --------------------------------------------------------------------------------------------
* Extract the values for components of the Vector2i type from a string.
*/

View File

@ -4,6 +4,7 @@
#include "Base/Quaternion.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
#include "Base/Buffer.hpp"
#include "Library/Numeric/Random.hpp"
// ------------------------------------------------------------------------------------------------
@ -628,6 +629,33 @@ void Vector3::CenterRotateYZBy(Value degrees, const Vector3 & center)
z = static_cast< Value >((y * sn) + (z * cs)) + center.y;
}
// ------------------------------------------------------------------------------------------------
LightObj Vector3::Format(const String & spec, StackStrF & fmt) const
{
String out;
// Attempt to build the format string
if (!BuildFormatString(out, fmt, 3, spec))
{
return LightObj{}; // Default to null
}
// Empty string is unacceptable
else if (out.empty())
{
STHROWF("Unable to build a valid format string.");
}
// Grab a temporary buffer
Buffer buff(out.size());
// Generate the string
Buffer::SzType n = buff.WriteF(0, out.c_str(), x, y, z);
// Did the format failed?
if (!n && !out.empty())
{
STHROWF("Format failed. Please check format specifier and parameter count.");
}
// Return the resulted string
return LightObj{buff.Begin< SQChar >(), static_cast< SQInteger >(n)};
}
// ------------------------------------------------------------------------------------------------
const Vector3 & Vector3::Get(StackStrF & str)
{
@ -715,6 +743,7 @@ void Register_Vector3(HSQUIRRELVM vm)
.Func(_SC("SetQuaternionEx"), &Vector3::SetQuaternionEx)
.FmtFunc(_SC("SetStr"), &Vector3::SetStr)
.Func(_SC("Clear"), &Vector3::Clear)
.FmtFunc(_SC("Format"), &Vector3::Format)
.Func(_SC("Normalize"), &Vector3::Normalize)
.Func(_SC("Dot"), &Vector3::DotProduct)
.Func(_SC("AbsDot"), &Vector3::AbsDotProduct)

View File

@ -489,6 +489,11 @@ struct Vector3
*/
void CenterRotateYZBy(Value degrees, const Vector3 & center);
/* --------------------------------------------------------------------------------------------
* Generate a formatted string with the values from this instance.
*/
LightObj Format(const String & spec, StackStrF & fmt) const;
/* --------------------------------------------------------------------------------------------
* Extract the values for components of the Vector3 type from a string.
*/

View File

@ -4,6 +4,7 @@
#include "Base/Quaternion.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
#include "Base/Buffer.hpp"
#include "Library/Numeric/Random.hpp"
// ------------------------------------------------------------------------------------------------
@ -470,6 +471,33 @@ const Vector4 & Vector4::Get(StackStrF & str)
return Vector4::GetEx(Vector4::Delim, str);
}
// ------------------------------------------------------------------------------------------------
LightObj Vector4::Format(const String & spec, StackStrF & fmt) const
{
String out;
// Attempt to build the format string
if (!BuildFormatString(out, fmt, 4, spec))
{
return LightObj{}; // Default to null
}
// Empty string is unacceptable
else if (out.empty())
{
STHROWF("Unable to build a valid format string.");
}
// Grab a temporary buffer
Buffer buff(out.size());
// Generate the string
Buffer::SzType n = buff.WriteF(0, out.c_str(), x, y, z, w);
// Did the format failed?
if (!n && !out.empty())
{
STHROWF("Format failed. Please check format specifier and parameter count.");
}
// Return the resulted string
return LightObj{buff.Begin< SQChar >(), static_cast< SQInteger >(n)};
}
// ------------------------------------------------------------------------------------------------
const Vector4 & Vector4::GetEx(SQChar delim, StackStrF & str)
{
@ -540,6 +568,7 @@ void Register_Vector4(HSQUIRRELVM vm)
.Func(_SC("SetQuaternionEx"), &Vector4::SetQuaternionEx)
.FmtFunc(_SC("SetStr"), &Vector4::SetStr)
.Func(_SC("Clear"), &Vector4::Clear)
.FmtFunc(_SC("Format"), &Vector4::Format)
// Member Overloads
.Overload< void (Vector4::*)(void) >(_SC("Generate"), &Vector4::Generate)
.Overload< void (Vector4::*)(Val, Val) >(_SC("Generate"), &Vector4::Generate)

View File

@ -363,6 +363,11 @@ struct Vector4
*/
Vector4 Abs() const;
/* --------------------------------------------------------------------------------------------
* Generate a formatted string with the values from this instance.
*/
LightObj Format(const String & spec, StackStrF & fmt) const;
/* --------------------------------------------------------------------------------------------
* Extract the values for components of the Vector4 type from a string.
*/