|
| 1 | +extends Node |
| 2 | +class_name Utilities |
| 3 | + |
| 4 | +static func get_json_data(value): |
| 5 | + if value is PackedByteArray: |
| 6 | + value = value.get_string_from_utf8() |
| 7 | + var json = JSON.new() |
| 8 | + var json_parse_result = json.parse(value) |
| 9 | + if json_parse_result == OK: |
| 10 | + return json.data |
| 11 | + |
| 12 | + return null |
| 13 | + |
| 14 | + |
| 15 | +# HTTPRequeust seems to have an issue in Web exports where the body returns empty |
| 16 | +# This appears to be caused by the gzip compression being unsupported, so we |
| 17 | +# disable it when web export is detected. |
| 18 | +static func fix_http_request(http_request): |
| 19 | + if is_web(): |
| 20 | + http_request.accept_gzip = false |
| 21 | + |
| 22 | +static func is_web() -> bool: |
| 23 | + return OS.get_name() in ["HTML5", "Web"] |
| 24 | + |
| 25 | + |
| 26 | +class MultiSignal extends RefCounted: |
| 27 | + signal completed(with_signal) |
| 28 | + signal all_completed() |
| 29 | + |
| 30 | + var _has_signaled := false |
| 31 | + var _early_exit := false |
| 32 | + |
| 33 | + var signal_count := 0 |
| 34 | + |
| 35 | + func _init(sigs : Array[Signal], early_exit := true, should_oneshot := true) -> void: |
| 36 | + _early_exit = early_exit |
| 37 | + for sig in sigs: |
| 38 | + add_signal(sig, should_oneshot) |
| 39 | + |
| 40 | + func add_signal(sig : Signal, should_oneshot) -> void: |
| 41 | + signal_count += 1 |
| 42 | + sig.connect( |
| 43 | + func(): |
| 44 | + if not _has_signaled and _early_exit: |
| 45 | + completed.emit(sig) |
| 46 | + _has_signaled = true |
| 47 | + elif not _early_exit: |
| 48 | + completed.emit(sig) |
| 49 | + signal_count -= 1 |
| 50 | + if signal_count <= 0: # Not sure how it could be less than |
| 51 | + all_completed.emit() |
| 52 | + , CONNECT_ONE_SHOT if should_oneshot else CONNECT_REFERENCE_COUNTED |
| 53 | + ) |
| 54 | + |
| 55 | +class SignalReducer extends RefCounted: # No need for a node, as this deals strictly with signals, which can be on any object. |
| 56 | + signal completed |
| 57 | + |
| 58 | + var awaiters : Array[Signal] = [] |
| 59 | + |
| 60 | + var reducers = { |
| 61 | + 0 : completed.emit, |
| 62 | + 1 : func(p): completed.emit(), |
| 63 | + 2 : func(p1, p2): completed.emit(), |
| 64 | + 3 : func(p1, p2, p3): completed.emit(), |
| 65 | + 4 : func(p1, p2, p3, p4): completed.emit() |
| 66 | + } |
| 67 | + |
| 68 | + func add_signal(sig : Signal, param_count : int = 0) -> void: |
| 69 | + assert(param_count < 5, "Too many parameters to reduce, just add more!") |
| 70 | + sig.connect(reducers[param_count], CONNECT_ONE_SHOT) # May wish to not just one-shot, but instead track all of them firing |
| 71 | + |
| 72 | +class SignalReducerWithResult extends RefCounted: # No need for a node, as this deals strictly with signals, which can be on any object. |
| 73 | + signal completed(result) |
| 74 | + |
| 75 | + var awaiters : Array[Signal] = [] |
| 76 | + |
| 77 | + var reducers = { |
| 78 | + 0 : completed.emit, |
| 79 | + 1 : func(p): completed.emit({1 : p}), |
| 80 | + 2 : func(p1, p2): completed.emit({ 1 : p1, 2 : p2 }), |
| 81 | + 3 : func(p1, p2, p3): completed.emit({ 1 : p1, 2 : p2, 3 : p3 }), |
| 82 | + 4 : func(p1, p2, p3, p4): completed.emit({ 1 : p1, 2 : p2, 3 : p3, 4 : p4 }) |
| 83 | + } |
| 84 | + |
| 85 | + func add_signal(sig : Signal, param_count : int = 0) -> void: |
| 86 | + assert(param_count < 5, "Too many parameters to reduce, just add more!") |
| 87 | + sig.connect(reducers[param_count], CONNECT_ONE_SHOT) # May wish to not just one-shot, but instead track all of them firing |
| 88 | + |
| 89 | +class ObservableDictionary extends RefCounted: |
| 90 | + signal keys_changed() |
| 91 | + |
| 92 | + var _internal : Dictionary |
| 93 | + var is_notifying := true |
| 94 | + |
| 95 | + func _init(copy : Dictionary = {}) -> void: |
| 96 | + _internal = copy |
| 97 | + |
| 98 | + func add(key : Variant, value : Variant) -> void: |
| 99 | + _internal[key] = value |
| 100 | + if is_notifying: |
| 101 | + keys_changed.emit() |
| 102 | + |
| 103 | + func update(key : Variant, value : Variant) -> void: |
| 104 | + _internal[key] = value |
| 105 | + if is_notifying: |
| 106 | + keys_changed.emit() |
| 107 | + |
| 108 | + func has(key : Variant) -> bool: |
| 109 | + return _internal.has(key) |
| 110 | + |
| 111 | + func keys(): |
| 112 | + return _internal.keys() |
| 113 | + |
| 114 | + func values(): |
| 115 | + return _internal.values() |
| 116 | + |
| 117 | + func erase(key : Variant) -> bool: |
| 118 | + var result = _internal.erase(key) |
| 119 | + if is_notifying: |
| 120 | + keys_changed.emit() |
| 121 | + |
| 122 | + return result |
| 123 | + |
| 124 | + func get_value(key : Variant) -> Variant: |
| 125 | + return _internal[key] |
| 126 | + |
| 127 | + func _get(property: StringName) -> Variant: |
| 128 | + if _internal.has(property): |
| 129 | + return _internal[property] |
| 130 | + |
| 131 | + return false |
| 132 | + |
| 133 | + func _set(property: StringName, value: Variant) -> bool: |
| 134 | + update(property, value) |
| 135 | + return true |
0 commit comments