chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
namespace Lib.@string.buffers.convert;
|
||||
|
||||
[Guid("c5f1292a-e692-422b-9261-b5ae3451cd7c")]
|
||||
internal sealed class StringBuilderToString : Instance<StringBuilderToString>
|
||||
{
|
||||
[Output(Guid = "71C4AA96-9A20-494A-9A28-6DD33A867ED2")]
|
||||
public readonly Slot<string> String = new();
|
||||
|
||||
public StringBuilderToString()
|
||||
{
|
||||
String.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var stringBuilder = InputBuffer.GetValue(context);
|
||||
if (stringBuilder == null)
|
||||
{
|
||||
String.Value = System.String.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
String.Value = stringBuilder.ToString();
|
||||
}
|
||||
|
||||
[Input(Guid = "4690405C-343C-4F4B-BF32-51F5D2CC9C76")]
|
||||
public readonly InputSlot<StringBuilder> InputBuffer = new();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "c5f1292a-e692-422b-9261-b5ae3451cd7c"/*StringBuilderToString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "4690405c-343c-4f4b-bf32-51f5d2cc9c76"/*InputBuffer*/,
|
||||
"DefaultValue": null
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "c5f1292a-e692-422b-9261-b5ae3451cd7c"/*StringBuilderToString*/,
|
||||
"Description": "Converts the 'Builder' output of a [StringBuilder] or [BuildRandomString] to a string",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "4690405c-343c-4f4b-bf32-51f5d2cc9c76"/*InputBuffer*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "71c4aa96-9a20-494a-9a28-6dd33a867ed2"/*String*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
namespace Lib.@string.buffers.transform;
|
||||
|
||||
[Guid("7dff2da3-30e3-4ad9-bfc6-d6800f90fca8")]
|
||||
internal sealed class StringInsert : Instance<StringInsert>
|
||||
{
|
||||
[Output(Guid = "3f9aa46b-e9d5-43fd-b463-fcdd48ded406")]
|
||||
public readonly Slot<string> Result = new();
|
||||
|
||||
public StringInsert()
|
||||
{
|
||||
Result.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var original = Original.GetValue(context);
|
||||
var insert = Insertion.GetValue(context);
|
||||
if (string.IsNullOrEmpty(original) || string.IsNullOrEmpty(insert))
|
||||
return;
|
||||
|
||||
var maxPosition = original.Length - insert.Length;
|
||||
|
||||
if (maxPosition <= 0)
|
||||
return;
|
||||
|
||||
var position = Position.GetValue(context);
|
||||
|
||||
if (UseModuloPosition.GetValue(context))
|
||||
{
|
||||
position = Math.Abs(position) % maxPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
position.Clamp(0, maxPosition);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Result.Value = original.Remove(position, insert.Length).Insert(position, insert);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.Warning("Failed to insert string:" + e);
|
||||
}
|
||||
}
|
||||
|
||||
[Input(Guid = "11d0a66a-e2e9-4267-9458-f9844a482235")]
|
||||
public readonly InputSlot<string> Original = new();
|
||||
|
||||
[Input(Guid = "b00a60d3-c525-4e65-8b84-2084521d0d2d")]
|
||||
public readonly InputSlot<string> Insertion = new();
|
||||
|
||||
[Input(Guid = "B5709B52-E755-4046-8E71-EEAD5A01303A")]
|
||||
public readonly InputSlot<int> Position = new();
|
||||
|
||||
[Input(Guid = "C103C06D-BF68-4C5C-967E-DDD939221292")]
|
||||
public readonly InputSlot<bool> UseModuloPosition = new();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "7dff2da3-30e3-4ad9-bfc6-d6800f90fca8"/*StringInsert*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "11d0a66a-e2e9-4267-9458-f9844a482235"/*Original*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "b00a60d3-c525-4e65-8b84-2084521d0d2d"/*Insertion*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "b5709b52-e755-4046-8e71-eead5a01303a"/*Position*/,
|
||||
"DefaultValue": 0
|
||||
},
|
||||
{
|
||||
"Id": "c103c06d-bf68-4c5c-967e-ddd939221292"/*UseModuloPosition*/,
|
||||
"DefaultValue": true
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "7dff2da3-30e3-4ad9-bfc6-d6800f90fca8"/*StringInsert*/,
|
||||
"Description": "Can replace and move characters to any position within a string",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "11d0a66a-e2e9-4267-9458-f9844a482235"/*Original*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Description": "Input for the string into which something is to be inserted",
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "b00a60d3-c525-4e65-8b84-2084521d0d2d"/*Insertion*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 90.0
|
||||
},
|
||||
"Description": "String to be inserted into the 'original' string",
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "b5709b52-e755-4046-8e71-eead5a01303a"/*Position*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 135.0
|
||||
},
|
||||
"Description": "Defines the position at which the 'Insertion' string is inserted into the 'original' string\n\nThis value can be animated"
|
||||
},
|
||||
{
|
||||
"InputId": "c103c06d-bf68-4c5c-967e-ddd939221292"/*UseModuloPosition*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 180.0
|
||||
},
|
||||
"Description": "If modulo is activated, the string position is looped if the value is too high or too low"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "3f9aa46b-e9d5-43fd-b463-fcdd48ded406"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
|
||||
namespace Lib.@string.combine;
|
||||
|
||||
[Guid("98bd1491-6e69-4ae0-9fc1-0be8e6a72d32")]
|
||||
internal sealed class BlendStrings : Instance<BlendStrings>
|
||||
{
|
||||
[Output(Guid = "1bb629bb-dd30-48df-b6b4-3245af10dc09")]
|
||||
public readonly Slot<string> Result = new();
|
||||
|
||||
public BlendStrings()
|
||||
{
|
||||
Result.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var needsUpdate = false;
|
||||
|
||||
var stringInputs = InputStrings.GetCollectedTypedInputs();
|
||||
var stringCount = stringInputs.Count;
|
||||
|
||||
needsUpdate |= Blend.GetChangedValue(context, ref _blend, out var floatIndex);
|
||||
|
||||
floatIndex = floatIndex.Clamp(0, stringCount - 1.0001f);
|
||||
var index = (int)floatIndex;
|
||||
|
||||
string strA;
|
||||
string strB;
|
||||
|
||||
InputStrings.DirtyFlag.Clear();
|
||||
if (stringCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (stringCount == 1)
|
||||
{
|
||||
needsUpdate |= stringInputs[0].GetChangedValue(context, ref _strA, out strA);
|
||||
strB = strA;
|
||||
//strB = strA = stringInputs[0].GetValue(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
needsUpdate |= stringInputs[index].GetChangedValue(context, ref _strA, out strA);
|
||||
needsUpdate |= stringInputs[index+1].GetChangedValue(context, ref _strB, out strB);
|
||||
// strA = stringInputs[index].GetValue(context);
|
||||
// strB = stringInputs[index+1].GetValue(context);
|
||||
}
|
||||
|
||||
var blendIndex = floatIndex - index;
|
||||
|
||||
strA ??= string.Empty;
|
||||
strB ??= string.Empty;
|
||||
|
||||
if (strA == string.Empty && strB == string.Empty)
|
||||
{
|
||||
Result.Value = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
BlendSpread.GetChangedValue(context, ref _blendSpread, out var blendSpread);
|
||||
//var blendSpread = BlendSpread.GetValue(context);
|
||||
|
||||
var totalMaxLength = MaxLength.GetValue(context).Clamp(1, 10000); // 10000 is going to be slow!
|
||||
var maxLength = Math.Max(strA.Length, strB.Length).Clamp(1,totalMaxLength);
|
||||
|
||||
needsUpdate|=Scramble.GetChangedValue(context, ref _scrambleFactor, out var scrambleFactor);
|
||||
needsUpdate|=ScrambleSeed.GetChangedValue(context, ref _scrambleSeed, out var scrambleSeed);
|
||||
|
||||
//var scrambleFactor = Scramble.GetValue(context);
|
||||
//var scrambleSeed = ScrambleSeed.GetValue(context);
|
||||
|
||||
needsUpdate|=Characters.GetChangedValue(context, ref _chars, out var chars);
|
||||
|
||||
//var chars = Characters.GetValue(context);
|
||||
if (string.IsNullOrEmpty(chars))
|
||||
chars = FallbackChars;
|
||||
|
||||
if (!needsUpdate)
|
||||
return;
|
||||
|
||||
|
||||
_stringBuilder.Clear();
|
||||
|
||||
//var needsUpdate = strA != _strA || strB != _strB || chars != _chars;
|
||||
|
||||
for (int charIndex = 0; charIndex < maxLength; charIndex++)
|
||||
{
|
||||
var charA = GetCharOrSpace(strA, charIndex);
|
||||
var charB = GetCharOrSpace(strB, charIndex);
|
||||
|
||||
if (charA == '\n' || charB == '\n')
|
||||
{
|
||||
_stringBuilder.Append(charA);
|
||||
continue;
|
||||
}
|
||||
|
||||
var charCount = chars.Length;
|
||||
var charAInt = chars.IndexOf(charA).Clamp(0,charCount-1);
|
||||
var charBInt = chars.IndexOf(charB).Clamp(0,charCount-1);
|
||||
|
||||
var hashA = MathUtils.Hash01((uint)((charIndex * 123 + scrambleSeed/100)));
|
||||
var scrambleOffset = hashA < scrambleFactor
|
||||
? (MathUtils.Hash01((uint)(charIndex * 123 + scrambleSeed )) - 0.5f) * charCount
|
||||
: 0;
|
||||
|
||||
var x = maxLength <= 1 ? 0: charIndex/ (float)(maxLength-1);
|
||||
var blendProgressForChar = ProgressTransition(x, blendIndex, blendSpread);
|
||||
//var blendedValue = (int)(charAInt + (charBInt - charAInt) * blendProgressForChar + scrambleOffset).Clamp(0, charCount-1);
|
||||
var blendedValue = (int)(charBInt + (charAInt - charBInt) * blendProgressForChar + scrambleOffset).Clamp(0, charCount-1);
|
||||
var s = chars[blendedValue];
|
||||
_stringBuilder.Append(s);
|
||||
}
|
||||
|
||||
Result.Value = _stringBuilder.ToString();
|
||||
}
|
||||
|
||||
// private static bool GetValue<T>(in InputSlot<T> input, in EvaluationContext context, ref T oldValue, out T newValue)
|
||||
// {
|
||||
// newValue = input.GetValue(context);
|
||||
// return newValue != oldValue;
|
||||
// }
|
||||
|
||||
private string _strA, _strB, _chars;
|
||||
|
||||
private float _blend;
|
||||
private float _blendSpread;
|
||||
|
||||
private readonly StringBuilder _stringBuilder = new();
|
||||
|
||||
|
||||
private static char GetCharOrSpace(string str, int index)
|
||||
{
|
||||
if (index < 0 || index >= str.Length)
|
||||
return ' ';
|
||||
|
||||
return str[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a normalized progress value for a given t and spreading.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is easier visualized than explained. Please have a look at: https://www.desmos.com/calculator/vd2njtavqq
|
||||
/// </remarks>
|
||||
public static float ProgressTransition(float x, float progress, float spread=1)
|
||||
{
|
||||
return ((x-progress)/spread - progress + 1).Clamp(0,1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private const string FallbackChars = " .-/\\?#<^*()&AÁÄBCDEFGHIJKLMNOÄÓÖPQRSTUÜÜÚVWXYZaäåbcdefghijklmnoóöpqrsßtuúüvwxyz0123456789";
|
||||
|
||||
[Input(Guid = "EB2D968D-0CE0-48F1-A014-29475A3F0B04")]
|
||||
public readonly MultiInputSlot<string> InputStrings = new();
|
||||
|
||||
|
||||
|
||||
[Input(Guid = "2EFD4A0C-958C-49F6-86CB-F8D9FD6FB308")]
|
||||
public readonly InputSlot<float> Blend= new();
|
||||
|
||||
[Input(Guid = "C3E0CDE4-FECF-4802-A287-A173A6A12518")]
|
||||
public readonly InputSlot<float> BlendSpread= new();
|
||||
|
||||
[Input(Guid = "DC4E5B79-53E5-463A-92AD-D9BB1F2B0495")]
|
||||
public readonly InputSlot<float> Scramble= new();
|
||||
|
||||
[Input(Guid = "D95E112F-B89A-4AA1-954B-10521C0A3815")]
|
||||
public readonly InputSlot<int> ScrambleSeed= new();
|
||||
|
||||
[Input(Guid = "D70DA276-C047-42DB-A921-5C1263613CBB")]
|
||||
public readonly InputSlot<int> MaxLength= new();
|
||||
|
||||
|
||||
[Input(Guid = "48DE52F6-9B8D-4C12-9336-40091824BE43")]
|
||||
public readonly InputSlot<string> Characters= new();
|
||||
|
||||
[Input(Guid = "3197934e-d0ed-4a81-9dc1-2cc63d97ac6f")]
|
||||
public readonly InputSlot<string> InputTextA = new();
|
||||
|
||||
[Input(Guid = "CCC21ECC-2877-4FE7-8D78-F7E2A708D762")]
|
||||
public readonly InputSlot<string> InputTextB= new();
|
||||
|
||||
private float _scrambleFactor;
|
||||
private int _scrambleSeed;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "98bd1491-6e69-4ae0-9fc1-0be8e6a72d32"/*BlendStrings*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "2efd4a0c-958c-49f6-86cb-f8d9fd6fb308"/*Blend*/,
|
||||
"DefaultValue": 0.0
|
||||
},
|
||||
{
|
||||
"Id": "3197934e-d0ed-4a81-9dc1-2cc63d97ac6f"/*InputTextA*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "48de52f6-9b8d-4c12-9336-40091824be43"/*Characters*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "c3e0cde4-fecf-4802-a287-a173a6a12518"/*BlendSpread*/,
|
||||
"DefaultValue": 0.5
|
||||
},
|
||||
{
|
||||
"Id": "ccc21ecc-2877-4fe7-8d78-f7e2a708d762"/*InputTextB*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "d70da276-c047-42db-a921-5c1263613cbb"/*MaxLength*/,
|
||||
"DefaultValue": 1000
|
||||
},
|
||||
{
|
||||
"Id": "d95e112f-b89a-4aa1-954b-10521c0a3815"/*ScrambleSeed*/,
|
||||
"DefaultValue": 0
|
||||
},
|
||||
{
|
||||
"Id": "dc4e5b79-53e5-463a-92ad-d9bb1f2b0495"/*Scramble*/,
|
||||
"DefaultValue": 0.0
|
||||
},
|
||||
{
|
||||
"Id": "eb2d968d-0ce0-48f1-a014-29475a3f0b04"/*InputStrings*/,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "98bd1491-6e69-4ae0-9fc1-0be8e6a72d32"/*BlendStrings*/,
|
||||
"Description": "Blends two strings with a scrambling animation similar to an airport flight display board.",
|
||||
"SymbolTags": "9",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "2efd4a0c-958c-49f6-86cb-f8d9fd6fb308"/*Blend*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 135.0
|
||||
},
|
||||
"GroupTitle": "Blend Settings",
|
||||
"Description": "BlendSettings"
|
||||
},
|
||||
{
|
||||
"InputId": "3197934e-d0ed-4a81-9dc1-2cc63d97ac6f"/*InputTextA*/,
|
||||
"Relevancy": "Relevant",
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"GroupTitle": "String A",
|
||||
"Usage": "Multiline"
|
||||
},
|
||||
{
|
||||
"InputId": "48de52f6-9b8d-4c12-9336-40091824be43"/*Characters*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 345.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "c3e0cde4-fecf-4802-a287-a173a6a12518"/*BlendSpread*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 180.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "ccc21ecc-2877-4fe7-8d78-f7e2a708d762"/*InputTextB*/,
|
||||
"Relevancy": "Relevant",
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 90.0
|
||||
},
|
||||
"GroupTitle": "String B",
|
||||
"Usage": "Multiline"
|
||||
},
|
||||
{
|
||||
"InputId": "d70da276-c047-42db-a921-5c1263613cbb"/*MaxLength*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 270.0
|
||||
},
|
||||
"AddPadding": "True"
|
||||
},
|
||||
{
|
||||
"InputId": "d95e112f-b89a-4aa1-954b-10521c0a3815"/*ScrambleSeed*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 225.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "dc4e5b79-53e5-463a-92ad-d9bb1f2b0495"/*Scramble*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 180.0
|
||||
},
|
||||
"AddPadding": "True"
|
||||
},
|
||||
{
|
||||
"InputId": "eb2d968d-0ce0-48f1-a014-29475a3f0b04"/*InputStrings*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "1bb629bb-dd30-48df-b6b4-3245af10dc09"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
namespace Lib.@string.combine;
|
||||
|
||||
[Guid("48ab9824-76ca-4238-800f-9cf95311e6c0")]
|
||||
internal sealed class CombineStrings : Instance<CombineStrings>
|
||||
{
|
||||
[Output(Guid = "{E47BF25E-351A-44E6-84C6-AD3ABC93531A}")]
|
||||
public readonly Slot<string> Result = new();
|
||||
|
||||
public CombineStrings()
|
||||
{
|
||||
Result.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
_stringBuilder.Clear();
|
||||
var separator = Separator.GetValue(context).Replace("\\n", "\n");
|
||||
|
||||
var isFirst = true;
|
||||
foreach (var input in Input.GetCollectedTypedInputs())
|
||||
{
|
||||
if (!isFirst && !string.IsNullOrEmpty(separator))
|
||||
_stringBuilder.Append(separator);
|
||||
|
||||
var t = input.GetValue(context);
|
||||
if(!string.IsNullOrEmpty(t))
|
||||
_stringBuilder.Append(t);
|
||||
|
||||
isFirst = false;
|
||||
}
|
||||
Result.Value = _stringBuilder.ToString();
|
||||
Input.DirtyFlag.Clear();
|
||||
}
|
||||
|
||||
private readonly StringBuilder _stringBuilder = new();
|
||||
|
||||
[Input(Guid = "{B5E72715-9339-484F-B197-5A28CD823798}")]
|
||||
public readonly MultiInputSlot<string> Input = new();
|
||||
|
||||
[Input(Guid = "C832BA89-F4AE-4C47-B62B-52DA52A09556")]
|
||||
public readonly InputSlot<string> Separator = new();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "48ab9824-76ca-4238-800f-9cf95311e6c0"/*CombineStrings*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "b5e72715-9339-484f-b197-5a28cd823798"/*Input*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "c832ba89-f4ae-4c47-b62b-52da52a09556"/*Separator*/,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "48ab9824-76ca-4238-800f-9cf95311e6c0"/*CombineStrings*/,
|
||||
"Description": "Combines any number with strings with the provided optional separator.\n\nTo add line breaks use \"\\n\".\n\nAlternative titles: Concat, Join",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "b5e72715-9339-484f-b197-5a28cd823798"/*Input*/,
|
||||
"Relevancy": "Required",
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "c832ba89-f4ae-4c47-b62b-52da52a09556"/*Separator*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Description": "Optional separator inserted between elements. \nUse \"\\n\" to insert line breaks.",
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "e47bf25e-351a-44e6-84c6-ad3abc93531a"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Lib.@string.combine;
|
||||
|
||||
[Guid("abf1ec99-049d-474c-9023-5302d5a5c804")]
|
||||
internal sealed class FloatListToString : Instance<FloatListToString>
|
||||
{
|
||||
[Output(Guid = "fcd2597b-31cb-443e-a9a9-6647bc406763")]
|
||||
public readonly Slot<string> Output = new();
|
||||
|
||||
public FloatListToString()
|
||||
{
|
||||
Output.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var values = Value.GetValue(context);
|
||||
if (values == null || values.Count == 0)
|
||||
Output.Value = "";
|
||||
|
||||
var format = Format.GetValue(context);
|
||||
var sep = Separator.GetValue(context);
|
||||
if (string.IsNullOrWhiteSpace(format))
|
||||
{
|
||||
format = "{0:0.00}";
|
||||
}
|
||||
|
||||
if (sep == null)
|
||||
{
|
||||
sep = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
sep = sep.Replace("\\n", "\n");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_stringBuilder.Clear();
|
||||
|
||||
if (values != null)
|
||||
{
|
||||
foreach (var v in values)
|
||||
{
|
||||
_stringBuilder.Append(v.ToString(format, CultureInfo.InvariantCulture));
|
||||
_stringBuilder.Append(sep);
|
||||
}
|
||||
}
|
||||
|
||||
Output.Value = _stringBuilder
|
||||
.ToString(); //string.IsNullOrEmpty(format) ? values.ToString(CultureInfo.InvariantCulture) : string.Format(CultureInfo.InvariantCulture, format, values);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
Output.Value = "Invalid Format";
|
||||
}
|
||||
}
|
||||
|
||||
private StringBuilder _stringBuilder = new();
|
||||
|
||||
[Input(Guid = "010C814B-BE7D-4BF9-82BE-1869217BD1AD")]
|
||||
public readonly InputSlot<List<float>> Value = new();
|
||||
|
||||
[Input(Guid = "ab4eef8d-8b76-48ff-8a3c-d9fc352b5a6c")]
|
||||
public readonly InputSlot<string> Format = new();
|
||||
|
||||
[Input(Guid = "FA19703A-BE58-4C51-8674-A0EAFBCF96C4")]
|
||||
public readonly InputSlot<string> Separator = new();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "abf1ec99-049d-474c-9023-5302d5a5c804"/*FloatListToString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "010c814b-be7d-4bf9-82be-1869217bd1ad"/*Value*/,
|
||||
"DefaultValue": {
|
||||
"Values": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"Id": "ab4eef8d-8b76-48ff-8a3c-d9fc352b5a6c"/*Format*/,
|
||||
"DefaultValue": "{0:0.000}"
|
||||
},
|
||||
{
|
||||
"Id": "fa19703a-be58-4c51-8674-a0eafbcf96c4"/*Separator*/,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "abf1ec99-049d-474c-9023-5302d5a5c804"/*FloatListToString*/,
|
||||
"Description": "Converts a list of float numbers to String",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "010c814b-be7d-4bf9-82be-1869217bd1ad"/*Value*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "ab4eef8d-8b76-48ff-8a3c-d9fc352b5a6c"/*Format*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "fa19703a-be58-4c51-8674-a0eafbcf96c4"/*Separator*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "fcd2597b-31cb-443e-a9a9-6647bc406763"/*Output*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
namespace Lib.@string.combine;
|
||||
|
||||
[Guid("04d0d6d7-8c40-4d18-aa44-6806c51fe139")]
|
||||
internal sealed class StringRepeat : Instance<StringRepeat>
|
||||
{
|
||||
[Output(Guid = "568d04ca-3b13-4ed3-93f9-f0fbf804d96e")]
|
||||
public readonly Slot<string> Result = new();
|
||||
|
||||
public StringRepeat()
|
||||
{
|
||||
Result.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var content = Fragment.GetValue(context);
|
||||
var count = Count.GetValue(context).Clamp(0,1000);
|
||||
if (count == 0 || string.IsNullOrEmpty(content))
|
||||
{
|
||||
Result.Value = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result.Value = new StringBuilder().Insert(0, content, count).ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[Input(Guid = "3804f72d-7541-4877-a417-d029a20035d8")]
|
||||
public readonly InputSlot<string> Fragment = new();
|
||||
|
||||
|
||||
[Input(Guid = "DA681B55-9537-4D86-B31A-38223CC0BC71")]
|
||||
public readonly InputSlot<int> Count = new();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "04d0d6d7-8c40-4d18-aa44-6806c51fe139"/*StringRepeat*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "3804f72d-7541-4877-a417-d029a20035d8"/*Fragment*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "da681b55-9537-4d86-b31a-38223cc0bc71"/*Count*/,
|
||||
"DefaultValue": 5
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "04d0d6d7-8c40-4d18-aa44-6806c51fe139"/*StringRepeat*/,
|
||||
"Description": "Repeats a string multiple times.",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "3804f72d-7541-4877-a417-d029a20035d8"/*Fragment*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "da681b55-9537-4d86-b31a-38223cc0bc71"/*Count*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 180.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "568d04ca-3b13-4ed3-93f9-f0fbf804d96e"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Lib.@string.convert;
|
||||
|
||||
[Guid("39c96cfd-dedf-4f76-a471-d1c26c9ba9fa")]
|
||||
internal sealed class FloatToString : Instance<FloatToString>
|
||||
{
|
||||
[Output(Guid = "{C63A1977-A594-490D-B5FB-DE4D40BAD016}")]
|
||||
public readonly Slot<string> Output = new();
|
||||
|
||||
public FloatToString()
|
||||
{
|
||||
Output.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var v = Value.GetValue(context);
|
||||
var s = Format.GetValue(context);
|
||||
try
|
||||
{
|
||||
Output.Value = string.IsNullOrEmpty(s) ? v.ToString(CultureInfo.InvariantCulture) : string.Format(CultureInfo.InvariantCulture, s, v);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
Output.Value = "Invalid Format";
|
||||
}
|
||||
}
|
||||
|
||||
[Input(Guid = "{F36E4078-2608-4308-AB5F-077C05B1181A}")]
|
||||
public readonly InputSlot<float> Value = new();
|
||||
|
||||
[Input(Guid = "{B2B32C44-62D8-4ACB-A9A7-4856EC7A33BB}")]
|
||||
public readonly InputSlot<string> Format = new();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "39c96cfd-dedf-4f76-a471-d1c26c9ba9fa"/*FloatToString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "b2b32c44-62d8-4acb-a9a7-4856ec7a33bb"/*Format*/,
|
||||
"DefaultValue": "{0:0.000}"
|
||||
},
|
||||
{
|
||||
"Id": "f36e4078-2608-4308-ab5f-077c05b1181a"/*Value*/,
|
||||
"DefaultValue": 0.0
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "39c96cfd-dedf-4f76-a471-d1c26c9ba9fa"/*FloatToString*/,
|
||||
"Description": "Converts a float value into a string.\n\nYou can use the .net string format descriptor for various effects, like...\n\nHere are some examples for the value 1.2345\n\n{0:P1} -> 123.45%\n{0:000.000} -> 001.234\n{0:0} -> 1\n{0:G3} -> 1.23\nneed {0:1.2} cookies -> need 1.2 cookies\n",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "b2b32c44-62d8-4acb-a9a7-4856ec7a33bb"/*Format*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "f36e4078-2608-4308-ab5f-077c05b1181a"/*Value*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Min": -221.0,
|
||||
"Max": 302.0
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "c63a1977-a594-490d-b5fb-de4d40bad016"/*Output*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Lib.@string.convert;
|
||||
|
||||
[Guid("416a1c8d-4143-4de7-bcf9-466c4009112a")]
|
||||
internal sealed class IntToString : Instance<IntToString>
|
||||
{
|
||||
[Output(Guid = "460f2a09-b706-4e1e-a1fb-32eeab51524b")]
|
||||
public readonly Slot<string> Output = new();
|
||||
|
||||
public IntToString()
|
||||
{
|
||||
Output.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var v = Value.GetValue(context);
|
||||
var s = Format.GetValue(context);
|
||||
try
|
||||
{
|
||||
Output.Value = string.IsNullOrEmpty(s) ? v.ToString(CultureInfo.InvariantCulture) : string.Format(CultureInfo.InvariantCulture, s, v);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
Output.Value = "Invalid Format";
|
||||
}
|
||||
}
|
||||
|
||||
[Input(Guid = "3C1A8975-AB27-40B3-9FEE-7DE38643294A")]
|
||||
public readonly InputSlot<int> Value = new();
|
||||
|
||||
[Input(Guid = "a9dd6368-455d-4b1d-8685-02d8f7640ecf")]
|
||||
public readonly InputSlot<string> Format = new();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "416a1c8d-4143-4de7-bcf9-466c4009112a"/*IntToString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "3c1a8975-ab27-40b3-9fee-7de38643294a"/*Value*/,
|
||||
"DefaultValue": 0
|
||||
},
|
||||
{
|
||||
"Id": "a9dd6368-455d-4b1d-8685-02d8f7640ecf"/*Format*/,
|
||||
"DefaultValue": "{0:0}"
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "416a1c8d-4143-4de7-bcf9-466c4009112a"/*IntToString*/,
|
||||
"Description": "Converts an [IntValue] to a string.\n\nTip: You can override the string formatting to something like... \"{0:0} times\" add prefixes or suffixes.",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "3c1a8975-ab27-40b3-9fee-7de38643294a"/*Value*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "a9dd6368-455d-4b1d-8685-02d8f7640ecf"/*Format*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "460f2a09-b706-4e1e-a1fb-32eeab51524b"/*Output*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Lib.@string.convert;
|
||||
|
||||
[Guid("06ae6091-ce81-4e8f-ae96-83c189c70b10")]
|
||||
internal sealed class Vec3ToString : Instance<Vec3ToString>
|
||||
{
|
||||
[Output(Guid = "bc59ac99-0e6f-4d8a-8896-661b45c86ecd")]
|
||||
public readonly Slot<string> Output = new();
|
||||
|
||||
public Vec3ToString()
|
||||
{
|
||||
Output.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var v = Vector.GetValue(context);
|
||||
var s = Format.GetValue(context);
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
// Fixed width: 7 chars total (e.g., " -1.50" or " 1.50")
|
||||
Output.Value = string.Format(CultureInfo.InvariantCulture,
|
||||
"X: {0,7:F2}\nY: {1,7:F2}\nZ: {2,7:F2}", v.X, v.Y, v.Z);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replace literal \n with actual newline characters
|
||||
var formatWithNewlines = s.Replace("\\n", "\n");
|
||||
Output.Value = string.Format(CultureInfo.InvariantCulture, formatWithNewlines, v.X, v.Y, v.Z);
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
Output.Value = "Invalid Format";
|
||||
}
|
||||
}
|
||||
|
||||
[Input(Guid = "0035b185-2e0b-4854-842a-4965180177f1")]
|
||||
public readonly InputSlot<Vector3> Vector = new();
|
||||
|
||||
[Input(Guid = "045e84e3-2456-46fb-af43-30549e08afbd")]
|
||||
public readonly InputSlot<string> Format = new();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "06ae6091-ce81-4e8f-ae96-83c189c70b10"/*Vec3ToString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "0035b185-2e0b-4854-842a-4965180177f1"/*Vector*/,
|
||||
"DefaultValue": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Id": "045e84e3-2456-46fb-af43-30549e08afbd"/*Format*/,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "06ae6091-ce81-4e8f-ae96-83c189c70b10"/*Vec3ToString*/,
|
||||
"Description": "Converts a Vector3 into a string.\n\nFormats examples: \n({0:F2}, {1:F2}, {2:F2})\nResult: \n(0.00, 1.00, 2.00)\n\nX: {0,7:F2}\\nY: {1,7:F2}\\nZ: {2,7:F2} \nResult:\nX: 1.50\nY: 2.50\nZ: 3.50\n\n",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "0035b185-2e0b-4854-842a-4965180177f1"/*Vector*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Min": -221.0,
|
||||
"Max": 302.0,
|
||||
"Scale": 5.23
|
||||
},
|
||||
{
|
||||
"InputId": "045e84e3-2456-46fb-af43-30549e08afbd"/*Format*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "bc59ac99-0e6f-4d8a-8896-661b45c86ecd"/*Output*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Lib.@string.datetime;
|
||||
|
||||
[Guid("e4a38f3c-bd4c-406a-9979-bb683d79b39b")]
|
||||
internal sealed class CountDown : Instance<CountDown>
|
||||
{
|
||||
[Output(Guid = "511af1e0-9ada-46a2-8c14-0e18db506f95", DirtyFlagTrigger = DirtyFlagTrigger.Animated)]
|
||||
public readonly Slot<string> Output = new();
|
||||
|
||||
public CountDown()
|
||||
{
|
||||
Output.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
|
||||
try
|
||||
{
|
||||
var targetTime = DateTime.Today;
|
||||
var launchTime = LaunchTime.GetValue(context);
|
||||
if(DateTime.TryParse(launchTime, out var d))
|
||||
{
|
||||
targetTime = d;
|
||||
//Log.Debug("date:" + d);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warning($"invalid format for lauchTime '{launchTime}'", this);
|
||||
}
|
||||
//var v = Duration.GetValue(context);
|
||||
var duration = DateTime.Now - targetTime;
|
||||
|
||||
|
||||
var format = Format.GetValue(context);
|
||||
var outString = duration.ToString(format, CultureInfo.InvariantCulture);
|
||||
Output.Value = outString;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
//Log.Warning("Failed to format CountDown time: " + e.Message, this);
|
||||
Output.Value = "Invalid Format";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[Input(Guid = "61E5281B-B772-4BBD-B52F-E6B6310D259A")]
|
||||
public readonly InputSlot<string> LaunchTime = new();
|
||||
|
||||
[Input(Guid = "d404e744-fa84-4bc8-8aa3-e6e972d9a5a7")]
|
||||
public readonly InputSlot<string> Format = new();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "e4a38f3c-bd4c-406a-9979-bb683d79b39b"/*CountDown*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "61e5281b-b772-4bbd-b52f-e6b6310d259a"/*LaunchTime*/,
|
||||
"DefaultValue": "2021-04-17 17:00"
|
||||
},
|
||||
{
|
||||
"Id": "d404e744-fa84-4bc8-8aa3-e6e972d9a5a7"/*Format*/,
|
||||
"DefaultValue": "hh\\:mm\\:ss\\:ff"
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "e4a38f3c-bd4c-406a-9979-bb683d79b39b"/*CountDown*/,
|
||||
"Description": "Prints a formatted string counting down a duration or time to/since a fixed date.",
|
||||
"SymbolTags": "192",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "61e5281b-b772-4bbd-b52f-e6b6310d259a"/*LaunchTime*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "d404e744-fa84-4bc8-8aa3-e6e972d9a5a7"/*Format*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "511af1e0-9ada-46a2-8c14-0e18db506f95"/*Output*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
namespace Lib.@string.datetime;
|
||||
|
||||
[Guid("10acf0aa-2cb3-446b-b837-b6abe24d44da")]
|
||||
internal sealed class DateTimeToFloat : Instance<DateTimeToFloat>
|
||||
{
|
||||
[Output(Guid = "E07DC943-B32B-4037-9E84-0E50B4B67D05")]
|
||||
public readonly Slot<float> Output = new ();
|
||||
|
||||
public DateTimeToFloat()
|
||||
{
|
||||
Output.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var dateTime = Value.GetValue(context);
|
||||
var offset = HourOffset.GetValue(context);
|
||||
|
||||
var offsetSpan = new TimeSpan(0, (int)offset, (int)(offset*60 % 60), (int)(offset*60*60 % 60));
|
||||
dateTime -= offsetSpan;
|
||||
var value = OutputMapping.GetEnumValue<Modes>(context) switch
|
||||
{
|
||||
Modes.TimeOfDay_Hours => (float)(dateTime.TimeOfDay.TotalMilliseconds / (double)(60 * 60 * 1000)),
|
||||
Modes.TimeOfDay_Normalized => (float)(dateTime.TimeOfDay.TotalMilliseconds / (double)(24 * 60 * 60 * 1000)),
|
||||
Modes.DayOfTheYear => dateTime.DayOfYear,
|
||||
Modes.DayOfTheMonths => dateTime.Day,
|
||||
_ => 0f
|
||||
};
|
||||
|
||||
Output.Value = value;
|
||||
}
|
||||
|
||||
[Input(Guid = "7b432357-225c-499e-9109-61168b4be4a7")]
|
||||
public readonly InputSlot<DateTime> Value = new();
|
||||
|
||||
[Input(Guid = "5D9065A3-A124-4261-B5A9-25D969E30F73", MappedType = typeof(Modes))]
|
||||
public readonly InputSlot<int> OutputMapping = new();
|
||||
|
||||
[Input(Guid = "EC1A2E0C-4C65-45E8-BFAC-FAE10CF3A717")]
|
||||
public readonly InputSlot<float> HourOffset = new();
|
||||
|
||||
private enum Modes
|
||||
{
|
||||
TimeOfDay_Hours,
|
||||
TimeOfDay_Normalized,
|
||||
DayOfTheYear,
|
||||
DayOfTheMonths,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "10acf0aa-2cb3-446b-b837-b6abe24d44da"/*DateTimeToFloat*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "5d9065a3-a124-4261-b5a9-25d969e30f73"/*OutputMapping*/,
|
||||
"DefaultValue": 0
|
||||
},
|
||||
{
|
||||
"Id": "7b432357-225c-499e-9109-61168b4be4a7"/*Value*/,
|
||||
"DefaultValue": null
|
||||
},
|
||||
{
|
||||
"Id": "ec1a2e0c-4c65-45e8-bfac-fae10cf3a717"/*HourOffset*/,
|
||||
"DefaultValue": 0.0
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "10acf0aa-2cb3-446b-b837-b6abe24d44da"/*DateTimeToFloat*/,
|
||||
"Description": "Converts a DateTime into different float values like normalized time of day (between 0 ... 1), day of the year, etc.",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "5d9065a3-a124-4261-b5a9-25d969e30f73"/*OutputMapping*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 45.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "7b432357-225c-499e-9109-61168b4be4a7"/*Value*/,
|
||||
"Relevancy": "Required",
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "ec1a2e0c-4c65-45e8-bfac-fae10cf3a717"/*HourOffset*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 90.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "e07dc943-b32b-4037-9e84-0e50b4b67d05"/*Output*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 100.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Lib.@string.datetime;
|
||||
|
||||
[Guid("c1c3725a-0745-4ce1-874b-839810c2124c")]
|
||||
internal sealed class DateTimeToString : Instance<DateTimeToString>
|
||||
{
|
||||
[Output(Guid = "75ad6b31-2460-47fb-aa75-019e50e0fd44")]
|
||||
public readonly Slot<string> Output = new();
|
||||
|
||||
public DateTimeToString()
|
||||
{
|
||||
Output.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var v = Value.GetValue(context);
|
||||
var format = Format.GetValue(context);
|
||||
try
|
||||
{
|
||||
Output.Value = string.IsNullOrEmpty(format)
|
||||
? v.ToString(CultureInfo.InvariantCulture)
|
||||
: v.ToString(format, CultureInfo.InvariantCulture);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
Output.Value = "Invalid Format";
|
||||
}
|
||||
}
|
||||
|
||||
[Input(Guid = "C420E846-8BA2-4BE4-AD43-9F4380DA0851")]
|
||||
public readonly InputSlot<DateTime> Value = new();
|
||||
|
||||
[Input(Guid = "5af4a05f-72dc-4c0d-a728-309bf3a1b1b9")]
|
||||
public readonly InputSlot<string> Format = new();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "c1c3725a-0745-4ce1-874b-839810c2124c"/*DateTimeToString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "5af4a05f-72dc-4c0d-a728-309bf3a1b1b9"/*Format*/,
|
||||
"DefaultValue": "dddd MMMM dd, yyyy"
|
||||
},
|
||||
{
|
||||
"Id": "c420e846-8ba2-4be4-ad43-9f4380da0851"/*Value*/,
|
||||
"DefaultValue": null
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "c1c3725a-0745-4ce1-874b-839810c2124c"/*DateTimeToString*/,
|
||||
"Description": "Uses [NowAsDateTime] output to convert it into a string",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "5af4a05f-72dc-4c0d-a728-309bf3a1b1b9"/*Format*/,
|
||||
"Position": {
|
||||
"X": -133.22765,
|
||||
"Y": 40.552734
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "c420e846-8ba2-4be4-ad43-9f4380da0851"/*Value*/,
|
||||
"Relevancy": "Required",
|
||||
"Position": {
|
||||
"X": -182.1091,
|
||||
"Y": -14.074188
|
||||
},
|
||||
"Description": "Input for a 'DateTime' parameter\n\nFor example by [NowAsDateTime] operator"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "75ad6b31-2460-47fb-aa75-019e50e0fd44"/*Output*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"Links": [
|
||||
{
|
||||
"Id": "bb0ffba9-a635-495a-baa7-86fffb62fad2",
|
||||
"Title": "Custom date and time format strings",
|
||||
"Description": "Describe how to use the Format field",
|
||||
"LinkUrl": "https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings#date-and-time-separator-specifiers",
|
||||
"LinkType": "Reference"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace Lib.@string.datetime;
|
||||
|
||||
[Guid("bd8d684c-96ae-4864-84fd-ca87f98ce1a4")]
|
||||
internal sealed class NowAsDateTime : Instance<NowAsDateTime>
|
||||
{
|
||||
[Output(Guid = "99f94d1c-7d79-497d-9d42-dff8b749e493")]
|
||||
public readonly Slot<DateTime> Output = new();
|
||||
|
||||
|
||||
public NowAsDateTime()
|
||||
{
|
||||
Output.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
Output.Value = DateTime.Now;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "bd8d684c-96ae-4864-84fd-ca87f98ce1a4"/*NowAsDateTime*/,
|
||||
"Inputs": [],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "bd8d684c-96ae-4864-84fd-ca87f98ce1a4"/*NowAsDateTime*/,
|
||||
"Description": "Returns the current system time.",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "99f94d1c-7d79-497d-9d42-dff8b749e493"/*Output*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 100.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
namespace Lib.@string.datetime;
|
||||
|
||||
[Guid("a78a07f8-cf75-4a72-8952-b9ba40d6983f")]
|
||||
internal sealed class StringToDateTime : Instance<StringToDateTime>, IStatusProvider
|
||||
{
|
||||
[Output(Guid = "8D2981DD-AC26-4CC0-8646-DEFB7196085C")]
|
||||
public readonly Slot<DateTime> Output = new();
|
||||
|
||||
|
||||
public StringToDateTime()
|
||||
{
|
||||
Output.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var dateString = DateString.GetValue(context);
|
||||
if (DateTime.TryParse(dateString, out var dateTime))
|
||||
{
|
||||
Output.Value = dateTime;
|
||||
_lastStatusError = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastStatusError = $"Failed to parse {dateString} into DateTime";
|
||||
}
|
||||
}
|
||||
|
||||
private string _lastStatusError;
|
||||
|
||||
// [Input(Guid = "d4f58293-ac29-4dee-8a66-a56724bf7006")]
|
||||
// public readonly InputSlot<DateTime> Value = new InputSlot<DateTime>();
|
||||
|
||||
[Input(Guid = "5F92445D-9234-420E-919D-21CDB6FB587D")]
|
||||
public readonly InputSlot<string> DateString = new();
|
||||
|
||||
// [Input(Guid = "62d27f4c-ce64-497b-bca6-5a36bfd4232c")]
|
||||
// public readonly InputSlot<string> Format = new InputSlot<string>();
|
||||
|
||||
public IStatusProvider.StatusLevel GetStatusLevel()
|
||||
{
|
||||
return string.IsNullOrEmpty(_lastStatusError) ? IStatusProvider.StatusLevel.Success : IStatusProvider.StatusLevel.Warning;
|
||||
}
|
||||
|
||||
public string GetStatusMessage()
|
||||
{
|
||||
return _lastStatusError;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "a78a07f8-cf75-4a72-8952-b9ba40d6983f"/*StringToDateTime*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "5f92445d-9234-420e-919d-21cdb6fb587d"/*DateString*/,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "a78a07f8-cf75-4a72-8952-b9ba40d6983f"/*StringToDateTime*/,
|
||||
"Description": "Tries to parse the incoming string as a DateTime.",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "5f92445d-9234-420e-919d-21cdb6fb587d"/*DateString*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "8d2981dd-ac26-4cc0-8646-defb7196085c"/*Output*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 100.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Lib.@string.datetime;
|
||||
|
||||
[Guid("075612b1-8760-4858-ad6b-6c85a7716794")]
|
||||
internal sealed class TimeToString : Instance<TimeToString>
|
||||
{
|
||||
[Output(Guid = "d45912c1-1c26-4a80-bfff-57de6ae6ccdf")]
|
||||
public readonly Slot<string> Result = new();
|
||||
|
||||
[Input(Guid = "ecc27b89-e89a-4c01-93ad-b4750d09f2f7")]
|
||||
public readonly InputSlot<float> Input = new();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "075612b1-8760-4858-ad6b-6c85a7716794"/*TimeToString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "ecc27b89-e89a-4c01-93ad-b4750d09f2f7"/*Input*/,
|
||||
"DefaultValue": 0.0
|
||||
}
|
||||
],
|
||||
"Children": [
|
||||
{
|
||||
"Id": "11e62dfd-c9de-4714-9115-5fcdbf720331"/*Multiply*/,
|
||||
"SymbolId": "17b60044-9125-4961-8a79-ca94697b3726",
|
||||
"InputValues": [
|
||||
{
|
||||
"Id": "5ae4bb07-4214-4ec3-a499-24d9f6d404a5"/*B*/,
|
||||
"Type": "System.Single",
|
||||
"Value": 100.0
|
||||
}
|
||||
],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "1d04262b-da7f-49de-a0a3-7de7589d20af"/*Floor*/,
|
||||
"SymbolId": "55b13dee-89f8-404f-b2fe-43d5e8c54536",
|
||||
"InputValues": [],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "1e1ae105-ea95-4b2c-9e7d-32fd934fab38"/*Modulo*/,
|
||||
"SymbolId": "5202d3f6-c970-4006-933d-3c60d6c202dc",
|
||||
"InputValues": [
|
||||
{
|
||||
"Id": "62a8185f-32c0-41d2-b8be-d8c1d7178c00"/*ModuloValue*/,
|
||||
"Type": "System.Single",
|
||||
"Value": 60.0
|
||||
}
|
||||
],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "387f494b-68de-40a3-9da4-9b4bed7caf91"/*Floor*/,
|
||||
"SymbolId": "55b13dee-89f8-404f-b2fe-43d5e8c54536",
|
||||
"InputValues": [],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "4693a9d2-485e-4e3b-9f07-496181b4281f"/*Div*/,
|
||||
"SymbolId": "15fb88b2-81a1-43b8-97ba-41221293bb07",
|
||||
"InputValues": [
|
||||
{
|
||||
"Id": "a79a2f16-7a4e-464d-8af4-3e3029ae853e"/*B*/,
|
||||
"Type": "System.Single",
|
||||
"Value": 60.0
|
||||
}
|
||||
],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "58230175-3f7a-4b01-b1b6-27193dc5a0e2"/*FloatToString*/,
|
||||
"SymbolId": "39c96cfd-dedf-4f76-a471-d1c26c9ba9fa",
|
||||
"InputValues": [
|
||||
{
|
||||
"Id": "b2b32c44-62d8-4acb-a9a7-4856ec7a33bb"/*Format*/,
|
||||
"Type": "System.String",
|
||||
"Value": "{0:00}"
|
||||
}
|
||||
],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "706dc843-9a95-4cf7-bb9a-ac1a8c1d4ce2"/*String*/,
|
||||
"SymbolId": "5880cbc3-a541-4484-a06a-0e6f77cdbe8e",
|
||||
"InputValues": [
|
||||
{
|
||||
"Id": "ceeae47b-d792-471d-a825-49e22749b7b9"/*InputString*/,
|
||||
"Type": "System.String",
|
||||
"Value": "Partial Preview v03 / 2021-03-30 "
|
||||
}
|
||||
],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "98c950e9-b0c4-4cee-be31-b9cd1ee60eed"/*FloatToString*/,
|
||||
"SymbolId": "39c96cfd-dedf-4f76-a471-d1c26c9ba9fa",
|
||||
"InputValues": [
|
||||
{
|
||||
"Id": "b2b32c44-62d8-4acb-a9a7-4856ec7a33bb"/*Format*/,
|
||||
"Type": "System.String",
|
||||
"Value": "{0:00}"
|
||||
}
|
||||
],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "ac87ddda-5e7f-4d85-a22a-3af5e274c154"/*Floor*/,
|
||||
"SymbolId": "55b13dee-89f8-404f-b2fe-43d5e8c54536",
|
||||
"InputValues": [],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "cdf0eb8d-e5e0-4a5c-8efa-63f1942fa4d9"/*CombineStrings*/,
|
||||
"SymbolId": "48ab9824-76ca-4238-800f-9cf95311e6c0",
|
||||
"InputValues": [],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "e5168e43-3129-4c1d-81c6-33ef4d80ea71"/*FloatToString*/,
|
||||
"SymbolId": "39c96cfd-dedf-4f76-a471-d1c26c9ba9fa",
|
||||
"InputValues": [
|
||||
{
|
||||
"Id": "b2b32c44-62d8-4acb-a9a7-4856ec7a33bb"/*Format*/,
|
||||
"Type": "System.String",
|
||||
"Value": "{0:00}"
|
||||
}
|
||||
],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "e96babee-8ef9-411c-81f9-fdf3015b9289"/*_Time_old*/,
|
||||
"SymbolId": "9cb4d49e-135b-400b-a035-2b02c5ea6a72",
|
||||
"InputValues": [],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "f7f79af2-50d8-4bbc-bb8f-0d08fec71b29"/*Modulo*/,
|
||||
"SymbolId": "5202d3f6-c970-4006-933d-3c60d6c202dc",
|
||||
"InputValues": [
|
||||
{
|
||||
"Id": "62a8185f-32c0-41d2-b8be-d8c1d7178c00"/*ModuloValue*/,
|
||||
"Type": "System.Single",
|
||||
"Value": 100.0
|
||||
}
|
||||
],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "febcd3dc-8adf-430b-a94e-eba1c010e1a8"/*CombineStrings*/,
|
||||
"SymbolId": "48ab9824-76ca-4238-800f-9cf95311e6c0",
|
||||
"InputValues": [
|
||||
{
|
||||
"Id": "c832ba89-f4ae-4c47-b62b-52da52a09556"/*Separator*/,
|
||||
"Type": "System.String",
|
||||
"Value": ":"
|
||||
}
|
||||
],
|
||||
"Outputs": []
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"SourceParentOrChildId": "cdf0eb8d-e5e0-4a5c-8efa-63f1942fa4d9",
|
||||
"SourceSlotId": "e47bf25e-351a-44e6-84c6-ad3abc93531a",
|
||||
"TargetParentOrChildId": "00000000-0000-0000-0000-000000000000",
|
||||
"TargetSlotId": "d45912c1-1c26-4a80-bfff-57de6ae6ccdf"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "00000000-0000-0000-0000-000000000000",
|
||||
"SourceSlotId": "ecc27b89-e89a-4c01-93ad-b4750d09f2f7",
|
||||
"TargetParentOrChildId": "11e62dfd-c9de-4714-9115-5fcdbf720331",
|
||||
"TargetSlotId": "372288fa-3794-47ba-9f91-59240513217a"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "4693a9d2-485e-4e3b-9f07-496181b4281f",
|
||||
"SourceSlotId": "866642e7-17dd-4375-9d5e-2e3747a554c2",
|
||||
"TargetParentOrChildId": "1d04262b-da7f-49de-a0a3-7de7589d20af",
|
||||
"TargetSlotId": "550289db-89cb-465c-a9d8-a16dbf23cc45"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "00000000-0000-0000-0000-000000000000",
|
||||
"SourceSlotId": "ecc27b89-e89a-4c01-93ad-b4750d09f2f7",
|
||||
"TargetParentOrChildId": "1e1ae105-ea95-4b2c-9e7d-32fd934fab38",
|
||||
"TargetSlotId": "8a401e5d-295d-4403-a3af-1d6b91ce3dba"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "1e1ae105-ea95-4b2c-9e7d-32fd934fab38",
|
||||
"SourceSlotId": "4e4ebbcf-6b12-4ce7-9bec-78cd9049e239",
|
||||
"TargetParentOrChildId": "387f494b-68de-40a3-9da4-9b4bed7caf91",
|
||||
"TargetSlotId": "550289db-89cb-465c-a9d8-a16dbf23cc45"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "00000000-0000-0000-0000-000000000000",
|
||||
"SourceSlotId": "ecc27b89-e89a-4c01-93ad-b4750d09f2f7",
|
||||
"TargetParentOrChildId": "4693a9d2-485e-4e3b-9f07-496181b4281f",
|
||||
"TargetSlotId": "70460191-7573-400f-ba88-11878ecc917c"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "ac87ddda-5e7f-4d85-a22a-3af5e274c154",
|
||||
"SourceSlotId": "5c54174b-c9e6-41de-b796-84ef4271dd20",
|
||||
"TargetParentOrChildId": "58230175-3f7a-4b01-b1b6-27193dc5a0e2",
|
||||
"TargetSlotId": "f36e4078-2608-4308-ab5f-077c05b1181a"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "387f494b-68de-40a3-9da4-9b4bed7caf91",
|
||||
"SourceSlotId": "5c54174b-c9e6-41de-b796-84ef4271dd20",
|
||||
"TargetParentOrChildId": "98c950e9-b0c4-4cee-be31-b9cd1ee60eed",
|
||||
"TargetSlotId": "f36e4078-2608-4308-ab5f-077c05b1181a"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "f7f79af2-50d8-4bbc-bb8f-0d08fec71b29",
|
||||
"SourceSlotId": "4e4ebbcf-6b12-4ce7-9bec-78cd9049e239",
|
||||
"TargetParentOrChildId": "ac87ddda-5e7f-4d85-a22a-3af5e274c154",
|
||||
"TargetSlotId": "550289db-89cb-465c-a9d8-a16dbf23cc45"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "febcd3dc-8adf-430b-a94e-eba1c010e1a8",
|
||||
"SourceSlotId": "e47bf25e-351a-44e6-84c6-ad3abc93531a",
|
||||
"TargetParentOrChildId": "cdf0eb8d-e5e0-4a5c-8efa-63f1942fa4d9",
|
||||
"TargetSlotId": "b5e72715-9339-484f-b197-5a28cd823798"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "1d04262b-da7f-49de-a0a3-7de7589d20af",
|
||||
"SourceSlotId": "5c54174b-c9e6-41de-b796-84ef4271dd20",
|
||||
"TargetParentOrChildId": "e5168e43-3129-4c1d-81c6-33ef4d80ea71",
|
||||
"TargetSlotId": "f36e4078-2608-4308-ab5f-077c05b1181a"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "11e62dfd-c9de-4714-9115-5fcdbf720331",
|
||||
"SourceSlotId": "e011dd8c-1b9c-458f-8960-e6c38e83ca74",
|
||||
"TargetParentOrChildId": "f7f79af2-50d8-4bbc-bb8f-0d08fec71b29",
|
||||
"TargetSlotId": "8a401e5d-295d-4403-a3af-1d6b91ce3dba"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "e5168e43-3129-4c1d-81c6-33ef4d80ea71",
|
||||
"SourceSlotId": "c63a1977-a594-490d-b5fb-de4d40bad016",
|
||||
"TargetParentOrChildId": "febcd3dc-8adf-430b-a94e-eba1c010e1a8",
|
||||
"TargetSlotId": "b5e72715-9339-484f-b197-5a28cd823798"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "98c950e9-b0c4-4cee-be31-b9cd1ee60eed",
|
||||
"SourceSlotId": "c63a1977-a594-490d-b5fb-de4d40bad016",
|
||||
"TargetParentOrChildId": "febcd3dc-8adf-430b-a94e-eba1c010e1a8",
|
||||
"TargetSlotId": "b5e72715-9339-484f-b197-5a28cd823798"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "58230175-3f7a-4b01-b1b6-27193dc5a0e2",
|
||||
"SourceSlotId": "c63a1977-a594-490d-b5fb-de4d40bad016",
|
||||
"TargetParentOrChildId": "febcd3dc-8adf-430b-a94e-eba1c010e1a8",
|
||||
"TargetSlotId": "b5e72715-9339-484f-b197-5a28cd823798"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "075612b1-8760-4858-ad6b-6c85a7716794"/*TimeToString*/,
|
||||
"Description": "Converts [Time] float output and similar to a string",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "ecc27b89-e89a-4c01-93ad-b4750d09f2f7"/*Input*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Description": "Input for [Time] operator"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [
|
||||
{
|
||||
"ChildId": "11e62dfd-c9de-4714-9115-5fcdbf720331"/*Multiply*/,
|
||||
"Position": {
|
||||
"X": 19.560425,
|
||||
"Y": 195.0003
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "1d04262b-da7f-49de-a0a3-7de7589d20af"/*Floor*/,
|
||||
"Position": {
|
||||
"X": 319.56042,
|
||||
"Y": 43.000122
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "1e1ae105-ea95-4b2c-9e7d-32fd934fab38"/*Modulo*/,
|
||||
"Position": {
|
||||
"X": 169.56042,
|
||||
"Y": 119.000305
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "387f494b-68de-40a3-9da4-9b4bed7caf91"/*Floor*/,
|
||||
"Position": {
|
||||
"X": 319.56042,
|
||||
"Y": 119.000305
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "4693a9d2-485e-4e3b-9f07-496181b4281f"/*Div*/,
|
||||
"Position": {
|
||||
"X": 169.56042,
|
||||
"Y": 43.000122
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "58230175-3f7a-4b01-b1b6-27193dc5a0e2"/*FloatToString*/,
|
||||
"Position": {
|
||||
"X": 469.56042,
|
||||
"Y": 195.0003
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "706dc843-9a95-4cf7-bb9a-ac1a8c1d4ce2"/*String*/,
|
||||
"Position": {
|
||||
"X": 458.7432,
|
||||
"Y": -97.51553
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "98c950e9-b0c4-4cee-be31-b9cd1ee60eed"/*FloatToString*/,
|
||||
"Position": {
|
||||
"X": 469.56042,
|
||||
"Y": 119.000305
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "ac87ddda-5e7f-4d85-a22a-3af5e274c154"/*Floor*/,
|
||||
"Position": {
|
||||
"X": 319.56042,
|
||||
"Y": 195.0003
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "cdf0eb8d-e5e0-4a5c-8efa-63f1942fa4d9"/*CombineStrings*/,
|
||||
"Position": {
|
||||
"X": 769.5604,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "e5168e43-3129-4c1d-81c6-33ef4d80ea71"/*FloatToString*/,
|
||||
"Position": {
|
||||
"X": 469.56042,
|
||||
"Y": 43.000122
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "e96babee-8ef9-411c-81f9-fdf3015b9289"/*_Time_old*/,
|
||||
"Position": {
|
||||
"X": -101.543846,
|
||||
"Y": 92.77409
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "f7f79af2-50d8-4bbc-bb8f-0d08fec71b29"/*Modulo*/,
|
||||
"Position": {
|
||||
"X": 169.56042,
|
||||
"Y": 195.0003
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "febcd3dc-8adf-430b-a94e-eba1c010e1a8"/*CombineStrings*/,
|
||||
"Position": {
|
||||
"X": 619.5604,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "d45912c1-1c26-4a80-bfff-57de6ae6ccdf"/*Result*/,
|
||||
"Position": {
|
||||
"X": 1069.5604,
|
||||
"Y": 97.50015
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
namespace Lib.@string.list;
|
||||
|
||||
[Guid("51943340-70b1-4bb5-8cb9-0e79d366a57b")]
|
||||
internal sealed class JoinStringList : Instance<JoinStringList>, IStatusProvider
|
||||
{
|
||||
[Output(Guid = "ef105688-3e28-47c3-8b8e-5fda3bde3090")]
|
||||
public readonly Slot<string> Result = new(); public JoinStringList()
|
||||
{
|
||||
Result.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var separatorValue = Separator.GetValue(context);
|
||||
if (separatorValue == null)
|
||||
{
|
||||
_lastErrorMessage = "Separator can't be null.";
|
||||
Result.Value = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
var separator = separatorValue.Replace("\\n", "\n");
|
||||
var input = Input.GetValue(context);
|
||||
if (input == null || input.Count == 0)
|
||||
{
|
||||
_lastErrorMessage = "Can't join empty string list.";
|
||||
Result.Value = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
_lastErrorMessage = null;
|
||||
Result.Value = string.Join(separator, input);
|
||||
}
|
||||
|
||||
[Input(Guid = "DB366216-B485-48BF-B267-56344B317CF7")]
|
||||
public readonly InputSlot<List<string>> Input = new ();
|
||||
|
||||
[Input(Guid = "89350e3c-2b83-4720-bfa1-d4adc6cc02fa")]
|
||||
public readonly InputSlot<string> Separator = new();
|
||||
|
||||
IStatusProvider.StatusLevel IStatusProvider.GetStatusLevel()
|
||||
=> string.IsNullOrEmpty(_lastErrorMessage) ? IStatusProvider.StatusLevel.Success : IStatusProvider.StatusLevel.Warning;
|
||||
|
||||
string IStatusProvider.GetStatusMessage() => _lastErrorMessage;
|
||||
|
||||
private string _lastErrorMessage;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "51943340-70b1-4bb5-8cb9-0e79d366a57b"/*JoinStringList*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "89350e3c-2b83-4720-bfa1-d4adc6cc02fa"/*Separator*/,
|
||||
"DefaultValue": "\\n"
|
||||
},
|
||||
{
|
||||
"Id": "db366216-b485-48bf-b267-56344b317cf7"/*Input*/,
|
||||
"DefaultValue": {
|
||||
"Values": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "51943340-70b1-4bb5-8cb9-0e79d366a57b"/*JoinStringList*/,
|
||||
"Description": "Joins the members of a string with a separator.",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "89350e3c-2b83-4720-bfa1-d4adc6cc02fa"/*Separator*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "db366216-b485-48bf-b267-56344b317cf7"/*Input*/,
|
||||
"Relevancy": "Required",
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "ef105688-3e28-47c3-8b8e-5fda3bde3090"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
namespace Lib.@string.list;
|
||||
|
||||
[Guid("56eda8f4-09fc-48a3-ab1d-fbff4f4b6438")]
|
||||
internal sealed class KeepStrings : Instance<KeepStrings>
|
||||
{
|
||||
[Output(Guid = "5e1b1aad-2fe2-49f3-9954-a35dc7b3ec25")]
|
||||
public readonly Slot<List<string>> Strings = new();
|
||||
|
||||
[Output(Guid = "9661F810-7B94-4187-A2F0-2B26950A2F2E")]
|
||||
public readonly Slot<List<float>> InsertTimes = new();
|
||||
|
||||
[Output(Guid = "30760da6-3ed4-41df-aa76-545bd203ea57")]
|
||||
public readonly Slot<int> Count = new();
|
||||
|
||||
public KeepStrings()
|
||||
{
|
||||
Strings.UpdateAction = Update;
|
||||
}
|
||||
|
||||
private bool _clear;
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var maxCount = MaxCount.GetValue(context).Clamp(0, 10000);
|
||||
var insertTriggered = InsertTrigger.GetValue(context);
|
||||
var index = Index.GetValue(context).Mod(maxCount);
|
||||
|
||||
if (MathUtils.WasTriggered(ClearTrigger.GetValue(context), ref _clear))
|
||||
{
|
||||
_strings.Clear();
|
||||
_insertTimes.Clear();
|
||||
ClearTrigger.SetTypedInputValue(false);
|
||||
}
|
||||
|
||||
var onlyOnChanges = OnlyOnChanges.GetValue(context);
|
||||
var newStr = NewString.GetValue(context);
|
||||
var hasStringChanged = newStr != _lastString;
|
||||
if (hasStringChanged)
|
||||
{
|
||||
_lastString = newStr;
|
||||
}
|
||||
|
||||
var insertMode = InsertMode.GetEnumValue<InsertModes>(context);
|
||||
|
||||
if (insertTriggered)
|
||||
{
|
||||
switch (insertMode)
|
||||
{
|
||||
case InsertModes.Append:
|
||||
if (hasStringChanged || !onlyOnChanges)
|
||||
{
|
||||
_strings.Add(newStr);
|
||||
_insertTimes.Add((float)context.LocalFxTime);
|
||||
|
||||
while (_strings.Count > maxCount && _strings.Count > 1)
|
||||
{
|
||||
_strings.RemoveAt(0);
|
||||
_insertTimes.RemoveAt(0);
|
||||
}
|
||||
|
||||
_index = _strings.Count - 1;
|
||||
}
|
||||
|
||||
break;
|
||||
case InsertModes.Insert:
|
||||
if (hasStringChanged || !onlyOnChanges)
|
||||
{
|
||||
_strings.Insert(0, newStr);
|
||||
_insertTimes.Insert(0, (float)context.LocalFxTime);
|
||||
|
||||
while (_strings.Count > maxCount && _strings.Count > 1)
|
||||
{
|
||||
_strings.RemoveAt(_strings.Count - 1);
|
||||
_insertTimes.RemoveAt(_insertTimes.Count - 1);
|
||||
}
|
||||
|
||||
_index = 0;
|
||||
}
|
||||
break;
|
||||
case InsertModes.Overwrite:
|
||||
if (hasStringChanged || !onlyOnChanges)
|
||||
{
|
||||
if (maxCount > 0)
|
||||
{
|
||||
if (_strings.Count == 0)
|
||||
{
|
||||
_strings.Add(newStr);
|
||||
_insertTimes.Add((float)context.LocalFxTime);
|
||||
}
|
||||
else if(_strings.Count < maxCount)
|
||||
{
|
||||
_strings.Add(newStr);
|
||||
_insertTimes.Add((float)context.LocalFxTime);
|
||||
_index = _strings.Count - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_index = (_index+1) % _strings.Count;
|
||||
_strings[_index] = newStr;
|
||||
_insertTimes[_index] = (float)context.LocalFxTime;
|
||||
}
|
||||
}
|
||||
|
||||
while (_strings.Count > maxCount && _strings.Count > 1)
|
||||
{
|
||||
_strings.RemoveAt(_strings.Count - 1);
|
||||
_insertTimes.RemoveAt(_insertTimes.Count - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case InsertModes.UseIndex:
|
||||
try
|
||||
{
|
||||
while (_strings.Count > maxCount && _strings.Count > 1)
|
||||
{
|
||||
_strings.RemoveAt(_strings.Count - 1);
|
||||
_insertTimes.RemoveAt(_insertTimes.Count - 1);
|
||||
}
|
||||
|
||||
if (hasStringChanged || !onlyOnChanges)
|
||||
{
|
||||
if (_strings.Count <= index)
|
||||
{
|
||||
_strings.Add(newStr);
|
||||
_insertTimes.Add((float)context.LocalFxTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
_strings[index] = newStr;
|
||||
_insertTimes[index]= (float)context.LocalFxTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Debug($"Error in KeepStrings: {index} {e.Message} {e.StackTrace}", this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Strings.Value = _strings;
|
||||
InsertTimes.Value = _insertTimes;
|
||||
Count.Value = _strings.Count;
|
||||
}
|
||||
|
||||
|
||||
private readonly List<string> _strings = new();
|
||||
private readonly List<float> _insertTimes = new();
|
||||
private int _index;
|
||||
|
||||
private string _lastString = string.Empty;
|
||||
|
||||
private enum InsertModes
|
||||
{
|
||||
Append,
|
||||
Insert,
|
||||
Overwrite,
|
||||
UseIndex,
|
||||
}
|
||||
|
||||
[Input(Guid = "26ADB8D2-14E7-4006-99ED-BCBBEDE8352A")]
|
||||
public readonly InputSlot<string> NewString = new();
|
||||
|
||||
[Input(Guid = "D045F941-7035-4A84-B0B0-2691477EF375")]
|
||||
public readonly InputSlot<bool> InsertTrigger = new();
|
||||
|
||||
[Input(Guid = "1B777F1E-E219-4B8F-B185-94466C280881")]
|
||||
public readonly InputSlot<int> MaxCount = new();
|
||||
|
||||
[Input(Guid = "2FF583B8-8B3E-4441-AA60-7365F4C54320")]
|
||||
public readonly InputSlot<bool> ClearTrigger = new();
|
||||
|
||||
[Input(Guid = "3A9E3E1C-E8C2-46C7-96AC-B7C317205ED4")]
|
||||
public readonly InputSlot<bool> OnlyOnChanges = new();
|
||||
|
||||
[Input(Guid = "694574A3-A3A9-4073-BEEC-A6A10ED64B81", MappedType = typeof(InsertModes))]
|
||||
public readonly InputSlot<int> InsertMode = new();
|
||||
|
||||
[Input(Guid = "ba5cd2ae-15df-4d67-8690-a5b0d1b81971")]
|
||||
public readonly InputSlot<int> Index = new(0);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "56eda8f4-09fc-48a3-ab1d-fbff4f4b6438"/*KeepStrings*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "1b777f1e-e219-4b8f-b185-94466c280881"/*MaxCount*/,
|
||||
"DefaultValue": 100
|
||||
},
|
||||
{
|
||||
"Id": "26adb8d2-14e7-4006-99ed-bcbbede8352a"/*NewString*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "2ff583b8-8b3e-4441-aa60-7365f4c54320"/*ClearTrigger*/,
|
||||
"DefaultValue": false
|
||||
},
|
||||
{
|
||||
"Id": "3a9e3e1c-e8c2-46c7-96ac-b7c317205ed4"/*OnlyOnChanges*/,
|
||||
"DefaultValue": true
|
||||
},
|
||||
{
|
||||
"Id": "694574a3-a3a9-4073-beec-a6a10ed64b81"/*InsertMode*/,
|
||||
"DefaultValue": 0
|
||||
},
|
||||
{
|
||||
"Id": "ba5cd2ae-15df-4d67-8690-a5b0d1b81971"/*Index*/,
|
||||
"DefaultValue": 0
|
||||
},
|
||||
{
|
||||
"Id": "d045f941-7035-4a84-b0b0-2691477ef375"/*InsertTrigger*/,
|
||||
"DefaultValue": true
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "56eda8f4-09fc-48a3-ab1d-fbff4f4b6438"/*KeepStrings*/,
|
||||
"Description": "Collects the input string to a list.",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "1b777f1e-e219-4b8f-b185-94466c280881"/*MaxCount*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 135.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "26adb8d2-14e7-4006-99ed-bcbbede8352a"/*NewString*/,
|
||||
"Relevancy": "Relevant",
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "2ff583b8-8b3e-4441-aa60-7365f4c54320"/*ClearTrigger*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "3a9e3e1c-e8c2-46c7-96ac-b7c317205ed4"/*OnlyOnChanges*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 45.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "694574a3-a3a9-4073-beec-a6a10ed64b81"/*InsertMode*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 90.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "ba5cd2ae-15df-4d67-8690-a5b0d1b81971"/*Index*/,
|
||||
"Relevancy": "Relevant",
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "d045f941-7035-4a84-b0b0-2691477ef375"/*InsertTrigger*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 90.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "5e1b1aad-2fe2-49f3-9954-a35dc7b3ec25"/*Strings*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"OutputId": "30760da6-3ed4-41df-aa76-545bd203ea57"/*Count*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"OutputId": "9661f810-7b94-4187-a2f0-2b26950a2f2e"/*InsertTimes*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 100.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
namespace Lib.@string.list;
|
||||
|
||||
[Guid("ef357e66-24e9-4f54-8d86-869db74602f4")]
|
||||
internal sealed class PickStringFromList : Instance<PickStringFromList>
|
||||
{
|
||||
[Output(Guid = "467bb46e-3391-48a7-b0eb-f7fd9d77b60f")]
|
||||
public readonly Slot<string> Selected = new();
|
||||
|
||||
[Output(Guid = "83009BD4-5257-44A2-8091-92B7D2FA5E35")]
|
||||
public readonly Slot<int> Count = new();
|
||||
|
||||
|
||||
public PickStringFromList()
|
||||
{
|
||||
Selected.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var list = Input.GetValue(context);
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
Selected.Value = string.Empty;
|
||||
Count.Value = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Count.Value = list.Count;
|
||||
|
||||
var index = Index.GetValue(context).Mod(list.Count);
|
||||
|
||||
Selected.Value = list[index];
|
||||
}
|
||||
|
||||
[Input(Guid = "8d5e77a6-1ec4-4979-ad26-f7862049bce1")]
|
||||
public readonly InputSlot<List<string>> Input = new(new List<string>(20));
|
||||
|
||||
[Input(Guid = "12ce5fe3-750f-47ed-9507-416cb327a615")]
|
||||
public readonly InputSlot<int> Index = new(0);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "ef357e66-24e9-4f54-8d86-869db74602f4"/*PickStringFromList*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "12ce5fe3-750f-47ed-9507-416cb327a615"/*Index*/,
|
||||
"DefaultValue": 0
|
||||
},
|
||||
{
|
||||
"Id": "8d5e77a6-1ec4-4979-ad26-f7862049bce1"/*Input*/,
|
||||
"DefaultValue": {
|
||||
"Values": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "ef357e66-24e9-4f54-8d86-869db74602f4"/*PickStringFromList*/,
|
||||
"Description": "Can switch between different strings if the 'Fragments' output of a [SplitString] operator is used as an input",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "12ce5fe3-750f-47ed-9507-416cb327a615"/*Index*/,
|
||||
"Relevancy": "Relevant",
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Description": "Index that controls which part of a string is used",
|
||||
"AddPadding": "True"
|
||||
},
|
||||
{
|
||||
"InputId": "8d5e77a6-1ec4-4979-ad26-f7862049bce1"/*Input*/,
|
||||
"Relevancy": "Required",
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Description": "Input for [SplitString]"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "467bb46e-3391-48a7-b0eb-f7fd9d77b60f"/*Selected*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"OutputId": "83009bd4-5257-44a2-8091-92b7d2fa5e35"/*Count*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
namespace Lib.@string.list;
|
||||
|
||||
[Guid("a0fcf7ed-1f14-4a8b-a57e-99e5b2407b1b")]
|
||||
internal sealed class SplitString : Instance<SplitString>
|
||||
{
|
||||
[Output(Guid = "52745502-3b69-4b2e-be47-d2660fe08e48")]
|
||||
public readonly Slot<List<string>> Fragments = new();
|
||||
|
||||
[Output(Guid = "6C78D167-F9F5-43A0-8CD6-8A8B0A34067E")]
|
||||
public readonly Slot<int> Count = new();
|
||||
|
||||
public SplitString()
|
||||
{
|
||||
Fragments.UpdateAction += Update;
|
||||
Count.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var split = Split.GetValue(context);
|
||||
var c = (split.Length == 0 || split == "\\n")
|
||||
? '\n'
|
||||
: split[0];
|
||||
|
||||
var str = String.GetValue(context);
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
Fragments.Value = _emptyList;
|
||||
return;
|
||||
}
|
||||
|
||||
Fragments.Value = str.Split(c).ToList();
|
||||
Count.Value = Fragments.Value.Count;
|
||||
|
||||
Fragments.DirtyFlag.Clear();
|
||||
Count.DirtyFlag.Clear();
|
||||
}
|
||||
|
||||
private readonly List<string> _emptyList = new();
|
||||
|
||||
[Input(Guid = "b1fd8b37-140e-487f-bfe2-bc426d8fe439")]
|
||||
public readonly InputSlot<string> String = new("Line\nLine");
|
||||
|
||||
[Input(Guid = "c54e4b16-b185-41f8-bc50-230b7624d093")]
|
||||
public readonly InputSlot<string> Split = new("\n");
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "a0fcf7ed-1f14-4a8b-a57e-99e5b2407b1b"/*SplitString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "b1fd8b37-140e-487f-bfe2-bc426d8fe439"/*String*/,
|
||||
"DefaultValue": "."
|
||||
},
|
||||
{
|
||||
"Id": "c54e4b16-b185-41f8-bc50-230b7624d093"/*Split*/,
|
||||
"DefaultValue": "\\n"
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "a0fcf7ed-1f14-4a8b-a57e-99e5b2407b1b"/*SplitString*/,
|
||||
"Description": "Splits a string by the provided separation character. Returns a List<string> that can be parsed with [PickFromStringList].",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "b1fd8b37-140e-487f-bfe2-bc426d8fe439"/*String*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Multiline"
|
||||
},
|
||||
{
|
||||
"InputId": "c54e4b16-b185-41f8-bc50-230b7624d093"/*Split*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "52745502-3b69-4b2e-be47-d2660fe08e48"/*Fragments*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"OutputId": "6c78d167-f9f5-43a0-8cd6-8a8b0a34067e"/*Count*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 100.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Lib.@string.list;
|
||||
|
||||
[Guid("4c496e8d-2a83-4493-a7a4-fdad29ef3f7d")]
|
||||
internal sealed class StringLength : Instance<StringLength>
|
||||
{
|
||||
[Output(Guid = "{C2FA7C57-6A0C-4D33-A70D-5130F3D52798}")]
|
||||
public readonly Slot<int> Length = new();
|
||||
|
||||
public StringLength()
|
||||
{
|
||||
Length.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
Length.Value = InputString.GetValue(context).Length;
|
||||
}
|
||||
|
||||
[Input(Guid = "{5794D63A-3EF7-42C5-B726-E814EA9093E3}")]
|
||||
public readonly InputSlot<string> InputString = new();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "4c496e8d-2a83-4493-a7a4-fdad29ef3f7d"/*StringLength*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "5794d63a-3ef7-42c5-b726-e814ea9093e3"/*InputString*/,
|
||||
"DefaultValue": "ten plus eleven is 21"
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "4c496e8d-2a83-4493-a7a4-fdad29ef3f7d"/*StringLength*/,
|
||||
"Description": "Counts the characters in a string and outputs the amount as a float",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "5794d63a-3ef7-42c5-b726-e814ea9093e3"/*InputString*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "c2fa7c57-6a0c-4d33-a70d-5130f3d52798"/*Length*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Lib.@string.list;
|
||||
|
||||
[Guid("04d557f8-3cc7-471f-8f2f-39090fec63bb")]
|
||||
internal sealed class ZipStringList : Instance<ZipStringList>
|
||||
{
|
||||
[Output(Guid = "0fc84451-81a3-4fb1-bacf-ea22a4a341c7")]
|
||||
public readonly Slot<List<string>> Output = new();
|
||||
|
||||
public ZipStringList()
|
||||
{
|
||||
Output.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var strOne = StringsOne.GetValue(context);
|
||||
var strTwo = StringsTwo.GetValue(context);
|
||||
if (strOne == null || strTwo == null)
|
||||
{
|
||||
Output.Value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
Output.Value = [.. strOne
|
||||
.Zip(strTwo, (a, b) => new[] {a, b})
|
||||
.SelectMany(t => t)];
|
||||
}
|
||||
|
||||
[Input(Guid = "be829559-ab5b-41ee-b104-dc5b0c1a1b2e")]
|
||||
public readonly InputSlot<List<string>> StringsOne = new();
|
||||
|
||||
[Input(Guid = "d69c10f6-6b3d-4624-a9c4-9ac4796290cf")]
|
||||
public readonly InputSlot<List<string>> StringsTwo = new();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "04d557f8-3cc7-471f-8f2f-39090fec63bb"/*ZipStringList*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "be829559-ab5b-41ee-b104-dc5b0c1a1b2e"/*StringsOne*/,
|
||||
"DefaultValue": {
|
||||
"Values": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"Id": "d69c10f6-6b3d-4624-a9c4-9ac4796290cf"/*StringsTwo*/,
|
||||
"DefaultValue": {
|
||||
"Values": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "04d557f8-3cc7-471f-8f2f-39090fec63bb"/*ZipStringList*/,
|
||||
"Description": "Zip two lists of strings, if the list sizes are differents, additional values of the longest are ignored",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "be829559-ab5b-41ee-b104-dc5b0c1a1b2e"/*StringsOne*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "d69c10f6-6b3d-4624-a9c4-9ac4796290cf"/*StringsTwo*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 75.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "0fc84451-81a3-4fb1-bacf-ea22a4a341c7"/*Output*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
namespace Lib.@string.logic;
|
||||
|
||||
[Guid("42c556fb-014b-4ac5-b390-f426ab415aa7")]
|
||||
internal sealed class FilePathParts : Instance<FilePathParts>, IStatusProvider
|
||||
{
|
||||
[Output(Guid = "A628FB9E-7647-4FEE-838D-F17395E15148")]
|
||||
public readonly Slot<string> Directory = new();
|
||||
|
||||
|
||||
[Output(Guid = "1242E534-DA34-4DA0-8C17-6CFA8FEF6E59")]
|
||||
public readonly Slot<string> FilenameWithoutExtension = new();
|
||||
|
||||
[Output(Guid = "1a9be39d-16ed-4f5f-916d-03b604101c7e")]
|
||||
public readonly Slot<string> Extension = new();
|
||||
|
||||
[Output(Guid = "DD5D3B87-D27D-405E-B8F4-524F3C18379C")]
|
||||
public readonly Slot<bool> FileExists = new();
|
||||
|
||||
|
||||
public FilePathParts()
|
||||
{
|
||||
FilenameWithoutExtension.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var path = FilePath.GetValue(context);
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
FileExists.Value = File.Exists(path);
|
||||
Directory.Value = Path.GetDirectoryName(path);
|
||||
Extension.Value = Path.GetExtension(path);
|
||||
FilenameWithoutExtension.Value = Path.GetFileNameWithoutExtension(path);
|
||||
_errorMessageForStatus = string.Empty;
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_errorMessageForStatus = "Failed to analyse filepath: " + e.Message;
|
||||
Log.Debug(_errorMessageForStatus, this);
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reset();
|
||||
_errorMessageForStatus = "Need path";
|
||||
//Log.Debug("Need path", this);
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
FileExists.Value = false;
|
||||
Directory.Value = null;
|
||||
FilenameWithoutExtension.Value = null;
|
||||
Extension.Value = null;
|
||||
}
|
||||
|
||||
public IStatusProvider.StatusLevel GetStatusLevel()
|
||||
{
|
||||
return string.IsNullOrEmpty(_errorMessageForStatus) ? IStatusProvider.StatusLevel.Success : IStatusProvider.StatusLevel.Error;
|
||||
}
|
||||
|
||||
public string GetStatusMessage()
|
||||
{
|
||||
return _errorMessageForStatus;
|
||||
}
|
||||
|
||||
private string _errorMessageForStatus;
|
||||
|
||||
[Input(Guid = "04d5f714-4e38-4a1e-b245-f6f0b582b35a")]
|
||||
public readonly InputSlot<string> FilePath = new();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "42c556fb-014b-4ac5-b390-f426ab415aa7"/*FilePathParts*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "04d5f714-4e38-4a1e-b245-f6f0b582b35a"/*FilePath*/,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "42c556fb-014b-4ac5-b390-f426ab415aa7"/*FilePathParts*/,
|
||||
"Description": "Extracts directory, filename and extension from a filepath and checks if filepath exists.",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "04d5f714-4e38-4a1e-b245-f6f0b582b35a"/*FilePath*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "1a9be39d-16ed-4f5f-916d-03b604101c7e"/*Extension*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"OutputId": "a628fb9e-7647-4fee-838d-f17395e15148"/*Directory*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 100.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"OutputId": "1242e534-da34-4da0-8c17-6cfa8fef6e59"/*FilenameWithoutExtension*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 200.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"OutputId": "dd5d3b87-d27d-405e-b8f4-524f3c18379c"/*FileExists*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 300.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace Lib.@string.logic;
|
||||
|
||||
[Guid("de9f1dfd-05ec-466f-9f5f-46e7e8da219a")]
|
||||
internal sealed class HasStringChanged : Instance<HasStringChanged>
|
||||
{
|
||||
[Output(Guid = "e89cfe71-4246-4580-a42c-01d1263cd1c9")]
|
||||
public readonly Slot<bool> HasChanged = new();
|
||||
|
||||
|
||||
public HasStringChanged()
|
||||
{
|
||||
HasChanged.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var newString = Value.GetValue(context);
|
||||
|
||||
var hasChanged = newString != _lastString;
|
||||
HasChanged.Value = hasChanged;
|
||||
_lastString = newString;
|
||||
|
||||
HasChanged.DirtyFlag.Trigger = hasChanged ? DirtyFlagTrigger.Animated : DirtyFlagTrigger.None;
|
||||
}
|
||||
|
||||
private string _lastString;
|
||||
|
||||
[Input(Guid = "303A7A17-5B3E-4D2E-A5BD-FDE775BE387A")]
|
||||
public readonly InputSlot<string> Value = new();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "de9f1dfd-05ec-466f-9f5f-46e7e8da219a"/*HasStringChanged*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "303a7a17-5b3e-4d2e-a5bd-fde775be387a"/*Value*/,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "de9f1dfd-05ec-466f-9f5f-46e7e8da219a"/*HasStringChanged*/,
|
||||
"Description": "Returns true if the connected string attribute has changed.",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "303a7a17-5b3e-4d2e-a5bd-fde775be387a"/*Value*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "e89cfe71-4246-4580-a42c-01d1263cd1c9"/*HasChanged*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
namespace Lib.@string.logic;
|
||||
|
||||
[Guid("a9784e5e-7696-49a0-bb77-2302587ede59")]
|
||||
internal sealed class PickString : Instance<PickString>
|
||||
{
|
||||
[Output(Guid = "74104EB6-DFC2-4AD2-9600-91C5A33855D4")]
|
||||
public readonly Slot<string> Selected = new();
|
||||
|
||||
public PickString()
|
||||
{
|
||||
Selected.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var connections = Input.GetCollectedTypedInputs();
|
||||
var index = Index.GetValue(context).Mod(connections.Count);
|
||||
|
||||
Input.DirtyFlag.Clear();
|
||||
if (connections.Count == 0)
|
||||
return;
|
||||
|
||||
Selected.Value = connections[index].GetValue(context);
|
||||
|
||||
// Clear dirty flag
|
||||
if (_isFirstUpdate)
|
||||
{
|
||||
foreach (var c in connections)
|
||||
{
|
||||
c.GetValue(context);
|
||||
}
|
||||
|
||||
_isFirstUpdate = false;
|
||||
}
|
||||
|
||||
Input.DirtyFlag.Clear();
|
||||
}
|
||||
|
||||
private bool _isFirstUpdate = true;
|
||||
|
||||
[Input(Guid = "202CE6D5-EE5A-41C7-BD04-4C1490F3EA9C")]
|
||||
public readonly MultiInputSlot<string> Input = new();
|
||||
|
||||
[Input(Guid = "20E76577-92EE-443D-9630-EBC41E38BB85")]
|
||||
public readonly InputSlot<int> Index = new(0);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "a9784e5e-7696-49a0-bb77-2302587ede59"/*PickString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "202ce6d5-ee5a-41c7-bd04-4c1490f3ea9c"/*Input*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "20e76577-92ee-443d-9630-ebc41e38bb85"/*Index*/,
|
||||
"DefaultValue": 0
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "a9784e5e-7696-49a0-bb77-2302587ede59"/*PickString*/,
|
||||
"Description": "Picks a string of multiple connected.",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "202ce6d5-ee5a-41c7-bd04-4c1490f3ea9c"/*Input*/,
|
||||
"Relevancy": "Required",
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "20e76577-92ee-443d-9630-ebc41e38bb85"/*Index*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 45.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "74104eb6-dfc2-4ad2-9600-91c5a33855d4"/*Selected*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Lib.@string.logic;
|
||||
|
||||
[Guid("7baaa83d-5c09-42a0-b7bc-35dbcfa5156d")]
|
||||
internal sealed class PickStringPart : Instance<PickStringPart>
|
||||
{
|
||||
[Output(Guid = "62368C06-7815-47BC-9B0D-3024A2907E01")]
|
||||
public readonly Slot<string> Fragments = new();
|
||||
|
||||
[Output(Guid = "88888C06-7815-47BC-9B0D-3024A2907E01")]
|
||||
public readonly Slot<int> TotalCount = new();
|
||||
|
||||
|
||||
public PickStringPart()
|
||||
{
|
||||
Fragments.UpdateAction += Update;
|
||||
TotalCount.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private enum EntityTypes
|
||||
{
|
||||
Characters = 0,
|
||||
Words,
|
||||
Lines,
|
||||
Sentences,
|
||||
}
|
||||
|
||||
private EntityTypes _splitInto;
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
if (InputText.DirtyFlag.IsDirty || SplitInto.DirtyFlag.IsDirty)
|
||||
{
|
||||
_splitInto = (EntityTypes)SplitInto.GetValue(context);
|
||||
var inputText = InputText.GetValue(context);
|
||||
|
||||
if (inputText == null)
|
||||
{
|
||||
Fragments.Value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(inputText))
|
||||
inputText = inputText.Replace("\\n", "\n");
|
||||
|
||||
switch (_splitInto)
|
||||
{
|
||||
case EntityTypes.Characters:
|
||||
_chunks = Regex.Split(inputText, string.Empty);
|
||||
//_chunks = inputText.ToCharArray();
|
||||
//_chunks = new Regex("(.)").Split(inputText);
|
||||
_delimiter = "";
|
||||
break;
|
||||
|
||||
case EntityTypes.Words:
|
||||
_chunks = new Regex("[\\s\\.\\;\\,()`:]+").Split(inputText);
|
||||
_delimiter = " ";
|
||||
break;
|
||||
|
||||
case EntityTypes.Lines:
|
||||
_chunks = new Regex("\\n+").Split(inputText);
|
||||
_delimiter = "\n";
|
||||
break;
|
||||
|
||||
case EntityTypes.Sentences:
|
||||
_chunks = new Regex("\\.[\\s\\.]*").Split(inputText);
|
||||
_delimiter = ". ";
|
||||
break;
|
||||
default:
|
||||
_chunks = new string[0];
|
||||
break;
|
||||
}
|
||||
|
||||
_numberOfChunks = _chunks.Length > 0 && string.IsNullOrEmpty(_chunks[_chunks.Length - 1])
|
||||
? _chunks.Length - 1
|
||||
: _chunks.Length;
|
||||
//_lastFragment = "";
|
||||
}
|
||||
|
||||
var fragmentStart = FragmentStart.GetValue(context);
|
||||
var fragmentCount = FragmentCount.GetValue(context);
|
||||
//if (_splitInto == EntityTypes.Characters)
|
||||
// fragmentCount *= 2;
|
||||
|
||||
Fragments.Value = GetFragment(fragmentStart, fragmentCount);
|
||||
TotalCount.Value = _chunks.Length;
|
||||
|
||||
Fragments.DirtyFlag.Clear();
|
||||
TotalCount.DirtyFlag.Clear();
|
||||
}
|
||||
|
||||
private string GetFragment(int startFragment, int fragmentCount)
|
||||
{
|
||||
if (fragmentCount <= 0 || _numberOfChunks == 0)
|
||||
return "";
|
||||
|
||||
var sb = new StringBuilder();
|
||||
for (var index = 0;
|
||||
index < fragmentCount;
|
||||
index++)
|
||||
{
|
||||
if(index > 0)
|
||||
sb.Append(_delimiter);
|
||||
|
||||
var moduloIndex = (startFragment + index) % _numberOfChunks;
|
||||
if (moduloIndex < 0)
|
||||
moduloIndex += _numberOfChunks;
|
||||
|
||||
//sb.Append(d);
|
||||
//sb.Append(_chunks[moduloIndex]);
|
||||
//d = _delimiter;
|
||||
|
||||
sb.Append(_chunks[moduloIndex]);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
private int _numberOfChunks;
|
||||
private string[] _chunks;
|
||||
private string _delimiter;
|
||||
|
||||
[Input(Guid = "05d7962b-a02e-4ab5-9927-865375348ccd")]
|
||||
public readonly InputSlot<string> InputText = new("Line\nLine");
|
||||
|
||||
[Input(Guid = "5D7184F6-CF46-4CB0-B29F-B3C52B34B634", MappedType = typeof(EntityTypes))]
|
||||
public readonly InputSlot<int> SplitInto = new();
|
||||
|
||||
|
||||
[Input(Guid = "9CB908AD-0800-4B88-B256-C6CC2B84AB6C")]
|
||||
public readonly InputSlot<int> FragmentStart = new();
|
||||
|
||||
[Input(Guid = "7520DB6D-7855-40E1-BB81-EAD290815435")]
|
||||
public readonly InputSlot<int> FragmentCount = new();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "7baaa83d-5c09-42a0-b7bc-35dbcfa5156d"/*PickStringPart*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "05d7962b-a02e-4ab5-9927-865375348ccd"/*InputText*/,
|
||||
"DefaultValue": "The sky above the port\nwas the colour of television,\ntuned to a dead channel"
|
||||
},
|
||||
{
|
||||
"Id": "5d7184f6-cf46-4cb0-b29f-b3c52b34b634"/*SplitInto*/,
|
||||
"DefaultValue": 2
|
||||
},
|
||||
{
|
||||
"Id": "7520db6d-7855-40e1-bb81-ead290815435"/*FragmentCount*/,
|
||||
"DefaultValue": 1
|
||||
},
|
||||
{
|
||||
"Id": "9cb908ad-0800-4b88-b256-c6cc2b84ab6c"/*FragmentStart*/,
|
||||
"DefaultValue": 0
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "7baaa83d-5c09-42a0-b7bc-35dbcfa5156d"/*PickStringPart*/,
|
||||
"Description": "Gets lines, words, or characters from the input string. Good for typewriter effects, etc.\n\nUseful combinations: [ReadFile] [RequestUrl] [GetAttributeFromJsonString]",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "05d7962b-a02e-4ab5-9927-865375348ccd"/*InputText*/,
|
||||
"Relevancy": "Relevant",
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
},
|
||||
"Usage": "Multiline"
|
||||
},
|
||||
{
|
||||
"InputId": "5d7184f6-cf46-4cb0-b29f-b3c52b34b634"/*SplitInto*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "7520db6d-7855-40e1-bb81-ead290815435"/*FragmentCount*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 135.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "9cb908ad-0800-4b88-b256-c6cc2b84ab6c"/*FragmentStart*/,
|
||||
"Relevancy": "Relevant",
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 90.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "62368c06-7815-47bc-9b0d-3024a2907e01"/*Fragments*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"OutputId": "88888c06-7815-47bc-9b0d-3024a2907e01"/*TotalCount*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 100.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Lib.@string.random;
|
||||
|
||||
[Guid("dd7fa7ee-266a-43c8-b29f-3357488b26be")]
|
||||
internal sealed class AnimRandomString : Instance<AnimRandomString>
|
||||
{
|
||||
[Output(Guid = "3a769380-1586-4d7f-a881-e509d5c14c1b")]
|
||||
public readonly Slot<string> Fragments = new();
|
||||
|
||||
[Input(Guid = "4e36b984-43ff-447b-8e1d-a099fefd4d74")]
|
||||
public readonly InputSlot<float> Rate = new();
|
||||
|
||||
[Input(Guid = "9b705b88-a644-498a-b831-5d0243e01c41", MappedType = typeof(MockStrings.Categories))]
|
||||
public readonly InputSlot<int> Category = new();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "dd7fa7ee-266a-43c8-b29f-3357488b26be"/*AnimRandomString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "4e36b984-43ff-447b-8e1d-a099fefd4d74"/*Rate*/,
|
||||
"DefaultValue": 1.0
|
||||
},
|
||||
{
|
||||
"Id": "9b705b88-a644-498a-b831-5d0243e01c41"/*Category*/,
|
||||
"DefaultValue": 0
|
||||
}
|
||||
],
|
||||
"Children": [
|
||||
{
|
||||
"Id": "3af5dc6c-89f4-44b0-8c89-13b006d318cb"/*MockStrings*/,
|
||||
"SymbolId": "3af25959-fd3f-4608-b521-5860d82554df",
|
||||
"InputValues": [],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "9a2ba5ae-1660-48d2-bc58-a9a97f575741"/*PickStringPart*/,
|
||||
"SymbolId": "7baaa83d-5c09-42a0-b7bc-35dbcfa5156d",
|
||||
"InputValues": [],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "d49a1aed-efe6-48b7-a6e7-8c2d3f4db751"/*FloatToInt*/,
|
||||
"SymbolId": "06b4728e-852c-491a-a89d-647f7e0b5415",
|
||||
"InputValues": [],
|
||||
"Outputs": []
|
||||
},
|
||||
{
|
||||
"Id": "fa40238c-0cd8-4ffc-b8ea-18d11fa12790"/*AnimValue*/,
|
||||
"SymbolId": "ea7b8491-2f8e-4add-b0b1-fd068ccfed0d",
|
||||
"InputValues": [
|
||||
{
|
||||
"Id": "4cf5d20b-7335-4584-b246-c260ac5cdf4f"/*Shape*/,
|
||||
"Type": "System.Int32",
|
||||
"Value": 12
|
||||
}
|
||||
],
|
||||
"Outputs": []
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"SourceParentOrChildId": "9a2ba5ae-1660-48d2-bc58-a9a97f575741",
|
||||
"SourceSlotId": "62368c06-7815-47bc-9b0d-3024a2907e01",
|
||||
"TargetParentOrChildId": "00000000-0000-0000-0000-000000000000",
|
||||
"TargetSlotId": "3a769380-1586-4d7f-a881-e509d5c14c1b"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "00000000-0000-0000-0000-000000000000",
|
||||
"SourceSlotId": "9b705b88-a644-498a-b831-5d0243e01c41",
|
||||
"TargetParentOrChildId": "3af5dc6c-89f4-44b0-8c89-13b006d318cb",
|
||||
"TargetSlotId": "054ade21-c08e-4633-9725-6168fd7806f9"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "3af5dc6c-89f4-44b0-8c89-13b006d318cb",
|
||||
"SourceSlotId": "461d8e3a-b4db-4a12-94c5-c791e347e51f",
|
||||
"TargetParentOrChildId": "9a2ba5ae-1660-48d2-bc58-a9a97f575741",
|
||||
"TargetSlotId": "05d7962b-a02e-4ab5-9927-865375348ccd"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "d49a1aed-efe6-48b7-a6e7-8c2d3f4db751",
|
||||
"SourceSlotId": "1eb7c5c4-0982-43f4-b14d-524571e3cdda",
|
||||
"TargetParentOrChildId": "9a2ba5ae-1660-48d2-bc58-a9a97f575741",
|
||||
"TargetSlotId": "9cb908ad-0800-4b88-b256-c6cc2b84ab6c"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "fa40238c-0cd8-4ffc-b8ea-18d11fa12790",
|
||||
"SourceSlotId": "ae4addf0-08cf-4b25-9515-4fef9359d183",
|
||||
"TargetParentOrChildId": "d49a1aed-efe6-48b7-a6e7-8c2d3f4db751",
|
||||
"TargetSlotId": "af866a6c-1ab0-43c0-9e8a-5d25c300e128"
|
||||
},
|
||||
{
|
||||
"SourceParentOrChildId": "00000000-0000-0000-0000-000000000000",
|
||||
"SourceSlotId": "4e36b984-43ff-447b-8e1d-a099fefd4d74",
|
||||
"TargetParentOrChildId": "fa40238c-0cd8-4ffc-b8ea-18d11fa12790",
|
||||
"TargetSlotId": "48005727-0158-4795-ad70-8410c27fd01d"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "dd7fa7ee-266a-43c8-b29f-3357488b26be"/*AnimRandomString*/,
|
||||
"Description": "Returns a random word per beat.",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "4e36b984-43ff-447b-8e1d-a099fefd4d74"/*Rate*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "9b705b88-a644-498a-b831-5d0243e01c41"/*Category*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 45.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [
|
||||
{
|
||||
"ChildId": "3af5dc6c-89f4-44b0-8c89-13b006d318cb"/*MockStrings*/,
|
||||
"Position": {
|
||||
"X": 150.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "9a2ba5ae-1660-48d2-bc58-a9a97f575741"/*PickStringPart*/,
|
||||
"Position": {
|
||||
"X": 300.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "d49a1aed-efe6-48b7-a6e7-8c2d3f4db751"/*FloatToInt*/,
|
||||
"Position": {
|
||||
"X": 150.0,
|
||||
"Y": 56.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"ChildId": "fa40238c-0cd8-4ffc-b8ea-18d11fa12790"/*AnimValue*/,
|
||||
"Position": {
|
||||
"X": 1.0560608,
|
||||
"Y": 214.44357
|
||||
}
|
||||
}
|
||||
],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "3a769380-1586-4d7f-a881-e509d5c14c1b"/*Fragments*/,
|
||||
"Position": {
|
||||
"X": 600.0,
|
||||
"Y": 21.5
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
namespace Lib.@string.random;
|
||||
|
||||
[Guid("7b21f10b-3548-4a23-95df-360addaeb03d")]
|
||||
internal sealed class BuildRandomString : Instance<BuildRandomString>
|
||||
{
|
||||
[Output(Guid = "ABA9EB42-5AF0-4165-A2BD-FDFCD4340484", DirtyFlagTrigger = DirtyFlagTrigger.Animated)]
|
||||
public readonly Slot<string> Result = new();
|
||||
|
||||
[Output(Guid = "8116d50e-0220-4bb7-b09d-881f722804cd")]
|
||||
public readonly Slot<StringBuilder> Builder = new();
|
||||
|
||||
public BuildRandomString()
|
||||
{
|
||||
Result.UpdateAction += Update;
|
||||
Builder.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private double _lastUpdateTime = 0;
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var maxLength = MaxLength.GetValue(context);
|
||||
var stringBuilder = OverrideBuilder.GetValue(context);
|
||||
|
||||
if (Result.Value != null && Math.Abs(context.LocalFxTime - _lastUpdateTime) < 0.001)
|
||||
return;
|
||||
|
||||
_lastUpdateTime = context.LocalFxTime;
|
||||
var scrambleSeed = ScrambleSeed.GetValue(context);
|
||||
//var lastIndex = _index;
|
||||
|
||||
if (maxLength <= 0)
|
||||
{
|
||||
Result.Value= String.Empty;
|
||||
Result.Value= string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!OverrideBuilder.HasInputConnections || stringBuilder == null)
|
||||
{
|
||||
stringBuilder = _fallbackBuffer;
|
||||
}
|
||||
|
||||
if (Clear.GetValue(context))
|
||||
{
|
||||
stringBuilder.Clear();
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
//var mode = (Modes)WriteMode.GetValue(context);
|
||||
|
||||
try
|
||||
{
|
||||
var scrambleRatio = ScrambleRatio.GetValue(context);
|
||||
|
||||
var scrambleEnabled = Scramble.GetValue(context);
|
||||
if (scrambleRatio > 0 && scrambleEnabled)
|
||||
{
|
||||
for (int index = 0; index < stringBuilder.Length; index++)
|
||||
{
|
||||
var hash = (float)((double)MathUtils.XxHash((uint)index + (uint)scrambleSeed * 123127) / uint.MaxValue);
|
||||
if (hash < scrambleRatio)
|
||||
{
|
||||
var scrambleChunkEnd = index + hash * stringBuilder.Length + 1;
|
||||
while (index < stringBuilder.Length && index < scrambleChunkEnd)
|
||||
{
|
||||
var c = stringBuilder[index];
|
||||
if (c != '\n')
|
||||
{
|
||||
if (c == 32)
|
||||
c = (char)90;
|
||||
|
||||
c= (char)(c-1);
|
||||
stringBuilder[index] = c;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Insert.GetValue(context))
|
||||
{
|
||||
if (JumpToRandomPos.GetValue(context))
|
||||
_index = (int)_random.NextLong(0, stringBuilder.Length);
|
||||
|
||||
var separator = Separator.GetValue(context); ;
|
||||
if (!string.IsNullOrEmpty(separator))
|
||||
separator = separator.Replace("\\n", "\n");
|
||||
|
||||
var str = InsertString.GetValue(context);
|
||||
var insertString = str + separator;
|
||||
var insertLength = insertString.Length;
|
||||
var currentLength = stringBuilder.Length;
|
||||
var lineWrap = (WrapLinesModes)WrapLines.GetValue(context);
|
||||
var mode = (Modes)WriteMode.GetValue(context);
|
||||
|
||||
if (_index > maxLength)
|
||||
_index = 0;
|
||||
|
||||
var pos = _index;
|
||||
if (pos + insertLength > maxLength)
|
||||
{
|
||||
insertLength = maxLength - pos;
|
||||
}
|
||||
|
||||
if (mode != Modes.Insert && pos < currentLength - insertLength)
|
||||
{
|
||||
stringBuilder.Remove(pos, insertLength);
|
||||
}
|
||||
|
||||
if (pos > currentLength)
|
||||
{
|
||||
stringBuilder.Append(new string(' ', pos - currentLength));
|
||||
}
|
||||
|
||||
stringBuilder.Insert(pos, insertString);
|
||||
|
||||
InsertLineWraps(lineWrap, stringBuilder, pos, insertLength, WrapLineColumn.GetValue(context).Clamp(1,1000));
|
||||
|
||||
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case Modes.Insert:
|
||||
{
|
||||
_index += insertLength;
|
||||
_index %= maxLength;
|
||||
break;
|
||||
}
|
||||
case Modes.Overwrite:
|
||||
{
|
||||
_index += insertLength;
|
||||
_index %= maxLength;
|
||||
break;
|
||||
}
|
||||
case Modes.OverwriteAtFixedOffset:
|
||||
_index += OverwriteOffset.GetValue(context);
|
||||
if (_index > maxLength)
|
||||
{
|
||||
_index = _index % maxLength;
|
||||
}
|
||||
else if (_index < 0)
|
||||
{
|
||||
_index += maxLength - insertLength;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
|
||||
//InsertLineWraps(lineWrap, stringBuilder);
|
||||
|
||||
if (stringBuilder.Length > maxLength)
|
||||
stringBuilder.Length = maxLength;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warning($"Failed to manipulate string at index {_index} " + e.Message);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Builder.Value = stringBuilder;
|
||||
Result.Value = stringBuilder.ToString();
|
||||
}
|
||||
|
||||
private void InsertLineWraps(WrapLinesModes lineWrap, StringBuilder stringBuilder, int insertPos, int insertLength, int wrapColumn)
|
||||
{
|
||||
if (lineWrap == WrapLinesModes.WrapAtCharacters)
|
||||
{
|
||||
var lookBackIndex = insertPos;
|
||||
while (lookBackIndex > 0 && stringBuilder[lookBackIndex] != '\n')
|
||||
{
|
||||
lookBackIndex--;
|
||||
}
|
||||
|
||||
var lineLength = insertPos - lookBackIndex + insertLength;
|
||||
if (lineLength > wrapColumn && insertPos > 0 && insertPos < stringBuilder.Length)
|
||||
{
|
||||
stringBuilder[insertPos - 1] = '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
var lookForwardIndex = insertPos;
|
||||
while (lookForwardIndex < stringBuilder.Length && stringBuilder[lookForwardIndex] != '\n')
|
||||
{
|
||||
lookForwardIndex++;
|
||||
}
|
||||
|
||||
if (lookForwardIndex - lookBackIndex > wrapColumn)
|
||||
{
|
||||
stringBuilder[insertPos + insertLength - 1] = '\n';
|
||||
}
|
||||
}
|
||||
else if (lineWrap == WrapLinesModes.WrapAtWords)
|
||||
{
|
||||
int pos = 0;
|
||||
int currentLineLength = 0;
|
||||
int lastValidBreakPos = -1;
|
||||
while (pos < stringBuilder.Length)
|
||||
{
|
||||
var c = stringBuilder[pos];
|
||||
if (c == '\n')
|
||||
{
|
||||
currentLineLength = 0;
|
||||
lastValidBreakPos = -1;
|
||||
}
|
||||
|
||||
else if (c == ' ' || c == '.' || c == ',' || c == '/')
|
||||
{
|
||||
lastValidBreakPos = pos;
|
||||
currentLineLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentLineLength++;
|
||||
}
|
||||
|
||||
if (currentLineLength > wrapColumn && lastValidBreakPos != -1)
|
||||
{
|
||||
stringBuilder[lastValidBreakPos] = '\n';
|
||||
pos = lastValidBreakPos;
|
||||
lastValidBreakPos = -1;
|
||||
currentLineLength = 0;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else if (lineWrap == WrapLinesModes.WrapToFillBlock)
|
||||
{
|
||||
int pos = 0;
|
||||
int currentLineLength = 0;
|
||||
int lastValidBreakPos = -1;
|
||||
|
||||
while (pos < stringBuilder.Length)
|
||||
{
|
||||
var c = stringBuilder[pos];
|
||||
if (c == '\n')
|
||||
{
|
||||
stringBuilder[pos] = ' ';
|
||||
//currentLineLength = 0;
|
||||
lastValidBreakPos = pos;
|
||||
currentLineLength++;
|
||||
}
|
||||
|
||||
else if (c == ' ' || c == '.' || c == ',' || c == '/')
|
||||
{
|
||||
lastValidBreakPos = pos;
|
||||
currentLineLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentLineLength++;
|
||||
}
|
||||
|
||||
if (currentLineLength > wrapColumn && lastValidBreakPos != -1)
|
||||
{
|
||||
stringBuilder[lastValidBreakPos] = '\n';
|
||||
pos = lastValidBreakPos;
|
||||
lastValidBreakPos = -1;
|
||||
currentLineLength = 0;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else if (lineWrap == WrapLinesModes.SolidBlock)
|
||||
{
|
||||
int pos = 0;
|
||||
int currentLineLength = 0;
|
||||
while (pos < stringBuilder.Length)
|
||||
{
|
||||
var c = stringBuilder[pos];
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
stringBuilder.Remove(pos, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
currentLineLength++;
|
||||
pos++;
|
||||
|
||||
if (currentLineLength == wrapColumn)
|
||||
{
|
||||
stringBuilder.Insert(pos, '\n');
|
||||
pos++;
|
||||
currentLineLength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum Modes
|
||||
{
|
||||
Insert,
|
||||
Overwrite,
|
||||
OverwriteAtFixedOffset,
|
||||
}
|
||||
|
||||
private enum WrapLinesModes
|
||||
{
|
||||
DontWrap,
|
||||
WrapAtWords,
|
||||
WrapAtCharacters,
|
||||
WrapToFillBlock,
|
||||
SolidBlock,
|
||||
}
|
||||
|
||||
private StringBuilder _fallbackBuffer = new();
|
||||
|
||||
private int _index = 0;
|
||||
private Random _random = new();
|
||||
|
||||
[Input(Guid = "CE436E27-05A5-431D-9AA2-920DBFF639A7", MappedType = typeof(Modes))]
|
||||
public readonly InputSlot<int> WriteMode = new();
|
||||
|
||||
[Input(Guid = "77A5604A-034A-4352-BD46-BE3CB57F90B7")]
|
||||
public readonly InputSlot<bool> Clear = new();
|
||||
|
||||
[Input(Guid = "095202BF-118F-4C4C-802E-7916BC290A60")]
|
||||
public readonly InputSlot<bool> Insert = new();
|
||||
|
||||
|
||||
|
||||
[Input(Guid = "F977FAAF-1840-4A75-9BC5-43176F2E88E9")]
|
||||
public readonly InputSlot<bool> JumpToRandomPos = new();
|
||||
|
||||
|
||||
|
||||
[Input(Guid = "960179BD-286F-4629-BBCB-CD31AA9C9AE2")]
|
||||
public readonly InputSlot<string> InsertString = new();
|
||||
|
||||
[Input(Guid = "8EEE8067-1A4E-4372-93D0-2DBC368AA45A")]
|
||||
public readonly InputSlot<string> Separator = new();
|
||||
|
||||
[Input(Guid = "1559C0E9-BA56-447F-8241-03D8D59AC205")]
|
||||
public readonly InputSlot<int> OverwriteOffset = new();
|
||||
|
||||
[Input(Guid = "38CE7F47-C117-47A2-AEEA-609716C60555")]
|
||||
public readonly InputSlot<int> MaxLength = new();
|
||||
|
||||
[Input(Guid = "875CBFA9-FFA8-4204-810C-C04F5F421441", MappedType = typeof(WrapLinesModes))]
|
||||
public readonly InputSlot<int> WrapLines = new();
|
||||
|
||||
[Input(Guid = "BD941C4B-18A8-4687-85A8-3FE53B4F6213")]
|
||||
public readonly InputSlot<int> WrapLineColumn = new();
|
||||
|
||||
[Input(Guid = "7DABD7C8-5C2B-4BE2-B1B6-BF8B8FCBFD8D")]
|
||||
public readonly InputSlot<float> ScrambleRatio = new();
|
||||
|
||||
[Input(Guid = "9253B148-325B-427A-819E-1AE1B1019ADE")]
|
||||
public readonly InputSlot<bool> Scramble = new();
|
||||
|
||||
[Input(Guid = "3EA4F12E-7184-45BC-A523-EF6A2E1C5C3D")]
|
||||
public readonly InputSlot<int> ScrambleSeed = new();
|
||||
|
||||
|
||||
[Input(Guid = "CCFAC8A9-0954-4869-A47C-B66C714F6545")]
|
||||
public readonly InputSlot<StringBuilder> OverrideBuilder = new();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "7b21f10b-3548-4a23-95df-360addaeb03d"/*BuildRandomString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "095202bf-118f-4c4c-802e-7916bc290a60"/*Insert*/,
|
||||
"DefaultValue": true
|
||||
},
|
||||
{
|
||||
"Id": "1559c0e9-ba56-447f-8241-03d8d59ac205"/*OverwriteOffset*/,
|
||||
"DefaultValue": 10
|
||||
},
|
||||
{
|
||||
"Id": "38ce7f47-c117-47a2-aeea-609716c60555"/*MaxLength*/,
|
||||
"DefaultValue": 1000
|
||||
},
|
||||
{
|
||||
"Id": "3ea4f12e-7184-45bc-a523-ef6a2e1c5c3d"/*ScrambleSeed*/,
|
||||
"DefaultValue": 0
|
||||
},
|
||||
{
|
||||
"Id": "77a5604a-034a-4352-bd46-be3cb57f90b7"/*Clear*/,
|
||||
"DefaultValue": false
|
||||
},
|
||||
{
|
||||
"Id": "7dabd7c8-5c2b-4be2-b1b6-bf8b8fcbfd8d"/*ScrambleRatio*/,
|
||||
"DefaultValue": 0.0
|
||||
},
|
||||
{
|
||||
"Id": "875cbfa9-ffa8-4204-810c-c04f5f421441"/*WrapLines*/,
|
||||
"DefaultValue": 1
|
||||
},
|
||||
{
|
||||
"Id": "8eee8067-1a4e-4372-93d0-2dbc368aa45a"/*Separator*/,
|
||||
"DefaultValue": " "
|
||||
},
|
||||
{
|
||||
"Id": "9253b148-325b-427a-819e-1ae1b1019ade"/*Scramble*/,
|
||||
"DefaultValue": false
|
||||
},
|
||||
{
|
||||
"Id": "960179bd-286f-4629-bbcb-cd31aa9c9ae2"/*InsertString*/,
|
||||
"DefaultValue": "Tooll likes Cats."
|
||||
},
|
||||
{
|
||||
"Id": "bd941c4b-18a8-4687-85a8-3fe53b4f6213"/*WrapLineColumn*/,
|
||||
"DefaultValue": 60
|
||||
},
|
||||
{
|
||||
"Id": "ccfac8a9-0954-4869-a47c-b66c714f6545"/*OverrideBuilder*/,
|
||||
"DefaultValue": null
|
||||
},
|
||||
{
|
||||
"Id": "ce436e27-05a5-431d-9aa2-920dbff639a7"/*WriteMode*/,
|
||||
"DefaultValue": 0
|
||||
},
|
||||
{
|
||||
"Id": "f977faaf-1840-4a75-9bc5-43176f2e88e9"/*JumpToRandomPos*/,
|
||||
"DefaultValue": false
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "7b21f10b-3548-4a23-95df-360addaeb03d"/*BuildRandomString*/,
|
||||
"Description": "Produces a wide selection of text writer effects that \ncan be linked to AudioReactions. Interesting setups are\n\n[MockStrings]->[GetStringPart]->[ScrambleString]",
|
||||
"SymbolTags": "72",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "095202bf-118f-4c4c-802e-7916bc290a60"/*Insert*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 135.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "1559c0e9-ba56-447f-8241-03d8d59ac205"/*OverwriteOffset*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 270.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "38ce7f47-c117-47a2-aeea-609716c60555"/*MaxLength*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 90.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "3ea4f12e-7184-45bc-a523-ef6a2e1c5c3d"/*ScrambleSeed*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 225.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "77a5604a-034a-4352-bd46-be3cb57f90b7"/*Clear*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 405.0
|
||||
},
|
||||
"AddPadding": "True"
|
||||
},
|
||||
{
|
||||
"InputId": "7dabd7c8-5c2b-4be2-b1b6-bf8b8fcbfd8d"/*ScrambleRatio*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 135.0
|
||||
},
|
||||
"AddPadding": "True"
|
||||
},
|
||||
{
|
||||
"InputId": "875cbfa9-ffa8-4204-810c-c04f5f421441"/*WrapLines*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 360.0
|
||||
},
|
||||
"AddPadding": "True"
|
||||
},
|
||||
{
|
||||
"InputId": "8eee8067-1a4e-4372-93d0-2dbc368aa45a"/*Separator*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 180.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "9253b148-325b-427a-819e-1ae1b1019ade"/*Scramble*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 180.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "960179bd-286f-4629-bbcb-cd31aa9c9ae2"/*InsertString*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 180.0
|
||||
},
|
||||
"GroupTitle": "Settings",
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "bd941c4b-18a8-4687-85a8-3fe53b4f6213"/*WrapLineColumn*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 45.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "ccfac8a9-0954-4869-a47c-b66c714f6545"/*OverrideBuilder*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 90.0
|
||||
},
|
||||
"AddPadding": "True"
|
||||
},
|
||||
{
|
||||
"InputId": "ce436e27-05a5-431d-9aa2-920dbff639a7"/*WriteMode*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "f977faaf-1840-4a75-9bc5-43176f2e88e9"/*JumpToRandomPos*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 315.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "8116d50e-0220-4bb7-b09d-881f722804cd"/*Builder*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"OutputId": "aba9eb42-5af0-4165-a2bd-fdfcd4340484"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "3af25959-fd3f-4608-b521-5860d82554df"/*MockStrings*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "054ade21-c08e-4633-9725-6168fd7806f9"/*Category*/,
|
||||
"DefaultValue": 0
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "3af25959-fd3f-4608-b521-5860d82554df"/*MockStrings*/,
|
||||
"Description": "A small selection of strings of different categories.",
|
||||
"SymbolTags": "8",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "054ade21-c08e-4633-9725-6168fd7806f9"/*Category*/,
|
||||
"Position": {
|
||||
"X": -200.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "461d8e3a-b4db-4a12-94c5-c791e347e51f"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
namespace Lib.@string.search;
|
||||
|
||||
[Guid("fc0a5e68-9915-4323-b2a4-2491fa5d59a9")]
|
||||
internal sealed class IndexOf : Instance<IndexOf>
|
||||
{
|
||||
[Input(Guid = "841784c4-0ca7-41cd-8d79-bbe4989e0842")]
|
||||
public readonly InputSlot<string> OriginalString = new();
|
||||
|
||||
[Input(Guid = "81a7aa30-eab9-4637-bb11-7c0940460afb")]
|
||||
public readonly InputSlot<string> SearchPattern = new();
|
||||
|
||||
public IndexOf()
|
||||
{
|
||||
Index.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
string searchPattern = SearchPattern.GetValue(context);
|
||||
string originalString = OriginalString.GetValue(context);
|
||||
if (string.IsNullOrEmpty(searchPattern) || string.IsNullOrEmpty(originalString))
|
||||
{
|
||||
Index.Value = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Index.Value = originalString.IndexOf(searchPattern);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Log.Error($"'{originalString}' or '{searchPattern}' is incorrect", this);
|
||||
}
|
||||
}
|
||||
|
||||
[Output(Guid = "4bb4bb23-4c3f-4d7d-9dab-c37ac63dd1c9")]
|
||||
public readonly Slot<int> Index = new Slot<int>();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "fc0a5e68-9915-4323-b2a4-2491fa5d59a9"/*IndexOf*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "81a7aa30-eab9-4637-bb11-7c0940460afb"/*SearchPattern*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "841784c4-0ca7-41cd-8d79-bbe4989e0842"/*OriginalString*/,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "fc0a5e68-9915-4323-b2a4-2491fa5d59a9"/*IndexOf*/,
|
||||
"Description": "Searches the original string for a search pattern and outputs the position at which the pattern was found",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "81a7aa30-eab9-4637-bb11-7c0940460afb"/*SearchPattern*/,
|
||||
"Position": {
|
||||
"X": -91.13745,
|
||||
"Y": 99.28253
|
||||
},
|
||||
"Description": "Letters, numbers, or combinations to be searched for in the original string",
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "841784c4-0ca7-41cd-8d79-bbe4989e0842"/*OriginalString*/,
|
||||
"Position": {
|
||||
"X": -91.13745,
|
||||
"Y": 54.28253
|
||||
},
|
||||
"Description": "String to be analyzed",
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "4bb4bb23-4c3f-4d7d-9dab-c37ac63dd1c9"/*Index*/,
|
||||
"Position": {
|
||||
"X": 103.37944,
|
||||
"Y": 54.011322
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Lib.@string.search;
|
||||
|
||||
[Guid("b7910fc6-c3b2-4daf-93cd-010dcfe22a57")]
|
||||
internal sealed class SearchAndReplace : Instance<SearchAndReplace>
|
||||
{
|
||||
[Output(Guid = "15672e8f-c483-432e-8ced-f2bd18c1be67")]
|
||||
public readonly Slot<string> Result = new();
|
||||
|
||||
public SearchAndReplace()
|
||||
{
|
||||
Result.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var useRegex = UseRegex.GetValue(context);
|
||||
var content = OriginalString.GetValue(context);
|
||||
var replacement = Replace.GetValue(context)?.Replace("\\n","\n");
|
||||
var pattern = SearchPattern.GetValue(context);
|
||||
if (string.IsNullOrEmpty(content)
|
||||
|| string.IsNullOrEmpty(replacement)
|
||||
|| string.IsNullOrEmpty(pattern))
|
||||
{
|
||||
Result.Value = content?? string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
if (useRegex)
|
||||
{
|
||||
try
|
||||
{
|
||||
Result.Value= Regex.Replace(content, pattern, replacement, RegexOptions.Multiline| RegexOptions.Singleline);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Log.Error($"'{pattern}' is an incorrect search pattern", this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Result.Value = content.Replace(pattern, replacement, StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
|
||||
[Input(Guid = "3ca66cbd-a16a-479c-b858-84732e5023ad")]
|
||||
public readonly InputSlot<string> OriginalString = new();
|
||||
|
||||
[Input(Guid = "4FE3F641-1C36-4970-BE71-DAFB5632FB53")]
|
||||
public readonly InputSlot<string> SearchPattern = new();
|
||||
|
||||
[Input(Guid = "DE8297AE-C7D8-414A-8825-D0FF9C2E3D78")]
|
||||
public readonly InputSlot<string> Replace = new();
|
||||
|
||||
[Input(Guid = "3C65F1D1-D535-4ED8-885D-78A3D1BF26BC")]
|
||||
public readonly InputSlot<bool> UseRegex = new();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "b7910fc6-c3b2-4daf-93cd-010dcfe22a57"/*SearchAndReplace*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "3c65f1d1-d535-4ed8-885d-78a3d1bf26bc"/*UseRegex*/,
|
||||
"DefaultValue": false
|
||||
},
|
||||
{
|
||||
"Id": "3ca66cbd-a16a-479c-b858-84732e5023ad"/*OriginalString*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "4fe3f641-1c36-4970-be71-dafb5632fb53"/*SearchPattern*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "de8297ae-c7d8-414a-8825-d0ff9c2e3d78"/*Replace*/,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "b7910fc6-c3b2-4daf-93cd-010dcfe22a57"/*SearchAndReplace*/,
|
||||
"Description": "Looks for characters or strings within another string and returns a new string with the matches replaced.",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "3c65f1d1-d535-4ed8-885d-78a3d1bf26bc"/*UseRegex*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 210.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "3ca66cbd-a16a-479c-b858-84732e5023ad"/*OriginalString*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Description": "Defines the string whose content is searched",
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "4fe3f641-1c36-4970-be71-dafb5632fb53"/*SearchPattern*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 90.0
|
||||
},
|
||||
"Description": "Defines the string pattern that will be searched for and replaced",
|
||||
"AddPadding": "True",
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "de8297ae-c7d8-414a-8825-d0ff9c2e3d78"/*Replace*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 135.0
|
||||
},
|
||||
"Description": "Defines the string that will be used to replace what is defined as the search pattern",
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "15672e8f-c483-432e-8ced-f2bd18c1be67"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
namespace Lib.@string.search;
|
||||
|
||||
[Guid("045e834a-f0ee-432b-8e14-19cadc497577")]
|
||||
internal sealed class SubString : Instance<SubString>
|
||||
{
|
||||
[Output(Guid = "fba93f4a-aecc-4bcb-9d5a-85b13e362b85")]
|
||||
public readonly Slot<string> Result = new();
|
||||
|
||||
public SubString()
|
||||
{
|
||||
Result.UpdateAction = Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var str = InputText.GetValue(context);
|
||||
var start = Start.GetValue(context);
|
||||
var length = Length.GetValue(context);
|
||||
|
||||
var clampStart = start.Clamp(0, str.Length);
|
||||
var clampedLength = length.Clamp(0, str.Length - clampStart);
|
||||
|
||||
if (string.IsNullOrEmpty(str) || clampedLength == 0 || clampStart >= str.Length)
|
||||
{
|
||||
Result.Value = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
// Return full string
|
||||
if(start == 0 && length >= str.Length)
|
||||
{
|
||||
Result.Value = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Result.Value = str.Substring(clampStart, clampedLength);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warning("Failed to get substring: " + e.Message, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Input(Guid = "e7f79746-ff87-478e-9755-a8c7b1c34354")]
|
||||
public readonly InputSlot<string> InputText = new();
|
||||
|
||||
[Input(Guid = "8BED669E-1141-433F-A8A5-ECBDE812462B")]
|
||||
public readonly InputSlot<int> Start = new ();
|
||||
|
||||
[Input(Guid = "1910639E-5A41-4258-9D63-962DDA5EA299")]
|
||||
public readonly InputSlot<int> Length = new ();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "045e834a-f0ee-432b-8e14-19cadc497577"/*SubString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "1910639e-5a41-4258-9d63-962dda5ea299"/*Length*/,
|
||||
"DefaultValue": 10000
|
||||
},
|
||||
{
|
||||
"Id": "8bed669e-1141-433f-a8a5-ecbde812462b"/*Start*/,
|
||||
"DefaultValue": 0
|
||||
},
|
||||
{
|
||||
"Id": "e7f79746-ff87-478e-9755-a8c7b1c34354"/*InputText*/,
|
||||
"DefaultValue": ""
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "045e834a-f0ee-432b-8e14-19cadc497577"/*SubString*/,
|
||||
"Description": "Returns a substring of the connect string. \nThis can be useful for trimming a string to a maximum length.",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "1910639e-5a41-4258-9d63-962dda5ea299"/*Length*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 180.0
|
||||
},
|
||||
"Min": 0,
|
||||
"Max": 100000,
|
||||
"ClampMin": true,
|
||||
"ClampMax": true
|
||||
},
|
||||
{
|
||||
"InputId": "8bed669e-1141-433f-a8a5-ecbde812462b"/*Start*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 135.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "e7f79746-ff87-478e-9755-a8c7b1c34354"/*InputText*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "fba93f4a-aecc-4bcb-9d5a-85b13e362b85"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
namespace Lib.@string.transform;
|
||||
|
||||
[Guid("acdd78b1-4e66-4fd0-a36b-5318670fefd4")]
|
||||
internal sealed class ChangeCase : Instance<ChangeCase>
|
||||
{
|
||||
[Output(Guid = "ecf66a1e-45e5-4e0c-ac9e-a784a9339153")]
|
||||
public readonly Slot<string> Result = new();
|
||||
|
||||
public ChangeCase()
|
||||
{
|
||||
Result.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var str = InputText.GetValue(context);
|
||||
var mode = Mode.GetEnumValue<Modes>(context);
|
||||
switch (mode)
|
||||
{
|
||||
case Modes.ToUpperCase:
|
||||
Result.Value = str?.ToUpperInvariant();
|
||||
break;
|
||||
case Modes.ToLowerCase:
|
||||
Result.Value = str?.ToLowerInvariant();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[Input(Guid = "041C98B6-4450-46D7-9DAE-C9030C88B9E6")]
|
||||
public readonly InputSlot<string> InputText = new();
|
||||
|
||||
[Input(Guid = "8BD38031-DE22-40A8-9B6D-A241B2FCD7F2", MappedType = typeof(Modes))]
|
||||
public readonly InputSlot<int> Mode = new ();
|
||||
|
||||
|
||||
|
||||
private enum Modes
|
||||
{
|
||||
ToUpperCase,
|
||||
ToLowerCase,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "acdd78b1-4e66-4fd0-a36b-5318670fefd4"/*ChangeCase*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "041c98b6-4450-46d7-9dae-c9030c88b9e6"/*InputText*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "8bd38031-de22-40a8-9b6d-a241b2fcd7f2"/*Mode*/,
|
||||
"DefaultValue": 0
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "acdd78b1-4e66-4fd0-a36b-5318670fefd4"/*ChangeCase*/,
|
||||
"Description": "Changes a case of string to upper or lower case.",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "041c98b6-4450-46d7-9dae-c9030c88b9e6"/*InputText*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "8bd38031-de22-40a8-9b6d-a241b2fcd7f2"/*Mode*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 90.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "ecf66a1e-45e5-4e0c-ac9e-a784a9339153"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
using T3.Core.Utils;
|
||||
|
||||
namespace Lib.@string.transform;
|
||||
|
||||
[Guid("96ccea19-c37f-4ee4-8dd2-5abdb347f5a1")]
|
||||
internal sealed class WrapString : Instance<WrapString>
|
||||
{
|
||||
[Output(Guid = "83571519-ade1-4508-bf4c-c3d734cf5603")]
|
||||
public readonly Slot<string> Result = new();
|
||||
|
||||
public WrapString()
|
||||
{
|
||||
Result.UpdateAction += Update;
|
||||
}
|
||||
|
||||
private void Update(EvaluationContext context)
|
||||
{
|
||||
var str = InputText.GetValue(context);
|
||||
var mode = Mode.GetEnumValue<WrapLinesModes>(context);
|
||||
var wrapColumn = WrapColumn.GetValue(context).Clamp(1,10000);
|
||||
|
||||
_stringBuilder.Clear();
|
||||
_stringBuilder.Append(str);
|
||||
InsertLineWraps(mode, _stringBuilder, 0, 0, wrapColumn);
|
||||
Result.Value = _stringBuilder.ToString();
|
||||
}
|
||||
|
||||
|
||||
private static void InsertLineWraps(WrapLinesModes lineWrap, StringBuilder stringBuilder, int insertPos, int insertLength, int wrapColumn)
|
||||
{
|
||||
if (lineWrap == WrapLinesModes.WrapAtCharacters)
|
||||
{
|
||||
Log.Warning("WrapAtCharacters has been deprecated. Use WrapToFillBlock instead.");
|
||||
}
|
||||
else if (lineWrap == WrapLinesModes.WrapAtWords)
|
||||
{
|
||||
int pos = 0;
|
||||
int currentLineLength = 0;
|
||||
int lastValidBreakPos = -1;
|
||||
while (pos < stringBuilder.Length)
|
||||
{
|
||||
var c = stringBuilder[pos];
|
||||
if (c == '\n')
|
||||
{
|
||||
currentLineLength = 0;
|
||||
lastValidBreakPos = -1;
|
||||
}
|
||||
|
||||
else if (c == ' ' || c == '.' || c == ',' || c == '/')
|
||||
{
|
||||
lastValidBreakPos = pos;
|
||||
currentLineLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentLineLength++;
|
||||
}
|
||||
|
||||
if (currentLineLength > wrapColumn && lastValidBreakPos != -1)
|
||||
{
|
||||
stringBuilder[lastValidBreakPos] = '\n';
|
||||
pos = lastValidBreakPos;
|
||||
lastValidBreakPos = -1;
|
||||
currentLineLength = 0;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else if (lineWrap == WrapLinesModes.WrapToFillBlock)
|
||||
{
|
||||
int pos = 0;
|
||||
int currentLineLength = 0;
|
||||
int lastValidBreakPos = -1;
|
||||
|
||||
while (pos < stringBuilder.Length)
|
||||
{
|
||||
var c = stringBuilder[pos];
|
||||
if (c == '\n')
|
||||
{
|
||||
stringBuilder[pos] = ' ';
|
||||
//currentLineLength = 0;
|
||||
lastValidBreakPos = pos;
|
||||
currentLineLength++;
|
||||
}
|
||||
|
||||
else if (c == ' ' || c == '.' || c == ',' || c == '/')
|
||||
{
|
||||
lastValidBreakPos = pos;
|
||||
currentLineLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentLineLength++;
|
||||
}
|
||||
|
||||
if (currentLineLength > wrapColumn && lastValidBreakPos != -1)
|
||||
{
|
||||
stringBuilder[lastValidBreakPos] = '\n';
|
||||
pos = lastValidBreakPos;
|
||||
lastValidBreakPos = -1;
|
||||
currentLineLength = 0;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else if (lineWrap == WrapLinesModes.SolidBlock)
|
||||
{
|
||||
int pos = 0;
|
||||
int currentLineLength = 0;
|
||||
while (pos < stringBuilder.Length)
|
||||
{
|
||||
var c = stringBuilder[pos];
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
stringBuilder.Remove(pos, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
currentLineLength++;
|
||||
pos++;
|
||||
|
||||
if (currentLineLength == wrapColumn)
|
||||
{
|
||||
stringBuilder.Insert(pos, '\n');
|
||||
pos++;
|
||||
currentLineLength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly StringBuilder _stringBuilder = new();
|
||||
|
||||
|
||||
private enum WrapLinesModes
|
||||
{
|
||||
DontWrap,
|
||||
WrapAtWords,
|
||||
WrapAtCharacters,
|
||||
WrapToFillBlock,
|
||||
SolidBlock,
|
||||
}
|
||||
|
||||
[Input(Guid = "85ad6b56-45eb-484e-b7d9-a93d52f8e54d")]
|
||||
public readonly InputSlot<string> InputText = new();
|
||||
|
||||
[Input(Guid = "545629C0-C027-4E7C-888C-8E0589940D9D")]
|
||||
public readonly InputSlot<int> WrapColumn = new();
|
||||
|
||||
[Input(Guid = "9a474693-b2f2-4293-bb52-2f9401a0c928", MappedType = typeof(WrapLinesModes))]
|
||||
public readonly InputSlot<int> Mode = new ();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "96ccea19-c37f-4ee4-8dd2-5abdb347f5a1"/*WrapString*/,
|
||||
"Inputs": [
|
||||
{
|
||||
"Id": "545629c0-c027-4e7c-888c-8e0589940d9d"/*WrapColumn*/,
|
||||
"DefaultValue": 100
|
||||
},
|
||||
{
|
||||
"Id": "85ad6b56-45eb-484e-b7d9-a93d52f8e54d"/*InputText*/,
|
||||
"DefaultValue": ""
|
||||
},
|
||||
{
|
||||
"Id": "9a474693-b2f2-4293-bb52-2f9401a0c928"/*Mode*/,
|
||||
"DefaultValue": 1
|
||||
}
|
||||
],
|
||||
"Children": [],
|
||||
"Connections": []
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"FormatVersion": 3,
|
||||
"Id": "96ccea19-c37f-4ee4-8dd2-5abdb347f5a1"/*WrapString*/,
|
||||
"Description": "Wraps a string at a column width",
|
||||
"SymbolTags": "1",
|
||||
"InputUis": [
|
||||
{
|
||||
"InputId": "545629c0-c027-4e7c-888c-8e0589940d9d"/*WrapColumn*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 90.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"InputId": "85ad6b56-45eb-484e-b7d9-a93d52f8e54d"/*InputText*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 45.0
|
||||
},
|
||||
"Usage": "Default"
|
||||
},
|
||||
{
|
||||
"InputId": "9a474693-b2f2-4293-bb52-2f9401a0c928"/*Mode*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 90.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"SymbolChildUis": [],
|
||||
"OutputUis": [
|
||||
{
|
||||
"OutputId": "83571519-ade1-4508-bf4c-c3d734cf5603"/*Result*/,
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user