mt-lang 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/lsp/diagnostics.rb +1 -1
- data/lib/milk_tea/tooling/linter/imports_platform.rb +14 -13
- data/std/blackboard.mt +100 -0
- data/std/cmd.mt +132 -0
- data/std/color.mt +245 -0
- data/std/graph.mt +237 -0
- data/std/htn.mt +254 -0
- data/std/input.mt +132 -0
- data/std/noise.mt +201 -0
- data/std/pool.mt +82 -0
- data/std/signal.mt +66 -0
- data/std/steering.mt +132 -0
- data/std/timer.mt +81 -0
- data/std/tween.mt +374 -0
- data/std/utility.mt +208 -0
- metadata +14 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7cd20acdc903389647adc4c6c7e552fdbbf35694f69328b0427134109782b21f
|
|
4
|
+
data.tar.gz: 5cc1498f88f6ddb87eaa2d7a7da9f54c76a6ee9a38fe3e33f68ddc6120160057
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bcf70e8639131a5d7198028d7f70e632ebb817eba816635d24d753dfa4023bc0364e0b8a6082f2ccd747d40bf7c5f7d778ad2efeb2b6283e6c10604a4f44492b
|
|
7
|
+
data.tar.gz: b802f4c8cc2654c8464ec156967430573577a76316d916e31e5b043d81a61a8e2279bf5fadc037b38f2f388e3241507b4f17be08b78558fa2424da4b72315c31
|
data/lib/milk_tea/base.rb
CHANGED
|
@@ -211,7 +211,7 @@ module MilkTea
|
|
|
211
211
|
unresolved_import_paths.include?(import_path)
|
|
212
212
|
end
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
def self.path_to_uri(path)
|
|
215
215
|
escaped_path = path.split('/').map { |seg| CGI.escape(seg).gsub('+', '%20') }.join('/')
|
|
216
216
|
"file://#{escaped_path}"
|
|
217
217
|
end
|
|
@@ -18,7 +18,6 @@ module MilkTea
|
|
|
18
18
|
local_name = import.alias_name || import.path.parts.last
|
|
19
19
|
next if ignored_binding_name?(local_name)
|
|
20
20
|
next if used.include?(local_name)
|
|
21
|
-
next if import_provides_extending_methods?(import)
|
|
22
21
|
|
|
23
22
|
@warnings << Warning.new(
|
|
24
23
|
path: @path,
|
|
@@ -32,15 +31,6 @@ module MilkTea
|
|
|
32
31
|
end
|
|
33
32
|
end
|
|
34
33
|
|
|
35
|
-
def import_provides_extending_methods?(import)
|
|
36
|
-
return false unless @sema_facts.respond_to?(:imports)
|
|
37
|
-
|
|
38
|
-
module_binding = @sema_facts.imports[import.alias_name || import.path.parts.last]
|
|
39
|
-
return false unless module_binding&.respond_to?(:methods)
|
|
40
|
-
|
|
41
|
-
module_binding.methods.any?
|
|
42
|
-
end
|
|
43
|
-
|
|
44
34
|
def check_platform_api_drift(source_file)
|
|
45
35
|
resolved_path = self.class.resolve_lint_path(@path)
|
|
46
36
|
return unless resolved_path&.end_with?(".mt")
|
|
@@ -615,10 +605,13 @@ module MilkTea
|
|
|
615
605
|
end
|
|
616
606
|
|
|
617
607
|
def collect_method_provider_import_uses(receiver, member_name, used, binding_resolution)
|
|
618
|
-
return unless receiver.is_a?(AST::Identifier)
|
|
619
608
|
return unless @sema_facts.respond_to?(:imports)
|
|
620
609
|
|
|
621
|
-
receiver_type =
|
|
610
|
+
receiver_type = if receiver.is_a?(AST::Identifier)
|
|
611
|
+
identifier_binding_type(receiver, binding_resolution)
|
|
612
|
+
else
|
|
613
|
+
resolved_expr_type(receiver)
|
|
614
|
+
end
|
|
622
615
|
return unless receiver_type
|
|
623
616
|
|
|
624
617
|
@sema_facts.imports.each do |local_name, module_binding|
|
|
@@ -629,6 +622,14 @@ module MilkTea
|
|
|
629
622
|
end
|
|
630
623
|
end
|
|
631
624
|
|
|
625
|
+
def resolved_expr_type(expr)
|
|
626
|
+
return nil unless @sema_facts.respond_to?(:ast) && @sema_facts.ast.respond_to?(:node_ids)
|
|
627
|
+
return nil unless @sema_facts.respond_to?(:resolved_expr_types)
|
|
628
|
+
|
|
629
|
+
node_id = @sema_facts.ast.node_ids[expr.object_id]
|
|
630
|
+
node_id ? @sema_facts.resolved_expr_types[node_id] : nil
|
|
631
|
+
end
|
|
632
|
+
|
|
632
633
|
def identifier_binding_type(identifier, binding_resolution)
|
|
633
634
|
binding_id = binding_resolution.identifier_binding_ids[identifier.object_id]
|
|
634
635
|
return nil unless binding_id
|
|
@@ -663,7 +664,7 @@ module MilkTea
|
|
|
663
664
|
Types::Registry.generic_instance(
|
|
664
665
|
receiver_type.name,
|
|
665
666
|
receiver_type.arguments.each_with_index.map do |argument, index|
|
|
666
|
-
argument.is_a?(Types::LiteralTypeArg) ? argument : Types::TypeVar.new("
|
|
667
|
+
argument.is_a?(Types::LiteralTypeArg) ? argument : Types::TypeVar.new("__receiver_arg#{index}")
|
|
667
668
|
end,
|
|
668
669
|
)
|
|
669
670
|
when Types::StructInstance
|
data/std/blackboard.mt
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
## Blackboard — typed key-value shared state for AI.
|
|
2
|
+
##
|
|
3
|
+
## Store and retrieve named values that multiple AI systems
|
|
4
|
+
## can read and write. Linear O(n) lookup (tuned for small
|
|
5
|
+
## sizes — typical AI blackboards have under 20 entries).
|
|
6
|
+
##
|
|
7
|
+
## import std.blackboard as bb
|
|
8
|
+
## var board = bb.Blackboard[float].create()
|
|
9
|
+
## board.set("health", 100.0)
|
|
10
|
+
## let h = board.get("health") else: 0.0
|
|
11
|
+
|
|
12
|
+
import std.vec as vec
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
public struct BlackboardEntry[T]:
|
|
16
|
+
key: str
|
|
17
|
+
value: T
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
public struct Blackboard[T]:
|
|
21
|
+
entries: vec.Vec[BlackboardEntry[T]]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ── internal helpers ──
|
|
25
|
+
|
|
26
|
+
function find_entry[T](board: ref[Blackboard[T]], key: str) -> ptr[BlackboardEntry[T]]?:
|
|
27
|
+
for entry in board.entries:
|
|
28
|
+
unsafe:
|
|
29
|
+
if read(entry).key == key:
|
|
30
|
+
return entry
|
|
31
|
+
return null
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# ── public API ──
|
|
35
|
+
|
|
36
|
+
extending Blackboard[T]:
|
|
37
|
+
public static function create() -> Blackboard[T]:
|
|
38
|
+
return Blackboard[T](
|
|
39
|
+
entries = vec.Vec[BlackboardEntry[T]].create()
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
public editable function set(key: str, value: T) -> void:
|
|
44
|
+
let existing = find_entry(ref_of(this), key)
|
|
45
|
+
if existing != null:
|
|
46
|
+
unsafe:
|
|
47
|
+
read(ptr[BlackboardEntry[T]]<-existing).value = value
|
|
48
|
+
return
|
|
49
|
+
this.entries.push(BlackboardEntry[T](key = key, value = value))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
public function get(key: str) -> Option[T]:
|
|
53
|
+
var n = this.entries.len()
|
|
54
|
+
var i: ptr_uint = 0
|
|
55
|
+
while i < n:
|
|
56
|
+
let entry_ptr = this.entries.get(i) else:
|
|
57
|
+
break
|
|
58
|
+
unsafe:
|
|
59
|
+
if read(entry_ptr).key == key:
|
|
60
|
+
return Option[T].some(value = read(entry_ptr).value)
|
|
61
|
+
i += 1
|
|
62
|
+
return Option[T].none
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
public function has(key: str) -> bool:
|
|
66
|
+
var n = this.entries.len()
|
|
67
|
+
var i: ptr_uint = 0
|
|
68
|
+
while i < n:
|
|
69
|
+
let entry_ptr = this.entries.get(i) else:
|
|
70
|
+
break
|
|
71
|
+
unsafe:
|
|
72
|
+
if read(entry_ptr).key == key:
|
|
73
|
+
return true
|
|
74
|
+
i += 1
|
|
75
|
+
return false
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
public editable function remove(key: str) -> void:
|
|
79
|
+
var n = this.entries.len()
|
|
80
|
+
var i: ptr_uint = 0
|
|
81
|
+
while i < n:
|
|
82
|
+
let entry_ptr = this.entries.get(i) else:
|
|
83
|
+
break
|
|
84
|
+
unsafe:
|
|
85
|
+
if read(entry_ptr).key == key:
|
|
86
|
+
this.entries.swap_remove(i)
|
|
87
|
+
return
|
|
88
|
+
i += 1
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
public editable function clear() -> void:
|
|
92
|
+
this.entries.clear()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
public function count() -> ptr_uint:
|
|
96
|
+
return this.entries.len()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
public editable function release() -> void:
|
|
100
|
+
this.entries.release()
|
data/std/cmd.mt
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
## Command pattern — undo/redo with paired do/undo callbacks.
|
|
2
|
+
##
|
|
3
|
+
## Encapsulate reversible actions as value-objects. Stack-based
|
|
4
|
+
## history for linear undo/redo. Recording for replay capture.
|
|
5
|
+
##
|
|
6
|
+
## import std.cmd as cmd
|
|
7
|
+
## var hist = cmd.History[Editor].create()
|
|
8
|
+
## hist.execute(cmd.Cmd[Editor].create(ctx, do_insert, undo_delete))
|
|
9
|
+
## hist.undo()
|
|
10
|
+
|
|
11
|
+
import std.vec as vec
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
public struct Cmd[Context]:
|
|
15
|
+
context: ptr[Context]
|
|
16
|
+
do_fn: fn(context: ptr[Context]) -> void
|
|
17
|
+
undo_fn: fn(context: ptr[Context]) -> void
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
public struct History[Context]:
|
|
21
|
+
undos: vec.Vec[Cmd[Context]]
|
|
22
|
+
redos: vec.Vec[Cmd[Context]]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
public struct Recording[Context]:
|
|
26
|
+
cmds: vec.Vec[Cmd[Context]]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# ── Cmd ──
|
|
30
|
+
|
|
31
|
+
extending Cmd[Context]:
|
|
32
|
+
public static function create(
|
|
33
|
+
context: ptr[Context],
|
|
34
|
+
do_fn: fn(context: ptr[Context]) -> void,
|
|
35
|
+
undo_fn: fn(context: ptr[Context]) -> void
|
|
36
|
+
) -> Cmd[Context]:
|
|
37
|
+
return Cmd[Context](context = context, do_fn = do_fn, undo_fn = undo_fn)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
public function invoke() -> void:
|
|
41
|
+
this.do_fn(this.context)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
public function revert() -> void:
|
|
45
|
+
this.undo_fn(this.context)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# ── History ──
|
|
49
|
+
|
|
50
|
+
extending History[Context]:
|
|
51
|
+
public static function create() -> History[Context]:
|
|
52
|
+
return History[Context](
|
|
53
|
+
undos = vec.Vec[Cmd[Context]].create(),
|
|
54
|
+
redos = vec.Vec[Cmd[Context]].create()
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
public editable function execute(cmd: Cmd[Context]) -> void:
|
|
59
|
+
cmd.invoke()
|
|
60
|
+
this.undos.push(cmd)
|
|
61
|
+
this.redos.clear()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
public editable function undo() -> bool:
|
|
65
|
+
let cmd = this.undos.pop() else:
|
|
66
|
+
return false
|
|
67
|
+
cmd.revert()
|
|
68
|
+
this.redos.push(cmd)
|
|
69
|
+
return true
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
public editable function redo() -> bool:
|
|
73
|
+
let cmd = this.redos.pop() else:
|
|
74
|
+
return false
|
|
75
|
+
cmd.invoke()
|
|
76
|
+
this.undos.push(cmd)
|
|
77
|
+
return true
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
public function can_undo() -> bool:
|
|
81
|
+
return this.undos.len() > 0
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
public function can_redo() -> bool:
|
|
85
|
+
return this.redos.len() > 0
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
public function undo_count() -> ptr_uint:
|
|
89
|
+
return this.undos.len()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
public function redo_count() -> ptr_uint:
|
|
93
|
+
return this.redos.len()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
public editable function clear() -> void:
|
|
97
|
+
this.undos.clear()
|
|
98
|
+
this.redos.clear()
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
public editable function release() -> void:
|
|
102
|
+
this.undos.release()
|
|
103
|
+
this.redos.release()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# ── Recording ──
|
|
107
|
+
|
|
108
|
+
extending Recording[Context]:
|
|
109
|
+
public static function create() -> Recording[Context]:
|
|
110
|
+
return Recording[Context](cmds = vec.Vec[Cmd[Context]].create())
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
public editable function record(cmd: Cmd[Context]) -> void:
|
|
114
|
+
this.cmds.push(cmd)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
public editable function replay(history: ref[History[Context]]) -> void:
|
|
118
|
+
for entry in this.cmds:
|
|
119
|
+
unsafe:
|
|
120
|
+
history.execute(read(entry))
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
public function count() -> ptr_uint:
|
|
124
|
+
return this.cmds.len()
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
public editable function clear() -> void:
|
|
128
|
+
this.cmds.clear()
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
public editable function release() -> void:
|
|
132
|
+
this.cmds.release()
|
data/std/color.mt
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
## Color utilities — RGBA conversion, blending, and presets.
|
|
2
|
+
##
|
|
3
|
+
## Provides an RGBA Color struct compatible with raylib/FBO
|
|
4
|
+
## layouts, plus HSL/HSV conversion, hex parsing, alpha
|
|
5
|
+
## blending, and common named-color constants.
|
|
6
|
+
##
|
|
7
|
+
## import std.color as clr
|
|
8
|
+
## let c = clr.Color.from_hsl(210.0, 0.8, 0.6)
|
|
9
|
+
## let blended = c.alpha_blend(clr.WHITE)
|
|
10
|
+
|
|
11
|
+
public struct Color:
|
|
12
|
+
r: ubyte
|
|
13
|
+
g: ubyte
|
|
14
|
+
b: ubyte
|
|
15
|
+
a: ubyte
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
public const WHITE: Color = Color(r = 255, g = 255, b = 255, a = 255)
|
|
19
|
+
public const BLACK: Color = Color(r = 0, g = 0, b = 0, a = 255)
|
|
20
|
+
public const RED: Color = Color(r = 255, g = 0, b = 0, a = 255)
|
|
21
|
+
public const GREEN: Color = Color(r = 0, g = 255, b = 0, a = 255)
|
|
22
|
+
public const BLUE: Color = Color(r = 0, g = 0, b = 255, a = 255)
|
|
23
|
+
public const YELLOW: Color = Color(r = 255, g = 255, b = 0, a = 255)
|
|
24
|
+
public const CYAN: Color = Color(r = 0, g = 255, b = 255, a = 255)
|
|
25
|
+
public const MAGENTA:Color = Color(r = 255, g = 0, b = 255, a = 255)
|
|
26
|
+
public const GRAY: Color = Color(r = 128, g = 128, b = 128, a = 255)
|
|
27
|
+
public const ORANGE: Color = Color(r = 255, g = 165, b = 0, a = 255)
|
|
28
|
+
public const PINK: Color = Color(r = 255, g = 192, b = 203, a = 255)
|
|
29
|
+
public const PURPLE: Color = Color(r = 128, g = 0, b = 128, a = 255)
|
|
30
|
+
public const TRANSPARENT: Color = Color(r = 0, g = 0, b = 0, a = 0)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# ── math helpers ──
|
|
34
|
+
|
|
35
|
+
function fmin(a: float, b: float) -> float:
|
|
36
|
+
if a < b: return a
|
|
37
|
+
return b
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
function fmax(a: float, b: float) -> float:
|
|
41
|
+
if a > b: return a
|
|
42
|
+
return b
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
function fabs(x: float) -> float:
|
|
46
|
+
if x < 0.0: return -x
|
|
47
|
+
return x
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
function fmod(x: float, m: float) -> float:
|
|
51
|
+
# x - floor(x / m) * m
|
|
52
|
+
let div = x / m
|
|
53
|
+
let fl = float<-(int<-(div))
|
|
54
|
+
if div < 0.0 and float<-(int<-(div)) != div:
|
|
55
|
+
return x - (fl - 1.0) * m
|
|
56
|
+
return x - fl * m
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# ── public API ──
|
|
60
|
+
|
|
61
|
+
extending Color:
|
|
62
|
+
public static function from_rgba(r: ubyte, g: ubyte, b: ubyte, a: ubyte) -> Color:
|
|
63
|
+
return Color(r = r, g = g, b = b, a = a)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
public static function from_hsl(h: float, s: float, l: float) -> Color:
|
|
67
|
+
# h: 0..360, s: 0..1, l: 0..1
|
|
68
|
+
var hh = fmod(h, 360.0)
|
|
69
|
+
if hh < 0.0: hh = hh + 360.0
|
|
70
|
+
|
|
71
|
+
let c = (1.0 - fabs(2.0 * l - 1.0)) * s
|
|
72
|
+
let x = c * (1.0 - fabs(fmod(hh / 60.0, 2.0) - 1.0))
|
|
73
|
+
let m = l - c / 2.0
|
|
74
|
+
|
|
75
|
+
var r1: float = 0.0
|
|
76
|
+
var g1: float = 0.0
|
|
77
|
+
var b1: float = 0.0
|
|
78
|
+
|
|
79
|
+
if hh < 60.0:
|
|
80
|
+
r1 = c
|
|
81
|
+
g1 = x
|
|
82
|
+
else if hh < 120.0:
|
|
83
|
+
r1 = x
|
|
84
|
+
g1 = c
|
|
85
|
+
else if hh < 180.0:
|
|
86
|
+
g1 = c
|
|
87
|
+
b1 = x
|
|
88
|
+
else if hh < 240.0:
|
|
89
|
+
g1 = x
|
|
90
|
+
b1 = c
|
|
91
|
+
else if hh < 300.0:
|
|
92
|
+
r1 = x
|
|
93
|
+
b1 = c
|
|
94
|
+
else:
|
|
95
|
+
r1 = c
|
|
96
|
+
b1 = x
|
|
97
|
+
|
|
98
|
+
return Color(
|
|
99
|
+
r = ubyte<-((r1 + m) * 255.0),
|
|
100
|
+
g = ubyte<-((g1 + m) * 255.0),
|
|
101
|
+
b = ubyte<-((b1 + m) * 255.0),
|
|
102
|
+
a = 255
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
public static function from_hsv(h: float, s: float, v: float) -> Color:
|
|
107
|
+
var hh = fmod(h, 360.0)
|
|
108
|
+
if hh < 0.0: hh = hh + 360.0
|
|
109
|
+
|
|
110
|
+
let c = v * s
|
|
111
|
+
let x = c * (1.0 - fabs(fmod(hh / 60.0, 2.0) - 1.0))
|
|
112
|
+
let m = v - c
|
|
113
|
+
|
|
114
|
+
var r1: float = 0.0
|
|
115
|
+
var g1: float = 0.0
|
|
116
|
+
var b1: float = 0.0
|
|
117
|
+
|
|
118
|
+
if hh < 60.0:
|
|
119
|
+
r1 = c
|
|
120
|
+
g1 = x
|
|
121
|
+
else if hh < 120.0:
|
|
122
|
+
r1 = x
|
|
123
|
+
g1 = c
|
|
124
|
+
else if hh < 180.0:
|
|
125
|
+
g1 = c
|
|
126
|
+
b1 = x
|
|
127
|
+
else if hh < 240.0:
|
|
128
|
+
g1 = x
|
|
129
|
+
b1 = c
|
|
130
|
+
else if hh < 300.0:
|
|
131
|
+
r1 = x
|
|
132
|
+
b1 = c
|
|
133
|
+
else:
|
|
134
|
+
r1 = c
|
|
135
|
+
b1 = x
|
|
136
|
+
|
|
137
|
+
return Color(
|
|
138
|
+
r = ubyte<-((r1 + m) * 255.0),
|
|
139
|
+
g = ubyte<-((g1 + m) * 255.0),
|
|
140
|
+
b = ubyte<-((b1 + m) * 255.0),
|
|
141
|
+
a = 255
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
public function to_hsl() -> (float, float, float):
|
|
146
|
+
let rf = float<-(this.r) / 255.0
|
|
147
|
+
let gf = float<-(this.g) / 255.0
|
|
148
|
+
let bf = float<-(this.b) / 255.0
|
|
149
|
+
|
|
150
|
+
let mx = fmax(fmax(rf, gf), bf)
|
|
151
|
+
let mn = fmin(fmin(rf, gf), bf)
|
|
152
|
+
let delta = mx - mn
|
|
153
|
+
|
|
154
|
+
let l = (mx + mn) / 2.0
|
|
155
|
+
|
|
156
|
+
var h: float = 0.0
|
|
157
|
+
let s = if delta == 0.0: 0.0 else: delta / (1.0 - fabs(2.0 * l - 1.0))
|
|
158
|
+
|
|
159
|
+
if delta != 0.0:
|
|
160
|
+
if mx == rf:
|
|
161
|
+
h = fmod((gf - bf) / delta, 6.0)
|
|
162
|
+
else if mx == gf:
|
|
163
|
+
h = (bf - rf) / delta + 2.0
|
|
164
|
+
else:
|
|
165
|
+
h = (rf - gf) / delta + 4.0
|
|
166
|
+
h = h * 60.0
|
|
167
|
+
if h < 0.0:
|
|
168
|
+
h = h + 360.0
|
|
169
|
+
|
|
170
|
+
return (h, s, l)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
public function to_hsv() -> (float, float, float):
|
|
174
|
+
let rf = float<-(this.r) / 255.0
|
|
175
|
+
let gf = float<-(this.g) / 255.0
|
|
176
|
+
let bf = float<-(this.b) / 255.0
|
|
177
|
+
|
|
178
|
+
let mx = fmax(fmax(rf, gf), bf)
|
|
179
|
+
let mn = fmin(fmin(rf, gf), bf)
|
|
180
|
+
let delta = mx - mn
|
|
181
|
+
|
|
182
|
+
var h: float = 0.0
|
|
183
|
+
let s = if mx == 0.0: 0.0 else: delta / mx
|
|
184
|
+
let v = mx
|
|
185
|
+
|
|
186
|
+
if delta != 0.0:
|
|
187
|
+
if mx == rf:
|
|
188
|
+
h = fmod((gf - bf) / delta, 6.0)
|
|
189
|
+
else if mx == gf:
|
|
190
|
+
h = (bf - rf) / delta + 2.0
|
|
191
|
+
else:
|
|
192
|
+
h = (rf - gf) / delta + 4.0
|
|
193
|
+
h = h * 60.0
|
|
194
|
+
if h < 0.0:
|
|
195
|
+
h = h + 360.0
|
|
196
|
+
|
|
197
|
+
return (h, s, v)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
public function lerp(target: Color, t: float) -> Color:
|
|
201
|
+
let r = float<-(this.r) + (float<-(target.r) - float<-(this.r)) * t
|
|
202
|
+
let g = float<-(this.g) + (float<-(target.g) - float<-(this.g)) * t
|
|
203
|
+
let b = float<-(this.b) + (float<-(target.b) - float<-(this.b)) * t
|
|
204
|
+
let a = float<-(this.a) + (float<-(target.a) - float<-(this.a)) * t
|
|
205
|
+
return Color(r = ubyte<-(r), g = ubyte<-(g), b = ubyte<-(b), a = ubyte<-(a))
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
public function alpha_blend(background: Color) -> Color:
|
|
209
|
+
if this.a == 0:
|
|
210
|
+
return background
|
|
211
|
+
if this.a == 255:
|
|
212
|
+
return this
|
|
213
|
+
|
|
214
|
+
let sa = float<-(this.a) / 255.0
|
|
215
|
+
let da = float<-(background.a) / 255.0
|
|
216
|
+
|
|
217
|
+
let r_out = float<-(this.r) * sa + float<-(background.r) * da * (1.0 - sa)
|
|
218
|
+
let g_out = float<-(this.g) * sa + float<-(background.g) * da * (1.0 - sa)
|
|
219
|
+
let b_out = float<-(this.b) * sa + float<-(background.b) * da * (1.0 - sa)
|
|
220
|
+
let a_out = sa + da * (1.0 - sa)
|
|
221
|
+
|
|
222
|
+
return Color(
|
|
223
|
+
r = ubyte<-(r_out),
|
|
224
|
+
g = ubyte<-(g_out),
|
|
225
|
+
b = ubyte<-(b_out),
|
|
226
|
+
a = ubyte<-(a_out * 255.0)
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
public function scale(factor: float) -> Color:
|
|
231
|
+
let r = fmin(fmax(float<-(this.r) * factor, 0.0), 255.0)
|
|
232
|
+
let g = fmin(fmax(float<-(this.g) * factor, 0.0), 255.0)
|
|
233
|
+
let b = fmin(fmax(float<-(this.b) * factor, 0.0), 255.0)
|
|
234
|
+
return Color(r = ubyte<-(r), g = ubyte<-(g), b = ubyte<-(b), a = this.a)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
public function multiply(other: Color) -> Color:
|
|
238
|
+
let r = ubyte<-(int<-((int<-(this.r) * int<-(other.r)) / 255))
|
|
239
|
+
let g = ubyte<-(int<-((int<-(this.g) * int<-(other.g)) / 255))
|
|
240
|
+
let b = ubyte<-(int<-((int<-(this.b) * int<-(other.b)) / 255))
|
|
241
|
+
return Color(r = r, g = g, b = b, a = this.a)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
public function with_alpha(a: ubyte) -> Color:
|
|
245
|
+
return Color(r = this.r, g = this.g, b = this.b, a = a)
|