diff --git a/module/Base/AABB.cpp b/module/Base/AABB.cpp index dd528b40..a266a0ea 100644 --- a/module/Base/AABB.cpp +++ b/module/Base/AABB.cpp @@ -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) diff --git a/module/Base/AABB.hpp b/module/Base/AABB.hpp index f88660b1..b27f7e7e 100644 --- a/module/Base/AABB.hpp +++ b/module/Base/AABB.hpp @@ -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. */ diff --git a/module/Base/Circle.cpp b/module/Base/Circle.cpp index ea3c752f..bfee1a82 100644 --- a/module/Base/Circle.cpp +++ b/module/Base/Circle.cpp @@ -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) diff --git a/module/Base/Circle.hpp b/module/Base/Circle.hpp index 51a841cc..c23fa87a 100644 --- a/module/Base/Circle.hpp +++ b/module/Base/Circle.hpp @@ -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. */ diff --git a/module/Base/Color3.cpp b/module/Base/Color3.cpp index 9c1618df..fff00fed 100644 --- a/module/Base/Color3.cpp +++ b/module/Base/Color3.cpp @@ -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 diff --git a/module/Base/Color3.hpp b/module/Base/Color3.hpp index 244618d9..3030d29a 100644 --- a/module/Base/Color3.hpp +++ b/module/Base/Color3.hpp @@ -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. */ diff --git a/module/Base/Color4.cpp b/module/Base/Color4.cpp index 8881bc33..aae90da2 100644 --- a/module/Base/Color4.cpp +++ b/module/Base/Color4.cpp @@ -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 diff --git a/module/Base/Color4.hpp b/module/Base/Color4.hpp index 418c9de1..dca55016 100644 --- a/module/Base/Color4.hpp +++ b/module/Base/Color4.hpp @@ -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 diff --git a/module/Base/Quaternion.cpp b/module/Base/Quaternion.cpp index 622b616e..aae654c5 100644 --- a/module/Base/Quaternion.cpp +++ b/module/Base/Quaternion.cpp @@ -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) diff --git a/module/Base/Quaternion.hpp b/module/Base/Quaternion.hpp index a95d1751..7564fb4b 100644 --- a/module/Base/Quaternion.hpp +++ b/module/Base/Quaternion.hpp @@ -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. */ diff --git a/module/Base/Shared.cpp b/module/Base/Shared.cpp index 2646459f..cb69873f 100644 --- a/module/Base/Shared.cpp +++ b/module/Base/Shared.cpp @@ -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, ...) { diff --git a/module/Base/Shared.hpp b/module/Base/Shared.hpp index 308b544a..6f27fc06 100644 --- a/module/Base/Shared.hpp +++ b/module/Base/Shared.hpp @@ -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 diff --git a/module/Base/Sphere.cpp b/module/Base/Sphere.cpp index b88d76a1..38760f7c 100644 --- a/module/Base/Sphere.cpp +++ b/module/Base/Sphere.cpp @@ -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) diff --git a/module/Base/Sphere.hpp b/module/Base/Sphere.hpp index 7e608b59..4eb80daa 100644 --- a/module/Base/Sphere.hpp +++ b/module/Base/Sphere.hpp @@ -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. */ diff --git a/module/Base/Vector2.cpp b/module/Base/Vector2.cpp index db14ccf4..ef96a55d 100644 --- a/module/Base/Vector2.cpp +++ b/module/Base/Vector2.cpp @@ -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) diff --git a/module/Base/Vector2.hpp b/module/Base/Vector2.hpp index b229f13d..52815c28 100644 --- a/module/Base/Vector2.hpp +++ b/module/Base/Vector2.hpp @@ -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. */ diff --git a/module/Base/Vector2i.cpp b/module/Base/Vector2i.cpp index 68634d8e..ccc254c1 100644 --- a/module/Base/Vector2i.cpp +++ b/module/Base/Vector2i.cpp @@ -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) diff --git a/module/Base/Vector2i.hpp b/module/Base/Vector2i.hpp index 7ba497d1..b9b97c62 100644 --- a/module/Base/Vector2i.hpp +++ b/module/Base/Vector2i.hpp @@ -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. */ diff --git a/module/Base/Vector3.cpp b/module/Base/Vector3.cpp index 8dbc7252..32f054f7 100644 --- a/module/Base/Vector3.cpp +++ b/module/Base/Vector3.cpp @@ -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) diff --git a/module/Base/Vector3.hpp b/module/Base/Vector3.hpp index 79def2c0..631740df 100644 --- a/module/Base/Vector3.hpp +++ b/module/Base/Vector3.hpp @@ -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. */ diff --git a/module/Base/Vector4.cpp b/module/Base/Vector4.cpp index a9a0019c..c6d009fc 100644 --- a/module/Base/Vector4.cpp +++ b/module/Base/Vector4.cpp @@ -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) diff --git a/module/Base/Vector4.hpp b/module/Base/Vector4.hpp index 066b8c8b..c5993bc5 100644 --- a/module/Base/Vector4.hpp +++ b/module/Base/Vector4.hpp @@ -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. */