Sicherung
This commit is contained in:
16
Kalk/Kalk.Core/Modules/Vectors/IKalkVectorObject.cs
Normal file
16
Kalk/Kalk.Core/Modules/Vectors/IKalkVectorObject.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace Kalk.Core
|
||||
{
|
||||
public interface IKalkVectorObject
|
||||
{
|
||||
int Length { get; }
|
||||
|
||||
Type ElementType { get; }
|
||||
}
|
||||
|
||||
public interface IKalkVectorObject<T> : IKalkVectorObject
|
||||
{
|
||||
object Transform(Func<T, T> apply);
|
||||
}
|
||||
}
|
||||
178
Kalk/Kalk.Core/Modules/Vectors/KalkBool.cs
Normal file
178
Kalk/Kalk.Core/Modules/Vectors/KalkBool.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using Scriban;
|
||||
using Scriban.Parsing;
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core
|
||||
{
|
||||
public struct KalkBool : IEquatable<KalkBool>, IFormattable, IConvertible, IScriptConvertibleTo, IScriptConvertibleFrom, IScriptCustomTypeInfo
|
||||
{
|
||||
private int _value;
|
||||
|
||||
public KalkBool(bool value)
|
||||
{
|
||||
_value = value ? -1 : 0;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ToString(null, null);
|
||||
}
|
||||
|
||||
public bool TryConvertFrom(TemplateContext context, SourceSpan span, object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
_value = Convert.ToBoolean(value) ? -1 : 0;
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryConvertTo(TemplateContext context, SourceSpan span, Type type, out object value)
|
||||
{
|
||||
if (type == typeof(bool))
|
||||
{
|
||||
value = (bool) this;
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
value = Convert.ChangeType(_value, type);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public string ToString(string? format, IFormatProvider? formatProvider)
|
||||
{
|
||||
return _value != 0 ? "true" : "false";
|
||||
}
|
||||
|
||||
public bool Equals(KalkBool other)
|
||||
{
|
||||
return _value == other._value;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is KalkBool other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
public static bool operator ==(KalkBool left, KalkBool right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(KalkBool left, KalkBool right)
|
||||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
public static implicit operator bool(KalkBool b) => b._value != 0;
|
||||
|
||||
public static implicit operator KalkBool(bool b) => new KalkBool(b);
|
||||
TypeCode IConvertible.GetTypeCode()
|
||||
{
|
||||
return _value.GetTypeCode();
|
||||
}
|
||||
|
||||
bool IConvertible.ToBoolean(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToBoolean(provider);
|
||||
}
|
||||
|
||||
byte IConvertible.ToByte(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToByte(provider);
|
||||
}
|
||||
|
||||
char IConvertible.ToChar(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToChar(provider);
|
||||
}
|
||||
|
||||
DateTime IConvertible.ToDateTime(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToDateTime(provider);
|
||||
}
|
||||
|
||||
decimal IConvertible.ToDecimal(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToDecimal(provider);
|
||||
}
|
||||
|
||||
double IConvertible.ToDouble(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToDouble(provider);
|
||||
}
|
||||
|
||||
short IConvertible.ToInt16(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToInt16(provider);
|
||||
}
|
||||
|
||||
int IConvertible.ToInt32(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToInt32(provider);
|
||||
}
|
||||
|
||||
long IConvertible.ToInt64(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToInt64(provider);
|
||||
}
|
||||
|
||||
sbyte IConvertible.ToSByte(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToSByte(provider);
|
||||
}
|
||||
|
||||
float IConvertible.ToSingle(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToSingle(provider);
|
||||
}
|
||||
|
||||
string IConvertible.ToString(IFormatProvider? provider)
|
||||
{
|
||||
return _value.ToString(provider);
|
||||
}
|
||||
|
||||
object IConvertible.ToType(Type conversionType, IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToType(conversionType, provider);
|
||||
}
|
||||
|
||||
ushort IConvertible.ToUInt16(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToUInt16(provider);
|
||||
}
|
||||
|
||||
uint IConvertible.ToUInt32(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToUInt32(provider);
|
||||
}
|
||||
|
||||
ulong IConvertible.ToUInt64(IFormatProvider? provider)
|
||||
{
|
||||
return ((IConvertible) _value).ToUInt64(provider);
|
||||
}
|
||||
|
||||
public string TypeName => "bool";
|
||||
}
|
||||
}
|
||||
181
Kalk/Kalk.Core/Modules/Vectors/KalkColor.cs
Normal file
181
Kalk/Kalk.Core/Modules/Vectors/KalkColor.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Consolus;
|
||||
using Scriban;
|
||||
using Scriban.Parsing;
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core
|
||||
{
|
||||
// https://github.com/google/palette.js/tree/master
|
||||
|
||||
[ScriptTypeName("color")]
|
||||
public abstract class KalkColor : KalkVector<byte>
|
||||
{
|
||||
protected KalkColor(int dimension) : base(dimension)
|
||||
{
|
||||
}
|
||||
|
||||
protected KalkColor(IReadOnlyList<byte> list) : base(list)
|
||||
{
|
||||
}
|
||||
|
||||
protected KalkColor(KalkVector<byte> values) : base(values)
|
||||
{
|
||||
}
|
||||
|
||||
public int rgb => (int)((r << 16) | (g << 8) | b);
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
KalkColorRgb.TryGetKnownColor(rgb, out var name);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetMembers()
|
||||
{
|
||||
for (int i = 0; i < Math.Min(4, Length); i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
yield return "r";
|
||||
break;
|
||||
case 1:
|
||||
yield return "g";
|
||||
break;
|
||||
case 2:
|
||||
yield return "b";
|
||||
break;
|
||||
case 3:
|
||||
yield return "a";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
yield return "name";
|
||||
}
|
||||
|
||||
public override bool TryGetValue(TemplateContext context, SourceSpan span, string member, out object result)
|
||||
{
|
||||
if (member == "name")
|
||||
{
|
||||
result = Name;
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.TryGetValue(context, span, member, out result);
|
||||
}
|
||||
|
||||
|
||||
private static float Clamp01(float value) => Math.Clamp(value, 0.0f, 1.0f);
|
||||
|
||||
public KalkVector<float> GetFloatVector(int targetDimension)
|
||||
{
|
||||
return this is KalkColorRgb
|
||||
? targetDimension == 4 ?
|
||||
new KalkVector<float>(Clamp01(this[0] / 255.0f), Clamp01(this[1] / 255.0f), Clamp01(this[2] / 255.0f), 1.0f):
|
||||
new KalkVector<float>(Clamp01(this[0] / 255.0f), Clamp01(this[1] / 255.0f), Clamp01(this[2] / 255.0f))
|
||||
: new KalkVector<float>(Clamp01(this[0] / 255.0f), Clamp01(this[1] / 255.0f), Clamp01(this[2] / 255.0f), Clamp01(this[3] / 255.0f));
|
||||
}
|
||||
|
||||
protected override object GetSwizzleValue(ComponentKind kind, byte result)
|
||||
{
|
||||
return kind == ComponentKind.xyzw ? (object)Clamp01(result / 255.0f) : result;
|
||||
}
|
||||
|
||||
protected override byte TransformComponentToSet(TemplateContext context, SourceSpan span, ComponentKind kind, object value)
|
||||
{
|
||||
return kind == ComponentKind.xyzw ? (byte)(Clamp01(context.ToObject<float>(span, value)) * 255) : base.TransformComponentToSet(context, span, kind, value);
|
||||
}
|
||||
|
||||
protected override KalkVector NewVector(ComponentKind kind, IReadOnlyList<byte> list)
|
||||
{
|
||||
if (kind == ComponentKind.xyzw)
|
||||
{
|
||||
if (list.Count == 4)
|
||||
{
|
||||
return new KalkVector<float>(Clamp01(list[0] / 255.0f), Clamp01(list[1] / 255.0f), Clamp01(list[2] / 255.0f), Clamp01(list[3] / 255.0f));
|
||||
}
|
||||
|
||||
if (list.Count == 3)
|
||||
{
|
||||
return new KalkVector<float>(Clamp01(list[0] / 255.0f), Clamp01(list[1] / 255.0f), Clamp01(list[2] / 255.0f));
|
||||
}
|
||||
|
||||
if (list.Count == 2)
|
||||
{
|
||||
return new KalkVector<float>(Clamp01(list[0] / 255.0f), Clamp01(list[1] / 255.0f));
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Cannot create a float vector type from this rgba components");
|
||||
}
|
||||
else
|
||||
{
|
||||
return list.Count == 4 ? new KalkColorRgba(list[0], list[1], list[2], list[3]) : list.Count == 3 ? new KalkColorRgb(list[0], list[1], list[2]) : base.NewVector(kind, list);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract override KalkVector<byte> NewVector(int length);
|
||||
|
||||
public abstract override string TypeName { get; }
|
||||
|
||||
public override string ToString(string format, IFormatProvider formatProvider)
|
||||
{
|
||||
var engine = formatProvider as KalkEngine;
|
||||
var builder = new StringBuilder();
|
||||
builder.Append(TypeName);
|
||||
builder.Append('(');
|
||||
var length = this is KalkColorRgb ? 3 : 4;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (i > 0) builder.Append(", ");
|
||||
builder.Append(engine != null ? engine.ObjectToString(this[i]) : this[i].ToString(null, formatProvider));
|
||||
}
|
||||
builder.Append(')');
|
||||
|
||||
bool isAligned = format == "aligned";
|
||||
|
||||
// rgb(240, 248, 255)
|
||||
// rgb(255, 255, 255, 255)
|
||||
if (isAligned)
|
||||
{
|
||||
if (length == 3)
|
||||
{
|
||||
builder.Append(' ', "rgb(255, 255, 255)".Length - builder.Length);
|
||||
}
|
||||
else if (length == 4)
|
||||
{
|
||||
builder.Append(' ', "rgb(255, 255, 255, 255)".Length - builder.Length);
|
||||
}
|
||||
}
|
||||
|
||||
builder.Append(" ## ");
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
builder.Append($"{this[i]:X2}");
|
||||
}
|
||||
|
||||
if (engine != null && engine.IsOutputSupportHighlighting)
|
||||
{
|
||||
builder.Append(" ");
|
||||
builder.Append(ConsoleStyle.BackgroundRgb(this[0], this[1], this[2]));
|
||||
builder.Append(" ");
|
||||
builder.Append(ConsoleStyle.Reset);
|
||||
}
|
||||
|
||||
// Add known color name
|
||||
if (KalkColorRgb.TryGetKnownColor(rgb, out var colorName))
|
||||
{
|
||||
builder.Append(isAligned ? $" {colorName,-20}" : $" {colorName}");
|
||||
}
|
||||
|
||||
builder.Append(" ##");
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
69
Kalk/Kalk.Core/Modules/Vectors/KalkColorConstructor.cs
Normal file
69
Kalk/Kalk.Core/Modules/Vectors/KalkColorConstructor.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Scriban;
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core
|
||||
{
|
||||
public abstract class KalkColorConstructor : KalkVectorConstructor<byte>
|
||||
{
|
||||
protected KalkColorConstructor(int dimension) : base(dimension)
|
||||
{
|
||||
}
|
||||
|
||||
protected abstract override KalkVector<byte> NewVector(int dimension);
|
||||
|
||||
protected override byte GetArgumentValue(TemplateContext context, object arg)
|
||||
{
|
||||
switch (arg)
|
||||
{
|
||||
case float f32:
|
||||
return (byte)(255 * Math.Clamp(f32, 0.0f, 1.0f));
|
||||
case double f64:
|
||||
return (byte)(255 * Math.Clamp(f64, 0.0, 1.0));
|
||||
case decimal dec:
|
||||
return (byte)(255 * Math.Clamp(dec, 0.0m, 1.0m));
|
||||
default:
|
||||
return base.GetArgumentValue(context, arg);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ProcessSingleArgument(TemplateContext context, ref int index, object arg, KalkVector<byte> vector)
|
||||
{
|
||||
int value;
|
||||
switch (arg)
|
||||
{
|
||||
case string rgbStr:
|
||||
try
|
||||
{
|
||||
if (!KalkColorRgb.TryGetKnownColor(rgbStr, out value))
|
||||
{
|
||||
value = int.Parse(rgbStr.TrimStart('#'), System.Globalization.NumberStyles.HexNumber);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new ScriptArgumentException(0, $"Expecting a known color (e.g `AliceBlue`) or an hexadecimal rgb string (e.g #FF80C2) instead of `{rgbStr}`. Type `colors` for listing known colors.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (arg is IList)
|
||||
{
|
||||
base.ProcessSingleArgument(context, ref index, arg, vector);
|
||||
return;
|
||||
}
|
||||
value = context.ToObject<int>(context.CurrentSpan, arg);
|
||||
break;
|
||||
}
|
||||
|
||||
vector[index++] = (byte)((value >> 16) & 0xFF);
|
||||
vector[index++] = (byte)((value >> 8) & 0xFF);
|
||||
vector[index++] = (byte)(value & 0xFF);
|
||||
|
||||
if (Dimension == 4)
|
||||
{
|
||||
vector[index++] = (byte)((value >> 24) & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
220
Kalk/Kalk.Core/Modules/Vectors/KalkColorRgb.cs
Normal file
220
Kalk/Kalk.Core/Modules/Vectors/KalkColorRgb.cs
Normal file
@@ -0,0 +1,220 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core
|
||||
{
|
||||
[ScriptTypeName("rgb")]
|
||||
public class KalkColorRgb : KalkColor
|
||||
{
|
||||
public KalkColorRgb() : base(4)
|
||||
{
|
||||
this[3] = 0xFF;
|
||||
}
|
||||
|
||||
public KalkColorRgb(KalkColorRgb values) : base(values)
|
||||
{
|
||||
this[3] = 0xFF;
|
||||
}
|
||||
|
||||
public KalkColorRgb(byte r, byte g, byte b) : this()
|
||||
{
|
||||
this[0] = r;
|
||||
this[1] = g;
|
||||
this[2] = b;
|
||||
}
|
||||
|
||||
public KalkColorRgb(int rgb) : this()
|
||||
{
|
||||
this[0] = (byte)((rgb >> 16) & 0xFF);
|
||||
this[1] = (byte)((rgb >> 8) & 0xFF);
|
||||
this[2] = (byte)(rgb & 0xFF);
|
||||
this[3] = 0xFF;
|
||||
}
|
||||
|
||||
public override string TypeName => "rgb";
|
||||
|
||||
public override KalkVector Clone()
|
||||
{
|
||||
return new KalkColorRgb(this);
|
||||
}
|
||||
|
||||
protected override KalkVector<byte> NewVector(int length) => new KalkColorRgb();
|
||||
|
||||
|
||||
public static bool TryGetKnownColor(string color, out int rgb)
|
||||
{
|
||||
if (color == null) throw new ArgumentNullException(nameof(color));
|
||||
return KnownColors.TryGetValue(color, out rgb);
|
||||
}
|
||||
|
||||
public static bool TryGetKnownColor(int rgb, out string color)
|
||||
{
|
||||
return ReverseKnownColors.TryGetValue(rgb, out color);
|
||||
}
|
||||
|
||||
public static List<KalkColorRgb> GetKnownColors()
|
||||
{
|
||||
return KnownColors.OrderBy(x => x.Key).Select(x => new KalkColorRgb(x.Value)).ToList();
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, int> KnownColors = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{"AliceBlue", 0xF0F8FF},
|
||||
{"AntiqueWhite", 0xFAEBD7},
|
||||
{"Aqua", 0x00FFFF},
|
||||
{"Aquamarine", 0x7FFFD4},
|
||||
{"Azure", 0xF0FFFF},
|
||||
{"Beige", 0xF5F5DC},
|
||||
{"Bisque", 0xFFE4C4},
|
||||
{"Black", 0x0},
|
||||
{"BlanchedAlmond", 0xFFEBCD},
|
||||
{"Blue", 0x0000FF},
|
||||
{"BlueViolet", 0x8A2BE2},
|
||||
{"Brown", 0xA52A2A},
|
||||
{"BurlyWood", 0xDEB887},
|
||||
{"CadetBlue", 0x5F9EA0},
|
||||
{"Chartreuse", 0x7FFF00},
|
||||
{"Chocolate", 0xD2691E},
|
||||
{"Coral", 0xFF7F50},
|
||||
{"CornflowerBlue", 0x6495ED},
|
||||
{"Cornsilk", 0xFFF8DC},
|
||||
{"Crimson", 0xDC143C},
|
||||
{"Cyan", 0x00FFFF},
|
||||
{"DarkBlue", 0x00008B},
|
||||
{"DarkCyan", 0x008B8B},
|
||||
{"DarkGoldenrod", 0xB8860B},
|
||||
{"DarkGray", 0xA9A9A9},
|
||||
{"DarkGreen", 0x6400},
|
||||
{"DarkKhaki", 0xBDB76B},
|
||||
{"DarkMagenta", 0x8B008B},
|
||||
{"DarkOliveGreen", 0x556B2F},
|
||||
{"DarkOrange", 0xFF8C00},
|
||||
{"DarkOrchid", 0x9932CC},
|
||||
{"DarkRed", 0x8B0000},
|
||||
{"DarkSalmon", 0xE9967A},
|
||||
{"DarkSeaGreen", 0x8FBC8F},
|
||||
{"DarkSlateBlue", 0x483D8B},
|
||||
{"DarkSlateGray", 0x2F4F4F},
|
||||
{"DarkTurquoise", 0x00CED1},
|
||||
{"DarkViolet", 0x9400D3},
|
||||
{"DeepPink", 0xFF1493},
|
||||
{"DeepSkyBlue", 0x00BFFF},
|
||||
{"DimGray", 0x696969},
|
||||
{"DodgerBlue", 0x1E90FF},
|
||||
{"Firebrick", 0xB22222},
|
||||
{"FloralWhite", 0xFFFAF0},
|
||||
{"ForestGreen", 0x228B22},
|
||||
{"Fuchsia", 0xFF00FF},
|
||||
{"Gainsboro", 0xDCDCDC},
|
||||
{"GhostWhite", 0xF8F8FF},
|
||||
{"Gold", 0xFFD700},
|
||||
{"Goldenrod", 0xDAA520},
|
||||
{"Gray", 0x808080},
|
||||
{"Green", 0x8000},
|
||||
{"GreenYellow", 0xADFF2F},
|
||||
{"Honeydew", 0xF0FFF0},
|
||||
{"HotPink", 0xFF69B4},
|
||||
{"IndianRed", 0xCD5C5C},
|
||||
{"Indigo", 0x4B0082},
|
||||
{"Ivory", 0xFFFFF0},
|
||||
{"Khaki", 0xF0E68C},
|
||||
{"Lavender", 0xE6E6FA},
|
||||
{"LavenderBlush", 0xFFF0F5},
|
||||
{"LawnGreen", 0x7CFC00},
|
||||
{"LemonChiffon", 0xFFFACD},
|
||||
{"LightBlue", 0xADD8E6},
|
||||
{"LightCoral", 0xF08080},
|
||||
{"LightCyan", 0xE0FFFF},
|
||||
{"LightGoldenrodYellow", 0xFAFAD2},
|
||||
{"LightGreen", 0x90EE90},
|
||||
{"LightGray", 0xD3D3D3},
|
||||
{"LightPink", 0xFFB6C1},
|
||||
{"LightSalmon", 0xFFA07A},
|
||||
{"LightSeaGreen", 0x20B2AA},
|
||||
{"LightSkyBlue", 0x87CEFA},
|
||||
{"LightSlateGray", 0x778899},
|
||||
{"LightSteelBlue", 0xB0C4DE},
|
||||
{"LightYellow", 0xFFFFE0},
|
||||
{"Lime", 0x00FF00},
|
||||
{"LimeGreen", 0x32CD32},
|
||||
{"Linen", 0xFAF0E6},
|
||||
{"Magenta", 0xFF00FF},
|
||||
{"Maroon", 0x800000},
|
||||
{"MediumAquamarine", 0x66CDAA},
|
||||
{"MediumBlue", 0x0000CD},
|
||||
{"MediumOrchid", 0xBA55D3},
|
||||
{"MediumPurple", 0x9370DB},
|
||||
{"MediumSeaGreen", 0x3CB371},
|
||||
{"MediumSlateBlue", 0x7B68EE},
|
||||
{"MediumSpringGreen", 0x00FA9A},
|
||||
{"MediumTurquoise", 0x48D1CC},
|
||||
{"MediumVioletRed", 0xC71585},
|
||||
{"MidnightBlue", 0x191970},
|
||||
{"MintCream", 0xF5FFFA},
|
||||
{"MistyRose", 0xFFE4E1},
|
||||
{"Moccasin", 0xFFE4B5},
|
||||
{"NavajoWhite", 0xFFDEAD},
|
||||
{"Navy", 0x80},
|
||||
{"OldLace", 0xFDF5E6},
|
||||
{"Olive", 0x808000},
|
||||
{"OliveDrab", 0x6B8E23},
|
||||
{"Orange", 0xFFA500},
|
||||
{"OrangeRed", 0xFF4500},
|
||||
{"Orchid", 0xDA70D6},
|
||||
{"PaleGoldenrod", 0xEEE8AA},
|
||||
{"PaleGreen", 0x98FB98},
|
||||
{"PaleTurquoise", 0xAFEEEE},
|
||||
{"PaleVioletRed", 0xDB7093},
|
||||
{"PapayaWhip", 0xFFEFD5},
|
||||
{"PeachPuff", 0xFFDAB9},
|
||||
{"Peru", 0xCD853F},
|
||||
{"Pink", 0xFFC0CB},
|
||||
{"Plum", 0xDDA0DD},
|
||||
{"PowderBlue", 0xB0E0E6},
|
||||
{"Purple", 0x800080},
|
||||
{"RebeccaPurple", 0x663399},
|
||||
{"Red", 0xFF0000},
|
||||
{"RosyBrown", 0xBC8F8F},
|
||||
{"RoyalBlue", 0x41690},
|
||||
{"SaddleBrown", 0x8B4513},
|
||||
{"Salmon", 0xFA8072},
|
||||
{"SandyBrown", 0xF4A460},
|
||||
{"SeaGreen", 0x2E8B57},
|
||||
{"SeaShell", 0xFFF5EE},
|
||||
{"Sienna", 0xA0522D},
|
||||
{"Silver", 0xC0C0C0},
|
||||
{"SkyBlue", 0x87CEEB},
|
||||
{"SlateBlue", 0x6A5ACD},
|
||||
{"SlateGray", 0x708090},
|
||||
{"Snow", 0xFFFAFA},
|
||||
{"SpringGreen", 0x00FF7F},
|
||||
{"SteelBlue", 0x4682B4},
|
||||
{"Tan", 0xD2B48C},
|
||||
{"Teal", 0x8080},
|
||||
{"Thistle", 0xD8BFD8},
|
||||
{"Tomato", 0xFF6347},
|
||||
{"Turquoise", 0x40E0D0},
|
||||
{"Violet", 0xEE82EE},
|
||||
{"Wheat", 0xF5DEB3},
|
||||
{"White", 0xFFFFFF},
|
||||
{"WhiteSmoke", 0xF5F5F5},
|
||||
{"Yellow", 0xFFFF00},
|
||||
{"YellowGreen", 0x9ACD32},
|
||||
};
|
||||
|
||||
private static readonly Dictionary<int, string> ReverseKnownColors = new Dictionary<int, string>();
|
||||
|
||||
static KalkColorRgb()
|
||||
{
|
||||
foreach (var knownColor in KnownColors)
|
||||
{
|
||||
if (!ReverseKnownColors.ContainsKey(knownColor.Value))
|
||||
{
|
||||
ReverseKnownColors.Add(knownColor.Value, knownColor.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Kalk/Kalk.Core/Modules/Vectors/KalkColorRgbConstructor.cs
Normal file
11
Kalk/Kalk.Core/Modules/Vectors/KalkColorRgbConstructor.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Kalk.Core
|
||||
{
|
||||
public class KalkColorRgbConstructor : KalkColorConstructor
|
||||
{
|
||||
public KalkColorRgbConstructor() : base(3)
|
||||
{
|
||||
}
|
||||
|
||||
protected override KalkVector<byte> NewVector(int dimension) => new KalkColorRgb();
|
||||
}
|
||||
}
|
||||
42
Kalk/Kalk.Core/Modules/Vectors/KalkColorRgba.cs
Normal file
42
Kalk/Kalk.Core/Modules/Vectors/KalkColorRgba.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core
|
||||
{
|
||||
[ScriptTypeName("rgba")]
|
||||
public class KalkColorRgba : KalkColor
|
||||
{
|
||||
public KalkColorRgba() : base(4)
|
||||
{
|
||||
}
|
||||
|
||||
public KalkColorRgba(byte r, byte g, byte b, byte a) : this()
|
||||
{
|
||||
this[0] = r;
|
||||
this[1] = g;
|
||||
this[2] = b;
|
||||
this[3] = a;
|
||||
}
|
||||
|
||||
public KalkColorRgba(int rgb) : this()
|
||||
{
|
||||
this[0] = (byte)((rgb >> 16) & 0xFF);
|
||||
this[1] = (byte)((rgb >> 8) & 0xFF);
|
||||
this[2] = (byte)(rgb & 0xFF);
|
||||
this[3] = (byte)((rgb >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
public KalkColorRgba(KalkColorRgba values) : base(values)
|
||||
{
|
||||
}
|
||||
|
||||
public override string TypeName => "rgba";
|
||||
|
||||
public override KalkVector Clone()
|
||||
{
|
||||
return new KalkColorRgba(this);
|
||||
}
|
||||
|
||||
|
||||
protected override KalkVector<byte> NewVector(int length) => new KalkColorRgba();
|
||||
}
|
||||
}
|
||||
11
Kalk/Kalk.Core/Modules/Vectors/KalkColorRgbaConstructor.cs
Normal file
11
Kalk/Kalk.Core/Modules/Vectors/KalkColorRgbaConstructor.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Kalk.Core
|
||||
{
|
||||
public class KalkColorRgbaConstructor : KalkColorConstructor
|
||||
{
|
||||
public KalkColorRgbaConstructor() : base(4)
|
||||
{
|
||||
}
|
||||
|
||||
protected override KalkVector<byte> NewVector(int dimension) => new KalkColorRgba();
|
||||
}
|
||||
}
|
||||
1201
Kalk/Kalk.Core/Modules/Vectors/KalkMatrix.cs
Normal file
1201
Kalk/Kalk.Core/Modules/Vectors/KalkMatrix.cs
Normal file
File diff suppressed because it is too large
Load Diff
1302
Kalk/Kalk.Core/Modules/Vectors/KalkVector.cs
Normal file
1302
Kalk/Kalk.Core/Modules/Vectors/KalkVector.cs
Normal file
File diff suppressed because it is too large
Load Diff
159
Kalk/Kalk.Core/Modules/Vectors/KalkVectorConstructor.cs
Normal file
159
Kalk/Kalk.Core/Modules/Vectors/KalkVectorConstructor.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Kalk.Core.Helpers;
|
||||
using Scriban;
|
||||
using Scriban.Helpers;
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core
|
||||
{
|
||||
public class KalkVectorConstructor<T> : KalkConstructor where T : unmanaged
|
||||
{
|
||||
public KalkVectorConstructor(int dimension)
|
||||
{
|
||||
Dimension = dimension;
|
||||
}
|
||||
|
||||
public int Dimension { get; }
|
||||
|
||||
public KalkVector<T> Invoke(TemplateContext context, object[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
return NewVector(Dimension);
|
||||
}
|
||||
|
||||
var vector = NewVector(Dimension);
|
||||
int index = 0;
|
||||
if (arguments.Length == 1)
|
||||
{
|
||||
var arg = arguments[0];
|
||||
// Replace implicitly Rgb/Rgba to xyzw
|
||||
if (arg is KalkColor color)
|
||||
{
|
||||
if (this is KalkColorConstructor)
|
||||
{
|
||||
var colorLength = color is KalkColorRgb ? 3 : 4;
|
||||
if (Dimension != colorLength)
|
||||
{
|
||||
if (Dimension == 3) // 4 to 3
|
||||
{
|
||||
arg = new KalkVector<byte>(color.r, color.g, color.b);
|
||||
}
|
||||
else // 3 to 4
|
||||
{
|
||||
Debug.Assert(Dimension == 4);
|
||||
arg = new KalkVector<byte>(color.r, color.g, color.b, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = color.GetFloatVector(Dimension);
|
||||
}
|
||||
}
|
||||
var argLength = GetArgLength(arg, true);
|
||||
var length = index + argLength;
|
||||
if (length != Dimension)
|
||||
{
|
||||
throw new ScriptArgumentException(0, $"Invalid number of arguments for {vector.TypeName}. Expecting {Dimension} arguments instead of {length}.");
|
||||
}
|
||||
|
||||
ProcessSingleArgument(context, ref index, arg, vector);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < arguments.Length; i++)
|
||||
{
|
||||
var arg = arguments[i];
|
||||
var argLength = GetArgLength(arg, false);
|
||||
|
||||
var length = index + argLength;
|
||||
if (length > Dimension)
|
||||
{
|
||||
throw new ScriptArgumentException(i, $"Invalid number of arguments for {vector.TypeName}. Expecting {Dimension} arguments instead of {length}.");
|
||||
}
|
||||
|
||||
ProcessArgument(context, ref index, arg, vector);
|
||||
}
|
||||
}
|
||||
|
||||
if (index != Dimension)
|
||||
{
|
||||
throw new ScriptArgumentException(arguments.Length - 1, $"Invalid number of arguments for {vector.TypeName}. Expecting {Dimension} arguments instead of {index}.");
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
private int GetArgLength(object arg, bool isSingleArg)
|
||||
{
|
||||
if (arg is IList list)
|
||||
{
|
||||
int argLength = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
argLength += GetArgLength(list[i], false);
|
||||
}
|
||||
return argLength;
|
||||
}
|
||||
|
||||
return isSingleArg ? Dimension : 1;
|
||||
}
|
||||
|
||||
private void AddListItem(TemplateContext context, ref int index, object arg, KalkVector<T> vector)
|
||||
{
|
||||
if (arg is IList list)
|
||||
{
|
||||
var count = list.Count;
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
AddListItem(context, ref index, list[j], vector);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = GetArgumentValue(context, arg);
|
||||
vector[index++] = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ProcessSingleArgument(TemplateContext context, ref int index, object arg, KalkVector<T> vector)
|
||||
{
|
||||
if (arg is IList list)
|
||||
{
|
||||
AddListItem(context, ref index, list, vector);
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = GetArgumentValue(context, arg);
|
||||
for (int j = 0; j < Dimension; j++)
|
||||
{
|
||||
vector[index++] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void ProcessArgument(TemplateContext context, ref int index, object arg, KalkVector<T> vector)
|
||||
{
|
||||
if (arg is IList list)
|
||||
{
|
||||
AddListItem(context, ref index, list, vector);
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = GetArgumentValue(context, arg);
|
||||
vector[index++] = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual KalkVector<T> NewVector(int dimension) => new KalkVector<T>(dimension);
|
||||
|
||||
protected virtual T GetArgumentValue(TemplateContext context, object value)
|
||||
{
|
||||
return context.ToObject<T>(context.CurrentSpan, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
111
Kalk/Kalk.Core/Modules/Vectors/PrimitiveSwizzleAccessor.cs
Normal file
111
Kalk/Kalk.Core/Modules/Vectors/PrimitiveSwizzleAccessor.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Scriban;
|
||||
using Scriban.Parsing;
|
||||
using Scriban.Runtime;
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core
|
||||
{
|
||||
public class PrimitiveSwizzleAccessor : IObjectAccessor
|
||||
{
|
||||
public static readonly PrimitiveSwizzleAccessor Default = new PrimitiveSwizzleAccessor();
|
||||
|
||||
private PrimitiveSwizzleAccessor()
|
||||
{
|
||||
}
|
||||
|
||||
public int GetMemberCount(TemplateContext context, SourceSpan span, object target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetMembers(TemplateContext context, SourceSpan span, object target)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
public bool HasMember(TemplateContext context, SourceSpan span, object target, string member)
|
||||
{
|
||||
return IsSwizzle(member);
|
||||
}
|
||||
|
||||
public bool TryGetValue(TemplateContext context, SourceSpan span, object target, string member, out object value)
|
||||
{
|
||||
var targetFloat = context.ToObject<float>(span, target);
|
||||
|
||||
if (member.Length == 1)
|
||||
{
|
||||
value = targetFloat;
|
||||
return true;
|
||||
}
|
||||
|
||||
var vector = new KalkVector<float>(member.Length);
|
||||
int index = 0;
|
||||
for(int i = 0; i < member.Length; i++)
|
||||
{
|
||||
var c = member[i];
|
||||
switch (c)
|
||||
{
|
||||
case 'x':
|
||||
vector[index] = targetFloat;
|
||||
break;
|
||||
case 'y':
|
||||
vector[index] = targetFloat;
|
||||
break;
|
||||
case 'z':
|
||||
vector[index] = targetFloat;
|
||||
break;
|
||||
case 'w':
|
||||
vector[index] = targetFloat;
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
value = vector;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TrySetValue(TemplateContext context, SourceSpan span, object target, string member, object value)
|
||||
{
|
||||
throw new ScriptRuntimeException(span, "Cannot set a member on a primitive");
|
||||
}
|
||||
|
||||
public bool TryGetItem(TemplateContext context, SourceSpan span, object target, object index, out object value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TrySetItem(TemplateContext context, SourceSpan span, object target, object index, object value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool HasIndexer => false;
|
||||
|
||||
public Type IndexType => typeof(int);
|
||||
|
||||
private static bool IsSwizzle(string text)
|
||||
{
|
||||
if (text.Length > 4) return false;
|
||||
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
var c = text[i];
|
||||
switch (c)
|
||||
{
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z':
|
||||
case 'w':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
538
Kalk/Kalk.Core/Modules/Vectors/TypesModule.cs
Normal file
538
Kalk/Kalk.Core/Modules/Vectors/TypesModule.cs
Normal file
@@ -0,0 +1,538 @@
|
||||
using System;
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core.Modules
|
||||
{
|
||||
public sealed partial class TypesModule : KalkModuleWithFunctions
|
||||
{
|
||||
public const string CategoryTypeConstructors = "Type Constructors";
|
||||
public const string CategoryVectorTypeConstructors = "Type Vector Constructors";
|
||||
private static readonly KalkColorRgbConstructor RgbConstructor = new KalkColorRgbConstructor();
|
||||
private static readonly KalkColorRgbaConstructor RgbaConstructor = new KalkColorRgbaConstructor();
|
||||
|
||||
public TypesModule() : base("Types")
|
||||
{
|
||||
IsBuiltin = true;
|
||||
RegisterFunctionsAuto();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an unsigned byte value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>An unsigned byte value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> byte
|
||||
/// # byte
|
||||
/// out = 0
|
||||
/// >>> byte 0
|
||||
/// # byte(0)
|
||||
/// out = 0
|
||||
/// >>> byte 255
|
||||
/// # byte(255)
|
||||
/// out = 255
|
||||
/// ```
|
||||
/// </example>
|
||||
/// <test>
|
||||
/// ```kalk
|
||||
/// >>> byte 256
|
||||
/// Unable to convert type `int` to `byte`
|
||||
/// ```
|
||||
/// </test>
|
||||
[KalkExport("byte", CategoryTypeConstructors)]
|
||||
public byte CreateByte(object value = null) => value == null ? (byte)0 : Engine.ToObject<byte>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a signed-byte value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>A signed-byte value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> sbyte
|
||||
/// # sbyte
|
||||
/// out = 0
|
||||
/// >>> sbyte 0
|
||||
/// # sbyte(0)
|
||||
/// out = 0
|
||||
/// >>> sbyte 127
|
||||
/// # sbyte(127)
|
||||
/// out = 127
|
||||
/// >>> sbyte(-128)
|
||||
/// # sbyte(-128)
|
||||
/// out = -128
|
||||
/// ```
|
||||
/// </example>
|
||||
/// <test>
|
||||
/// ```kalk
|
||||
/// >>> sbyte 128
|
||||
/// Unable to convert type `int` to `sbyte`
|
||||
/// ```
|
||||
/// </test>
|
||||
[KalkExport("sbyte", CategoryTypeConstructors)]
|
||||
public sbyte CreateSByte(object value = null) => value == null ? (sbyte)0 : Engine.ToObject<sbyte>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a signed-short (16-bit) value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>A signed-short (16-bit) value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> short
|
||||
/// # short
|
||||
/// out = 0
|
||||
/// >>> short 0
|
||||
/// # short(0)
|
||||
/// out = 0
|
||||
/// >>> short 32767
|
||||
/// # short(32767)
|
||||
/// out = 32_767
|
||||
/// >>> short(-32768)
|
||||
/// # short(-32768)
|
||||
/// out = -32_768
|
||||
/// >>> short 32768
|
||||
/// Unable to convert type `int` to `short`
|
||||
/// ```
|
||||
/// </example>
|
||||
/// <test>
|
||||
/// ```kalk
|
||||
/// >>> short 32768
|
||||
/// Unable to convert type `int` to `short`
|
||||
/// ```
|
||||
/// </test>
|
||||
[KalkExport("short", CategoryTypeConstructors)]
|
||||
public short CreateShort(object value = null) => value == null ? (short)0 : Engine.ToObject<short>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an unsigned short (16-bit) value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>An unsigned short (16-bit) value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> ushort
|
||||
/// # ushort
|
||||
/// out = 0
|
||||
/// >>> ushort 0
|
||||
/// # ushort(0)
|
||||
/// out = 0
|
||||
/// >>> ushort 65535
|
||||
/// # ushort(65535)
|
||||
/// out = 65_535
|
||||
/// ```
|
||||
/// </example>
|
||||
/// <test>
|
||||
/// ```kalk
|
||||
/// >>> ushort 65536
|
||||
/// Unable to convert type `int` to `ushort`
|
||||
/// ```
|
||||
/// </test>
|
||||
[KalkExport("ushort", CategoryTypeConstructors)]
|
||||
public ushort CreateUShort(object value = null) => value == null ? (ushort)0 : Engine.ToObject<ushort>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an unsigned int (32-bit) value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>An unsigned int (32-bit) value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> uint
|
||||
/// # uint
|
||||
/// out = 0
|
||||
/// >>> uint 0
|
||||
/// # uint(0)
|
||||
/// out = 0
|
||||
/// >>> uint(1<<32 - 1)
|
||||
/// # uint(1 << 32 - 1)
|
||||
/// out = 4_294_967_295
|
||||
/// ```
|
||||
/// </example>
|
||||
/// <test>
|
||||
/// ```kalk
|
||||
/// >>> uint 1 << 32
|
||||
/// Unable to convert type `long` to `uint`
|
||||
/// ```
|
||||
/// </test>
|
||||
[KalkExport("uint", CategoryTypeConstructors)]
|
||||
public uint CreateUInt(object value = null) => value == null ? 0U : Engine.ToObject<uint>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a signed-int (32-bit) value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>A signed-int (32-bit) value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> int
|
||||
/// # int
|
||||
/// out = 0
|
||||
/// >>> int 0
|
||||
/// # int(0)
|
||||
/// out = 0
|
||||
/// >>> int(1 << 31 - 1)
|
||||
/// # int(1 << 31 - 1)
|
||||
/// out = 2_147_483_647
|
||||
/// >>> int(-(1<<31))
|
||||
/// # int(-(1 << 31))
|
||||
/// out = -2_147_483_648
|
||||
/// ```
|
||||
/// </example>
|
||||
/// <test>
|
||||
/// ```kalk
|
||||
/// >>> int 1 << 31
|
||||
/// Unable to convert type `long` to int
|
||||
/// ```
|
||||
/// </test>
|
||||
[KalkExport("int", CategoryTypeConstructors)]
|
||||
public int CreateInt(object value = null) => value == null ? 0 : Engine.ToObject<int>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an unsigned long (64-bit) value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>An unsigned long (64-bit) value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> ulong
|
||||
/// # ulong
|
||||
/// out = 0
|
||||
/// >>> ulong 0
|
||||
/// # ulong(0)
|
||||
/// out = 0
|
||||
/// >>> ulong(1 << 64 - 1)
|
||||
/// # ulong(1 << 64 - 1)
|
||||
/// out = 18_446_744_073_709_551_615
|
||||
/// ```
|
||||
/// </example>
|
||||
/// <test>
|
||||
/// ```kalk
|
||||
/// >>> ulong 1 << 64
|
||||
/// Unable to convert type `bigint` to `ulong`
|
||||
/// ```
|
||||
/// </test>
|
||||
[KalkExport("ulong", CategoryTypeConstructors)]
|
||||
public ulong CreateULong(object value = null) => value == null ? 0UL : Engine.ToObject<ulong>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a signed-long (64-bit) value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>A signed-long (64-bit) value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> long
|
||||
/// # long
|
||||
/// out = 0
|
||||
/// >>> long 0
|
||||
/// # long(0)
|
||||
/// out = 0
|
||||
/// >>> long(1 << 63 - 1)
|
||||
/// # long(1 << 63 - 1)
|
||||
/// out = 9_223_372_036_854_775_807
|
||||
/// >>> long(-(1<<63))
|
||||
/// # long(-(1 << 63))
|
||||
/// out = -9_223_372_036_854_775_808
|
||||
/// ```
|
||||
/// </example>
|
||||
/// <test>
|
||||
/// ```kalk
|
||||
/// >>> long 1 << 63
|
||||
/// Unable to convert type `bigint` to `long`
|
||||
/// ```
|
||||
/// </test>
|
||||
[KalkExport("long", CategoryTypeConstructors)]
|
||||
public long CreateLong(object value = null) => value == null ? 0L : Engine.ToObject<long>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a boolean value (32-bit) value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>A boolean (32-bit) value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> bool 1
|
||||
/// # bool(1)
|
||||
/// out = true
|
||||
/// >>> bool 0
|
||||
/// # bool(0)
|
||||
/// out = false
|
||||
/// >>> bool true
|
||||
/// # bool(true)
|
||||
/// out = true
|
||||
/// >>> bool false
|
||||
/// # bool(false)
|
||||
/// out = false
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("bool", CategoryTypeConstructors)]
|
||||
public KalkBool CreateBool(object value = null) => value != null && Engine.ToObject<KalkBool>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a float value (32-bit) value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>A float (32-bit) value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> float(1)
|
||||
/// # float(1)
|
||||
/// out = 1
|
||||
/// >>> float(-1)
|
||||
/// # float(-1)
|
||||
/// out = -1
|
||||
/// >>> float(100000000000)
|
||||
/// # float(100000000000)
|
||||
/// out = 1E+11
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("float", CategoryTypeConstructors)]
|
||||
public float CreateFloat(object value = null) => value == null ? 0.0f : Engine.ToObject<float>(0, value);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a half float value (16-bit) value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>A half float (16-bit) value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> half(1)
|
||||
/// # half(1)
|
||||
/// out = 1
|
||||
/// >>> half(-1)
|
||||
/// # half(-1)
|
||||
/// out = -1
|
||||
/// >>> half(1000.5)
|
||||
/// # half(1000.5)
|
||||
/// out = 1000.5
|
||||
/// >>> kind out
|
||||
/// # kind(out)
|
||||
/// out = "half"
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("half", CategoryTypeConstructors)]
|
||||
public KalkHalf CreateHalf(object value = null) => value == null ? (KalkHalf)0.0f : Engine.ToObject<KalkHalf>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a double value (64-bit) value.
|
||||
/// </summary>
|
||||
/// <param name="value">The input value.</param>
|
||||
/// <returns>A double (64-bit) value</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> double(1)
|
||||
/// # double(1)
|
||||
/// out = 1
|
||||
/// >>> double(-1)
|
||||
/// # double(-1)
|
||||
/// out = -1
|
||||
/// >>> double(100000000000)
|
||||
/// # double(100000000000)
|
||||
/// out = 100000000000
|
||||
/// >>> double(1<<200)
|
||||
/// # double(1 << 200)
|
||||
/// out = 1.6069380442589903E+60
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("double", CategoryTypeConstructors)]
|
||||
public double CreateDouble(object value = null) => value == null ? 0.0 : Engine.ToObject<double>(0, value);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a vector of the specified element type, with the number of elements and optional values.
|
||||
/// </summary>
|
||||
/// <param name="name">The element type of the vector (e.g float).</param>
|
||||
/// <param name="dimension">The dimension of the vector.</param>
|
||||
/// <param name="arguments">The optional values (must have 1 or dimension elements).</param>
|
||||
/// <returns>A matrix of the specified row x column.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> vector(float, 4, 5..8)
|
||||
/// # vector(float, 4, 5..8)
|
||||
/// out = float4(5, 6, 7, 8)
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("vector", CategoryVectorTypeConstructors)]
|
||||
public object CreateVector(ScriptVariable name, int dimension, params object[] arguments)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
if (dimension <= 1) throw new ArgumentOutOfRangeException(nameof(dimension), "Invalid dimension. Expecting a value > 1.");
|
||||
switch (name.Name)
|
||||
{
|
||||
case "int":
|
||||
switch (dimension)
|
||||
{
|
||||
case 2: return CreateInt2(arguments);
|
||||
case 3: return CreateInt3(arguments);
|
||||
case 4: return CreateInt4(arguments);
|
||||
case 8: return CreateInt8(arguments);
|
||||
case 16: return CreateInt16(arguments);
|
||||
}
|
||||
return new KalkVectorConstructor<int>(dimension).Invoke(Engine, arguments);
|
||||
case "bool":
|
||||
switch (dimension)
|
||||
{
|
||||
case 2: return CreateBool2(arguments);
|
||||
case 3: return CreateBool3(arguments);
|
||||
case 4: return CreateBool4(arguments);
|
||||
case 8: return CreateBool8(arguments);
|
||||
case 16: return CreateBool16(arguments);
|
||||
}
|
||||
return new KalkVectorConstructor<KalkBool>(dimension).Invoke(Engine, arguments);
|
||||
|
||||
case "float":
|
||||
switch (dimension)
|
||||
{
|
||||
case 2: return CreateFloat2(arguments);
|
||||
case 3: return CreateFloat3(arguments);
|
||||
case 4: return CreateFloat4(arguments);
|
||||
case 8: return CreateFloat8(arguments);
|
||||
case 16: return CreateFloat16(arguments);
|
||||
}
|
||||
return new KalkVectorConstructor<float>(dimension).Invoke(Engine, arguments);
|
||||
|
||||
case "half":
|
||||
switch (dimension)
|
||||
{
|
||||
case 2: return CreateHalf2(arguments);
|
||||
case 3: return CreateHalf3(arguments);
|
||||
case 4: return CreateHalf4(arguments);
|
||||
case 8: return CreateHalf8(arguments);
|
||||
case 16: return CreateHalf16(arguments);
|
||||
case 32: return CreateHalf32(arguments);
|
||||
}
|
||||
return new KalkVectorConstructor<KalkHalf>(dimension).Invoke(Engine, arguments);
|
||||
|
||||
case "double":
|
||||
switch (dimension)
|
||||
{
|
||||
case 2: return CreateDouble2(arguments);
|
||||
case 3: return CreateDouble3(arguments);
|
||||
case 4: return CreateDouble4(arguments);
|
||||
case 8: return CreateDouble8(arguments);
|
||||
}
|
||||
return new KalkVectorConstructor<double>(dimension).Invoke(Engine, arguments);
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Unsupported vector type {name.Name}. Only bool, int, float and double are supported", nameof(name));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates an rgb vector type with the specified argument values.
|
||||
/// </summary>
|
||||
/// <param name="arguments">The vector item values. The total number of values must equal the dimension of the vector (3). The arguments can be:
|
||||
/// - No values: All items of the rgb vector are initialized with the value 0.
|
||||
/// - an integer value: `rgb(0xAABBCC)` will extract the RGB 8-bits component values (AA: R, BB: G, CC: B).
|
||||
/// - a string value: `rgb("#AABBCC")` or `rgb("AABBCC")` will extract the RGB 8-bits component values (AA: R, BB: G, CC: B).
|
||||
/// - an array value: `rgb([0xAA,0xBB,0xCC])` will initialize rgb elements with the array elements. The size of the array must match the size of the rgb vector (3).
|
||||
/// - A combination of vectors/single values (e.g `rgb(float3(0.1, 0.2, 0.3)`).
|
||||
/// </param>
|
||||
/// <returns>A rgb vector initialized with the specified arguments</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> rgb(0xAABBCC)
|
||||
/// # rgb(11189196)
|
||||
/// out = rgb(170, 187, 204) ## AABBCC ##
|
||||
/// >>> rgb("#AABBCC")
|
||||
/// # rgb("#AABBCC")
|
||||
/// out = rgb(170, 187, 204) ## AABBCC ##
|
||||
/// >>> rgb("AABBCC")
|
||||
/// # rgb("AABBCC")
|
||||
/// out = rgb(170, 187, 204) ## AABBCC ##
|
||||
/// >>> rgb([0xAA,0xBB,0xCC])
|
||||
/// # rgb([170,187,204])
|
||||
/// out = rgb(170, 187, 204) ## AABBCC ##
|
||||
/// >>> out.xyz
|
||||
/// # out.xyz
|
||||
/// out = float3(0.6666667, 0.73333335, 0.8)
|
||||
/// >>> rgb(out)
|
||||
/// # rgb(out)
|
||||
/// out = rgb(170, 187, 204) ## AABBCC ##
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("rgb", CategoryVectorTypeConstructors)]
|
||||
public KalkColorRgb CreateRgb(params object[] arguments) => (KalkColorRgb)RgbConstructor.Invoke(Engine, arguments);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an rgba vector type with the specified argument values.
|
||||
/// </summary>
|
||||
/// <param name="arguments">The vector item values. The total number of values must equal the dimension of the vector (4). The arguments can be:
|
||||
/// - No values: All items of the rgba vector are initialized with the value 0.
|
||||
/// - an integer value: `rgba(0xFFAABBCC)` will extract the RGB 8-bits component values (FF: A, AA: R, BB: G, CC: B).
|
||||
/// - a string value: `rgba("#FFAABBCC")` or `rgba("FFAABBCC")` will extract the RGB 8-bits component values (FF: A, AA: R, BB: G, CC: B).
|
||||
/// - an array value: `rgba([0xAA,0xBB,0xCC,0xFF])` will initialize rgba elements with the array elements. The size of the array must match the size of the rgb vector (3).
|
||||
/// - A combination of vectors/single values (e.g `rgba(float4(0.1, 0.2, 0.3, 1.0)`).
|
||||
/// </param>
|
||||
/// <returns>A rgb vector initialized with the specified arguments</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> rgba(0xFFAABBCC)
|
||||
/// # rgba(-5588020)
|
||||
/// out = rgba(170, 187, 204, 255) ## AABBCCFF ##
|
||||
/// >>> rgba("#FFAABBCC")
|
||||
/// # rgba("#FFAABBCC")
|
||||
/// out = rgba(170, 187, 204, 255) ## AABBCCFF ##
|
||||
/// >>> rgba("FFAABBCC")
|
||||
/// # rgba("FFAABBCC")
|
||||
/// out = rgba(170, 187, 204, 255) ## AABBCCFF ##
|
||||
/// >>> rgba([0xAA,0xBB,0xCC,0xFF])
|
||||
/// # rgba([170,187,204,255])
|
||||
/// out = rgba(170, 187, 204, 255) ## AABBCCFF ##
|
||||
/// >>> out.xyzw
|
||||
/// # out.xyzw
|
||||
/// out = float4(0.6666667, 0.73333335, 0.8, 1)
|
||||
/// >>> rgba(out)
|
||||
/// # rgba(out)
|
||||
/// out = rgba(170, 187, 204, 255) ## AABBCCFF ##
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("rgba", CategoryVectorTypeConstructors)]
|
||||
public KalkColorRgba CreateRgba(params object[] arguments) => (KalkColorRgba)RgbaConstructor.Invoke(Engine, arguments);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a matrix of the specified element type, number of rows and columns and optional values.
|
||||
/// </summary>
|
||||
/// <param name="name">The element type of the matrix (e.g float).</param>
|
||||
/// <param name="row">The number of rows.</param>
|
||||
/// <param name="column">The number of columns.</param>
|
||||
/// <param name="arguments">The optional values (must have 1 or row x column elements).</param>
|
||||
/// <returns>A matrix of the specified row x column.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> matrix(float,4,3,1..12)
|
||||
/// # matrix(float, 4, 3, 1..12)
|
||||
/// out = float4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
|
||||
/// # col 0 1 2 / row
|
||||
/// float3(1 , 2 , 3 ) # 0
|
||||
/// float3(4 , 5 , 6 ) # 1
|
||||
/// float3(7 , 8 , 9 ) # 2
|
||||
/// float3(10 , 11 , 12 ) # 3
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("matrix", CategoryMatrixConstructors)]
|
||||
public object CreateMatrix(ScriptVariable name, int row, int column, params object[] arguments)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
if (row <= 1) throw new ArgumentOutOfRangeException(nameof(row), $"Invalid row count {row}. Expecting a value > 1.");
|
||||
if (column <= 1) throw new ArgumentOutOfRangeException(nameof(column), $"Invalid column count {column}. Expecting a value > 1.");
|
||||
switch (name.Name)
|
||||
{
|
||||
case "int":
|
||||
return new KalkMatrixConstructor<int>(row, column).Invoke(Engine, arguments);
|
||||
case "bool":
|
||||
return new KalkMatrixConstructor<KalkBool>(row, column).Invoke(Engine, arguments);
|
||||
case "float":
|
||||
return new KalkMatrixConstructor<float>(row, column).Invoke(Engine, arguments);
|
||||
case "half":
|
||||
return new KalkMatrixConstructor<KalkHalf>(row, column).Invoke(Engine, arguments);
|
||||
case "double":
|
||||
return new KalkMatrixConstructor<double>(row, column).Invoke(Engine, arguments);
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Unsupported matrix type {name.Name}. Only bool, int, float, half and double are supported", nameof(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
1819
Kalk/Kalk.Core/Modules/Vectors/TypesModule.generated.cs
Normal file
1819
Kalk/Kalk.Core/Modules/Vectors/TypesModule.generated.cs
Normal file
File diff suppressed because it is too large
Load Diff
131
Kalk/Kalk.Core/Modules/Vectors/TypesModule.tt
Normal file
131
Kalk/Kalk.Core/Modules/Vectors/TypesModule.tt
Normal file
@@ -0,0 +1,131 @@
|
||||
<#@ template debug="false" hostspecific="false" language="C#" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
<#@ import namespace="System.Text" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
<#@ output extension=".generated.cs" #>
|
||||
<#
|
||||
var types = new List<(string, string, int, int, string)>();
|
||||
|
||||
foreach(var typeU in new string[] { "Bool", "Int", "Float", "Double", "Half" })
|
||||
{
|
||||
var type = typeU.ToLowerInvariant();
|
||||
for(int y = 2; y <= 4; y++) {
|
||||
for(int x = 2; x <= 4; x++) {
|
||||
var genericType = typeU == "Bool" ? "KalkBool" : typeU == "Half" ? "KalkHalf" : type;
|
||||
types.Add((type, $"{typeU}{y}x{x}", y, x, genericType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var vectypes = new List<(string, string, string, int[])>() {
|
||||
("byte", "Byte", "byte", new int[] {16,32,64}),
|
||||
("sbyte", "SByte", "sbyte", new int[] {16,32,64}),
|
||||
("short", "Short", "short", new int[] {2,4,8,16,32}),
|
||||
("ushort", "UShort", "ushort", new int[] {2,4,8,16,32}),
|
||||
("int", "Int", "int", new int[] {2,3,4,8,16}),
|
||||
("uint", "UInt", "uint", new int[] {2,3,4,8,16}),
|
||||
("long", "Long", "long", new int[] {2,3,4,8}),
|
||||
("ulong", "ULong", "ulong", new int[] {2,3,4,8}),
|
||||
("KalkBool", "Bool", "bool", new int[] {2,3,4,8,16}),
|
||||
("float", "Float", "float", new int[] {2,3,4,8,16}),
|
||||
("double", "Double", "double", new int[] {2,3,4,8}),
|
||||
("KalkHalf", "Half", "half", new int[] {2,3,4,8,16,32}),
|
||||
};
|
||||
#>
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Date: <#= DateTime.Now #>
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using Scriban.Helpers;
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core.Modules
|
||||
{
|
||||
public partial class TypesModule
|
||||
{
|
||||
private const string CategoryMatrixConstructors = "Type Matrix Constructors";
|
||||
|
||||
<# foreach(var type in vectypes) { #>
|
||||
<# foreach(var dim in type.Item4) { #>
|
||||
private static readonly KalkVectorConstructor<<#= type.Item1 #>> <#= type.Item2 #><#= dim #>Constructor = new KalkVectorConstructor<<#= type.Item1 #>>(<#= dim #>);
|
||||
<# } #>
|
||||
<# } #>
|
||||
|
||||
<# foreach(var type in types) { #>
|
||||
private static readonly KalkMatrixConstructor<<#= type.Item5 #>> <#= type.Item2 #>Constructor = new KalkMatrixConstructor<<#= type.Item5 #>>(<#= type.Item3 #>, <#= type.Item4 #>);
|
||||
<# } #>
|
||||
|
||||
<# foreach(var type in vectypes) { #>
|
||||
<# foreach(var dim in type.Item4) {
|
||||
var ctor = $"{type.Item3}{dim}";
|
||||
if (type.Item3 == "bool") { #>
|
||||
/// <summary>Creates a vector of <#= dim #> `<#= type.Item3 #>` items.</summary>
|
||||
/// <param name="arguments">The vector item values. The total number of values must equal the dimension of the vector. The arguments can be:
|
||||
/// - No values: The vector is initialized with false values.
|
||||
/// - a single value: `<#= ctor #>(true)` will initialize all elements with 123.
|
||||
/// - an array value: `<#= ctor #>([true, false, ...])` will initialize all elements with the array elements. The size of the array must match the size of the vector.
|
||||
/// - A combination of vectors/single values (e.g `<#= type.Item3 #>4(<#= type.Item3 #>2(true,false), <#= type.Item3 #>2(false,true))` or `<#= type.Item3 #>4(<#= type.Item3 #>3(false,true,true), false)`)
|
||||
/// </param>
|
||||
/// <returns>A <#= ctor #> vector initialized with the specified arguments</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> <#= ctor #>(true)
|
||||
/// # <#= ctor #>(true)
|
||||
/// out = <#= ctor #>(<#= string.Join(", ", Enumerable.Range(1, dim).Select(x => "true")) #>)
|
||||
<# } else { #>
|
||||
/// <summary>Creates a vector of <#= dim #> `<#= type.Item3 #>` items.</summary>
|
||||
/// <param name="arguments">The vector item values. The total number of values must equal the dimension of the vector. The arguments can be:
|
||||
/// - No values: All items of the vector are initialized with the value 0.
|
||||
/// - a single value: `<#= ctor #>(123)` will initialize all elements with 123.
|
||||
/// - an array value: `<#= ctor #>(1..<#= dim #>)` will initialize all elements with the array elements. The size of the array must match the size of the vector.
|
||||
/// - A combination of vectors/single values (e.g `<#= type.Item3 #>4(<#= type.Item3 #>2(1,2), <#= type.Item3 #>2(3,4))` or `<#= type.Item3 #>4(<#= type.Item3 #>3(1,2,3), 4)`.
|
||||
/// </param>
|
||||
/// <returns>A <#= ctor #> vector initialized with the specified arguments</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> <#= ctor #>
|
||||
/// # <#= ctor #>
|
||||
/// out = <#= ctor #>(<#= string.Join(", ", Enumerable.Range(1, dim).Select(x => "0")) #>)
|
||||
/// >>> <#= ctor #>(1..<#= dim #>)
|
||||
/// # <#= ctor #>(1..<#= dim #>)
|
||||
/// out = <#= ctor #>(<#= string.Join(", ", Enumerable.Range(1, dim)) #>)
|
||||
<# if (dim <= 16) { #>
|
||||
/// >>> <#= ctor #>(<#= string.Join(", ", Enumerable.Range(10, dim)) #>)
|
||||
/// # <#= ctor #>(<#= string.Join(", ", Enumerable.Range(10, dim)) #>)
|
||||
/// out = <#= ctor #>(<#= string.Join(", ", Enumerable.Range(10, dim)) #>)
|
||||
<# }
|
||||
}
|
||||
#>
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("<#= ctor #>", CategoryVectorTypeConstructors)]
|
||||
public KalkVector<<#= type.Item1 #>> Create<#= type.Item2 #><#= dim #>(params object[] arguments) => <#= type.Item2 #><#= dim #>Constructor.Invoke(Engine, arguments);
|
||||
<# }
|
||||
} #>
|
||||
|
||||
|
||||
<# foreach(var type in types) {
|
||||
var dim = type.Item3 * type.Item4;
|
||||
var ctor_prefix = type.Item1.ToLowerInvariant();
|
||||
var ctor = type.Item2.ToLowerInvariant();
|
||||
#>
|
||||
/// <summary>Creates a <#= type.Item3 #> (rows) x <#= type.Item4 #> (columns) matrix of <#= type.Item1 #>.</summary>
|
||||
/// <param name="arguments">The matrix item values. The total number of values must equal the total dimension of the matrix. The arguments can be:
|
||||
/// - No values: All items of the vector are initialized with the value 0.
|
||||
/// - a single value: `<#= ctor #>(123)` will initialize all elements with 123.
|
||||
/// - an array value: `<#= ctor #>(1..<#= dim #>)` will initialize all elements with the array elements. The size of the array must match the size of the vector.
|
||||
/// - A combination of vectors/single values (e.g `<#= ctor_prefix #>3x4(<#= ctor_prefix #>4(1), <#= ctor_prefix #>4(2), <#= ctor_prefix #>4(3))`.
|
||||
/// </param>
|
||||
/// <returns>A <#= ctor #> matrix initialized with the specified arguments</returns>
|
||||
[KalkExport("<#= ctor #>", CategoryMatrixConstructors)]
|
||||
public KalkMatrix<<#= type.Item5 #>> Create<#= type.Item2 #>(params object[] arguments) => <#= type.Item2 #>Constructor.Invoke(Engine, arguments);
|
||||
<# } #>
|
||||
}
|
||||
}
|
||||
228
Kalk/Kalk.Core/Modules/Vectors/VectorModule.Matrics.cs
Normal file
228
Kalk/Kalk.Core/Modules/Vectors/VectorModule.Matrics.cs
Normal file
@@ -0,0 +1,228 @@
|
||||
using System;
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core.Modules
|
||||
{
|
||||
public partial class VectorModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Transposes the specified matrix.
|
||||
/// </summary>
|
||||
/// <param name="m">The matrix to transpose.</param>
|
||||
/// <returns>The transposed matrix.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> transpose float3x4(1..12)
|
||||
/// # transpose(float3x4(1..12))
|
||||
/// out = float4x3(1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12)
|
||||
/// # col 0 1 2 / row
|
||||
/// float3(1 , 5 , 9 ) # 0
|
||||
/// float3(2 , 6 , 10 ) # 1
|
||||
/// float3(3 , 7 , 11 ) # 2
|
||||
/// float3(4 , 8 , 12 ) # 3
|
||||
/// >>> transpose(out)
|
||||
/// # transpose(out)
|
||||
/// out = float3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
|
||||
/// # col 0 1 2 3 / row
|
||||
/// float4(1 , 2 , 3 , 4 ) # 0
|
||||
/// float4(5 , 6 , 7 , 8 ) # 1
|
||||
/// float4(9 , 10 , 11 , 12 ) # 2
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("transpose", CategoryMathVectorMatrixFunctions)]
|
||||
public static KalkMatrix Transpose(KalkMatrix m) => KalkMatrix.Transpose(m);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an identity of a squared matrix.
|
||||
/// </summary>
|
||||
/// <param name="m">The type of the squared matrix.</param>
|
||||
/// <returns>The identity matrix of the squared matrix type.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> identity(float4x4)
|
||||
/// # identity(float4x4)
|
||||
/// out = float4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
|
||||
/// # col 0 1 2 3 / row
|
||||
/// float4(1 , 0 , 0 , 0 ) # 0
|
||||
/// float4(0 , 1 , 0 , 0 ) # 1
|
||||
/// float4(0 , 0 , 1 , 0 ) # 2
|
||||
/// float4(0 , 0 , 0 , 1 ) # 3
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("identity", CategoryMathVectorMatrixFunctions)]
|
||||
public static KalkMatrix Identity(KalkMatrix m) => KalkMatrix.Identity(m);
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the determinant of the specified matrix.
|
||||
/// </summary>
|
||||
/// <param name="m">The matrix to calculate the determinant for.</param>
|
||||
/// <returns>A scalar representing the determinant of the matrix.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> float4x4(4,3,2,2,0,1,-3,3,0,-1,3,3,0,3,1,1)
|
||||
/// # float4x4(4, 3, 2, 2, 0, 1, -3, 3, 0, -1, 3, 3, 0, 3, 1, 1)
|
||||
/// out = float4x4(4, 3, 2, 2, 0, 1, -3, 3, 0, -1, 3, 3, 0, 3, 1, 1)
|
||||
/// # col 0 1 2 3 / row
|
||||
/// float4(4 , 3 , 2 , 2 ) # 0
|
||||
/// float4(0 , 1 , -3 , 3 ) # 1
|
||||
/// float4(0 , -1 , 3 , 3 ) # 2
|
||||
/// float4(0 , 3 , 1 , 1 ) # 3
|
||||
/// >>> determinant out
|
||||
/// # determinant(out)
|
||||
/// out = -240
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("determinant", CategoryMathVectorMatrixFunctions)]
|
||||
public static object Determinant(KalkMatrix m) => KalkMatrix.Determinant(m);
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the inverse of the specified matrix.
|
||||
/// </summary>
|
||||
/// <param name="m">The matrix to calculate the inverse for.</param>
|
||||
/// <returns>The inverse matrix of the specified matrix.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> inverse(float3x3(10,20,10,4,5,6,2,3,5))
|
||||
/// # inverse(float3x3(10, 20, 10, 4, 5, 6, 2, 3, 5))
|
||||
/// out = float3x3(-0.1, 1, -1, 0.11428571, -0.42857143, 0.28571427, -0.028571427, -0.14285715, 0.42857143)
|
||||
/// # col 0 1 2 / row
|
||||
/// float3(-0.1 , 1 , -1 ) # 0
|
||||
/// float3( 0.11428571 , -0.42857143, 0.28571427) # 1
|
||||
/// float3(-0.028571427, -0.14285715, 0.42857143) # 2
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("inverse", CategoryMathVectorMatrixFunctions)]
|
||||
public static KalkMatrix Inverse(KalkMatrix m) => KalkMatrix.Inverse(m);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the diagonal vector of a squared matrix or a diagonal matrix from the specified vector.
|
||||
/// </summary>
|
||||
/// <param name="x">A vector or matrix to return the associated diagonal for.</param>
|
||||
/// <returns>A diagonal vector of a matrix or a diagonal matrix of a vector.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> diag(float4x4(1..16))
|
||||
/// # diag(float4x4(1..16))
|
||||
/// out = float4(1, 6, 11, 16)
|
||||
/// >>> diag(float4(1,2,3,4))
|
||||
/// # diag(float4(1, 2, 3, 4))
|
||||
/// out = float4x4(1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4)
|
||||
/// # col 0 1 2 3 / row
|
||||
/// float4(1 , 0 , 0 , 0 ) # 0
|
||||
/// float4(0 , 2 , 0 , 0 ) # 1
|
||||
/// float4(0 , 0 , 3 , 0 ) # 2
|
||||
/// float4(0 , 0 , 0 , 4 ) # 3
|
||||
///
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("diag", CategoryMathVectorMatrixFunctions)]
|
||||
public object Diagonal(object x)
|
||||
{
|
||||
if (x == null) throw new ArgumentNullException(nameof(x));
|
||||
|
||||
if (x is KalkMatrix m)
|
||||
{
|
||||
return KalkMatrix.Diagonal(m);
|
||||
}
|
||||
|
||||
if (x is KalkVector v)
|
||||
{
|
||||
return KalkVector.Diagonal(v);
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid argument type {Engine.GetTypeName(x)}. Expecting a matrix or a vector type.", nameof(x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract a row from the specified matrix.
|
||||
/// </summary>
|
||||
/// <param name="x">The matrix to extract a row from.</param>
|
||||
/// <param name="index">The index of the row (zero based).</param>
|
||||
/// <returns>A vector extracted from the matrix.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> row(float4x4(1..16), 2)
|
||||
/// # row(float4x4(1..16), 2)
|
||||
/// out = float4(9, 10, 11, 12)
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("row", CategoryMathVectorMatrixFunctions)]
|
||||
public KalkVector GetRow(KalkMatrix x, int index)
|
||||
{
|
||||
return x.GetRow(index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract a column from the specified matrix.
|
||||
/// </summary>
|
||||
/// <param name="x">The matrix to extract a column from.</param>
|
||||
/// <param name="index">The index of the column (zero based).</param>
|
||||
/// <returns>A vector extracted from the matrix.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> col(float4x4(1..16), 2)
|
||||
/// # col(float4x4(1..16), 2)
|
||||
/// out = float4(3, 7, 11, 15)
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("col", CategoryMathVectorMatrixFunctions)]
|
||||
public KalkVector GetColumn(KalkMatrix x, int index)
|
||||
{
|
||||
return x.GetColumn(index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies a vector x vector (dot product), or a vector x matrix, or a matrix x vector or a matrix x matrix.
|
||||
/// </summary>
|
||||
/// <param name="x">A left vector or a matrix.</param>
|
||||
/// <param name="y">A right vector or matrix.</param>
|
||||
/// <returns>The result of the multiplication.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> mul(float4(1,2,3,4), float4(5,6,7,8))
|
||||
/// # mul(float4(1, 2, 3, 4), float4(5, 6, 7, 8))
|
||||
/// out = 70
|
||||
/// >>> mul(float3(3,7,5), float3x3(2,3,-4,11,8,7,2,5,3))
|
||||
/// # mul(float3(3, 7, 5), float3x3(2, 3, -4, 11, 8, 7, 2, 5, 3))
|
||||
/// out = float3(7, 124, 56)
|
||||
/// >>> mul(float3x3(2,3,-4,11,8,7,2,5,3), float3(3,7,5))
|
||||
/// # mul(float3x3(2, 3, -4, 11, 8, 7, 2, 5, 3), float3(3, 7, 5))
|
||||
/// out = float3(93, 90, 52)
|
||||
/// >>> mul(float3x3(2,7,4,3,2,1,9,-1,2), float3x3(1,4,6,-1,-2,5,8,7,6))
|
||||
/// # mul(float3x3(2, 7, 4, 3, 2, 1, 9, -1, 2), float3x3(1, 4, 6, -1, -2, 5, 8, 7, 6))
|
||||
/// out = float3x3(68, 9, 20, 37, -16, 4, 91, 64, 51)
|
||||
/// # col 0 1 2 / row
|
||||
/// float3(68 , 9 , 20 ) # 0
|
||||
/// float3(37 , -16 , 4 ) # 1
|
||||
/// float3(91 , 64 , 51 ) # 2
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("mul", CategoryMathVectorMatrixFunctions)]
|
||||
public object Multiply(object x, object y)
|
||||
{
|
||||
if (x == null) throw new ArgumentNullException(nameof(x));
|
||||
if (y == null) throw new ArgumentNullException(nameof(y));
|
||||
|
||||
if (x is KalkVector vx && y is KalkVector vy)
|
||||
{
|
||||
return KalkVector.Dot(vx, vy);
|
||||
}
|
||||
|
||||
if (x is KalkVector vx1 && y is KalkMatrix my)
|
||||
{
|
||||
return KalkMatrix.Multiply(vx1, my);
|
||||
}
|
||||
if (x is KalkMatrix mx && y is KalkVector vy1)
|
||||
{
|
||||
return KalkMatrix.Multiply(mx, vy1);
|
||||
}
|
||||
|
||||
if (x is KalkMatrix mx1 && y is KalkMatrix my2)
|
||||
{
|
||||
return KalkMatrix.Multiply(mx1, my2);
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Unsupported type for matrix multiplication. The combination of {Engine.GetTypeName(x)} * {Engine.GetTypeName(y)} is not supported.", nameof(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
140
Kalk/Kalk.Core/Modules/Vectors/VectorModule.cs
Normal file
140
Kalk/Kalk.Core/Modules/Vectors/VectorModule.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using Scriban.Syntax;
|
||||
|
||||
namespace Kalk.Core.Modules
|
||||
{
|
||||
public sealed partial class VectorModule : KalkModuleWithFunctions
|
||||
{
|
||||
public const string CategoryMathVectorMatrixFunctions = "Math Vector/Matrix Functions";
|
||||
private static readonly KalkColorRgbConstructor RgbConstructor = new KalkColorRgbConstructor();
|
||||
private static readonly KalkColorRgbaConstructor RgbaConstructor = new KalkColorRgbaConstructor();
|
||||
private MathModule _mathModule;
|
||||
|
||||
public VectorModule() : base("Vectors")
|
||||
{
|
||||
IsBuiltin = true;
|
||||
RegisterFunctionsAuto();
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
_mathModule = Engine.GetOrCreateModule<MathModule>();
|
||||
//Engine.LoadSystemFile(Path.Combine("Modules", "Vectors", "colorspaces.kalk"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length of the specified floating-point vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The specified floating-point vector.</param>
|
||||
/// <returns>A floating-point scalar that represents the length of the x parameter.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> length float2(1, 2)
|
||||
/// # length(float2(1, 2))
|
||||
/// out = 2.23606797749979
|
||||
/// >>> length(-5)
|
||||
/// # length(-5)
|
||||
/// out = 5
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("length", CategoryMathVectorMatrixFunctions)]
|
||||
public object Length(object x)
|
||||
{
|
||||
if (x == null) throw new ArgumentNullException(nameof(x));
|
||||
if (_mathModule == null) throw new InvalidOperationException($"The module {Name} is not initialized.");
|
||||
if (x is KalkVector v)
|
||||
{
|
||||
return _mathModule.Sqrt(new KalkDoubleValue(KalkVector.Dot(v, v)));
|
||||
}
|
||||
return _mathModule.Abs(new KalkCompositeValue(x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes the specified floating-point vector according to x / length(x).
|
||||
/// </summary>
|
||||
/// <param name="x">he specified floating-point vector.</param>
|
||||
/// <returns>The normalized x parameter. If the length of the x parameter is 0, the result is indefinite.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> normalize float2(1,2)
|
||||
/// # normalize(float2(1, 2))
|
||||
/// out = float2(0.4472136, 0.8944272)
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("normalize", CategoryMathVectorMatrixFunctions)]
|
||||
public object Normalize(object x)
|
||||
{
|
||||
return ScriptBinaryExpression.Evaluate(Engine, Engine.CurrentSpan, ScriptBinaryOperator.Divide, x, Length(x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dot product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="x">The first vector.</param>
|
||||
/// <param name="y">The second vector.</param>
|
||||
/// <returns>The dot product of the x parameter and the y parameter.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> dot(float3(1,2,3), float3(4,5,6))
|
||||
/// # dot(float3(1, 2, 3), float3(4, 5, 6))
|
||||
/// out = 32
|
||||
/// >>> dot(float3(1,2,3), 4)
|
||||
/// # dot(float3(1, 2, 3), 4)
|
||||
/// out = 24
|
||||
/// >>> dot(4, float3(1,2,3))
|
||||
/// # dot(4, float3(1, 2, 3))
|
||||
/// out = 24
|
||||
/// >>> dot(5,6)
|
||||
/// # dot(5, 6)
|
||||
/// out = 30
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("dot", CategoryMathVectorMatrixFunctions)]
|
||||
public object Dot(object x, object y)
|
||||
{
|
||||
if (x is KalkVector vx)
|
||||
{
|
||||
if (y is KalkVector vy)
|
||||
{
|
||||
return KalkVector.Dot(vx, vy);
|
||||
}
|
||||
return KalkVector.Dot(vx, vx.FromValue(Engine.ToObject(1, y, vx.ElementType)));
|
||||
}
|
||||
else if (y is KalkVector vy)
|
||||
{
|
||||
return KalkVector.Dot(vy.FromValue(Engine.ToObject(1, x, vy.ElementType)), vy);
|
||||
}
|
||||
|
||||
return ScriptBinaryExpression.Evaluate(Engine, Engine.CurrentSpan, ScriptBinaryOperator.Multiply, x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cross product of two floating-point, 3D vectors.
|
||||
/// </summary>
|
||||
/// <param name="x">The first floating-point, 3D vector.</param>
|
||||
/// <param name="y">The second floating-point, 3D vector.</param>
|
||||
/// <returns>The cross product of the x parameter and the y parameter.</returns>
|
||||
/// <example>
|
||||
/// ```kalk
|
||||
/// >>> cross(float3(1,2,3), float3(4,5,6))
|
||||
/// # cross(float3(1, 2, 3), float3(4, 5, 6))
|
||||
/// out = float3(-3, 6, -3)
|
||||
/// >>> cross(float3(1,0,0), float3(0,1,0))
|
||||
/// # cross(float3(1, 0, 0), float3(0, 1, 0))
|
||||
/// out = float3(0, 0, 1)
|
||||
/// >>> cross(float3(0,0,1), float3(0,1,0))
|
||||
/// # cross(float3(0, 0, 1), float3(0, 1, 0))
|
||||
/// out = float3(-1, 0, 0)
|
||||
/// ```
|
||||
/// </example>
|
||||
[KalkExport("cross", CategoryMathVectorMatrixFunctions)]
|
||||
public object Cross(KalkVector x, KalkVector y)
|
||||
{
|
||||
if (x == null) throw new ArgumentNullException(nameof(x));
|
||||
if (y == null) throw new ArgumentNullException(nameof(y));
|
||||
if (x.Length != 3 || (x.ElementType != typeof(float) && x.ElementType != typeof(double))) throw new ArgumentOutOfRangeException(nameof(x), "Expecting a float3 or double3 vector.");
|
||||
if (y.Length != 3 || (y.ElementType != typeof(float) && y.ElementType != typeof(double))) throw new ArgumentOutOfRangeException(nameof(y), "Expecting a float3 or double3 vector.");
|
||||
return KalkVector.Cross(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
153
Kalk/Kalk.Core/Modules/Vectors/colorspaces.kalk
Normal file
153
Kalk/Kalk.Core/Modules/Vectors/colorspaces.kalk
Normal file
@@ -0,0 +1,153 @@
|
||||
# From http://www.chilliant.com/rgb2hsv.html
|
||||
|
||||
# Based on work by Sam Hocevar and Emil Persson
|
||||
func HUEtoRGB(x)
|
||||
$r = abs(x * 6 - 3) - 1;
|
||||
$g = 2 - abs(x * 6 - 2);
|
||||
$b = 2 - abs(x * 6 - 4);
|
||||
ret saturate(float3($r, $g, $b));
|
||||
end
|
||||
|
||||
func RGBtoHCV(x)
|
||||
x = x.xyz;
|
||||
Epsilon = 1e-10f
|
||||
if x.g < x.b; $p =float4(x.bg, -1.0f, 2.0f/3.0f); else; $p = float4(x.gb, 0.0f, -1.0f/3.0f); end;
|
||||
if x.r < $p.x; $q = float4($p.xyw, x.r); else; $q = float4(x.r, $p.yzx); end;
|
||||
$c = $q.x - min($q.w, $q.y);
|
||||
$h = abs(($q.w - $q.y) / (6.0f * $c + Epsilon) + $q.z);
|
||||
ret float3($h, $c, $q.x);
|
||||
end
|
||||
|
||||
func HSVtoRGB(x)
|
||||
x = x.xyz;
|
||||
$rgb = HUEtoRGB(x.x);
|
||||
ret (($rgb - 1) * x.y + 1) * x.z;
|
||||
end
|
||||
|
||||
func HSLtoRGB(x)
|
||||
x = x.xyz;
|
||||
$rgb = HUEtoRGB(x.x);
|
||||
$c = (1 - abs(2 * x.z - 1)) * x.y;
|
||||
ret ($rgb - 0.5) * $c + x.z;
|
||||
end
|
||||
|
||||
func HCYtoRGB(x)
|
||||
x = x.xyz;
|
||||
# The weights of RGB contributions to luminance.
|
||||
# Should sum to unity.
|
||||
$HCYwts = float3(0.299f, 0.587f, 0.114f);
|
||||
$rgb = HUEtoRGB(x.x);
|
||||
$z = dot($rgb, $HCYwts);
|
||||
if x.z < $z
|
||||
x.y = x.y * x.z / $z;
|
||||
else if $z < 1
|
||||
x.y = x.y * (1 - x.z) / (1 - $z);
|
||||
end
|
||||
ret ($rgb - $z) * x.y + x.z;
|
||||
end
|
||||
|
||||
func HCLtoRGB(x)
|
||||
x = x.xyz;
|
||||
HCLgamma = 3;
|
||||
HCLy0 = 100;
|
||||
HCLmaxL = 0.530454533953517; # == exp(HCLgamma / HCLy0) - 0.5
|
||||
$rgb = float3;
|
||||
if x.z != 0
|
||||
H = x.x;
|
||||
C = x.y;
|
||||
L = x.z * HCLmaxL;
|
||||
Q = exp((1 - C / (2 * L)) * (HCLgamma / HCLy0));
|
||||
U = (2 * L - C) / (2 * Q - 1);
|
||||
V = C / Q;
|
||||
A = (H + min(frac(2 * H) / 4, frac(-2 * H) / 8)) * pi * 2;
|
||||
H = H * 6;
|
||||
if (H <= 0.999)
|
||||
T = tan(A);
|
||||
$rgb.r = 1;
|
||||
$rgb.g = T / (1 + T);
|
||||
else if (H <= 1.001)
|
||||
$rgb.r = 1;
|
||||
$rgb.g = 1;
|
||||
else if (H <= 2)
|
||||
T = tan(A);
|
||||
$rgb.r = (1 + T) / T;
|
||||
$rgb.g = 1;
|
||||
else if (H <= 3)
|
||||
T = tan(A);
|
||||
$rgb.g = 1;
|
||||
$rgb.b = 1 + T;
|
||||
else if (H <= 3.999)
|
||||
T = tan(A);
|
||||
$rgb.g = 1 / (1 + T);
|
||||
$rgb.b = 1;
|
||||
else if (H <= 4.001)
|
||||
$rgb.g = 0;
|
||||
$rgb.b = 1;
|
||||
else if (H <= 5)
|
||||
T = tan(A);
|
||||
$rgb.r = -1 / T;
|
||||
$rgb.b = 1;
|
||||
else
|
||||
T = tan(A);
|
||||
$rgb.r = 1;
|
||||
$rgb.b = -T;
|
||||
end
|
||||
$rgb = $rgb * V + U;
|
||||
end
|
||||
ret $rgb;
|
||||
end
|
||||
|
||||
func RGBtoHSV(x)
|
||||
x = x.xyz;
|
||||
Epsilon = 1e-10f
|
||||
$Hcv = RGBtoHCV(x);
|
||||
$s = $Hcv.y / ($Hcv.z + Epsilon);
|
||||
ret float3($Hcv.x, $s, $Hcv.z);
|
||||
end
|
||||
|
||||
func RGBtoHSL(x)
|
||||
x = x.xyz;
|
||||
Epsilon = 1e-10f
|
||||
$hcv = RGBtoHCV(x);
|
||||
$l = $hcv.z - $hcv.y * 0.5;
|
||||
$s = $hcv.y / (1 - abs($l * 2 - 1) + Epsilon);
|
||||
ret float3($hcv.x, $s, $l);
|
||||
end
|
||||
|
||||
func RGBtoHCY(x)
|
||||
x = x.xyz;
|
||||
# Corrected by David Schaeffer
|
||||
$HCYwts = float3(0.299f, 0.587f, 0.114f);
|
||||
Epsilon = 1e-10f
|
||||
$hcv = RGBtoHCV(x);
|
||||
$y = dot(x, $HCYwts);
|
||||
$z = dot(HUEtoRGB($hcv.x), $HCYwts);
|
||||
if ($y < $z)
|
||||
$hcv.y = $hcv.y * $z / (Epsilon + $y);
|
||||
else
|
||||
$hcv.y = $hcv.y * (1 - $z) / (Epsilon + 1 - $y);
|
||||
end
|
||||
ret float3($hcv.x, $hcv.y, $y);
|
||||
end
|
||||
|
||||
func RGBtoHCL(x)
|
||||
x = x.xyz;
|
||||
HCLgamma = 3;
|
||||
HCLy0 = 100;
|
||||
HCLmaxL = 0.530454533953517; # == exp(HCLgamma / HCLy0) - 0.5
|
||||
$hcl = float3
|
||||
H = 0;
|
||||
U = min(x.r, min(x.g, x.b));
|
||||
V = max(x.r, max(x.g, x.b));
|
||||
Q = HCLgamma / HCLy0;
|
||||
$hcl.y = V - U;
|
||||
if ($hcl.y != 0)
|
||||
H = atan2(x.g - x.b, x.r - x.g) / pi;
|
||||
Q = Q * U / V;
|
||||
end
|
||||
Q = exp(Q);
|
||||
$hcl.x = frac(H / 2 - min(frac(H), frac(-H)) / 6);
|
||||
$hcl.y = $hcl.y * Q;
|
||||
$hcl.z = lerp(-U, V, Q) / (HCLmaxL * 2);
|
||||
ret $hcl;
|
||||
end
|
||||
Reference in New Issue
Block a user