initial commit
This commit is contained in:
commit
739752e75b
77 changed files with 11310 additions and 0 deletions
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Normalize EOL for all files that Git considers text files.
|
||||
* text=auto eol=lf
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
/android/
|
4
godot/.editorconfig
Normal file
4
godot/.editorconfig
Normal file
|
@ -0,0 +1,4 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
28
godot/addons/convert/convert.gd
Normal file
28
godot/addons/convert/convert.gd
Normal file
|
@ -0,0 +1,28 @@
|
|||
class_name Convert
|
||||
|
||||
class FromString:
|
||||
static func _invalid_type(value: String, type: String) -> Error:
|
||||
return Error.new('"%s" is not a valid %s')
|
||||
|
||||
static func to_int(value: String) -> Result:
|
||||
if value.is_valid_int():
|
||||
return Result.ok(value.to_int())
|
||||
else: return Result.err(_invalid_type(value, 'int'))
|
||||
|
||||
static func to_float(value: String) -> Result:
|
||||
if value.is_valid_float():
|
||||
return Result.ok(value.to_float())
|
||||
else: return Result.err(_invalid_type(value, 'float'))
|
||||
|
||||
static func to_bool(value: String) -> Result:
|
||||
if value == 'true': return Result.ok(true)
|
||||
elif value == 'false': return Result.ok(false)
|
||||
else: return Result.err(_invalid_type(value, 'bool'))
|
||||
|
||||
static func binary_to_int(value: String) -> int:
|
||||
return value.bin_to_int()
|
||||
|
||||
static func hex_to_int(value: String) -> Result:
|
||||
if value.is_valid_hex_number():
|
||||
return Result.ok(value.hex_to_int())
|
||||
else: return Result.err(_invalid_type(value, 'hex string'))
|
1
godot/addons/convert/convert.gd.uid
Normal file
1
godot/addons/convert/convert.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://3fd4av3spg8k
|
33
godot/addons/error/error.gd
Normal file
33
godot/addons/error/error.gd
Normal file
|
@ -0,0 +1,33 @@
|
|||
class_name Error extends RefCounted
|
||||
|
||||
var message: String
|
||||
var stack: Array
|
||||
|
||||
func _init(message: String):
|
||||
self.message = message
|
||||
stack = get_stack().slice(1)
|
||||
|
||||
func raise_self():
|
||||
Error.raise(message)
|
||||
|
||||
static func raise(message: String):
|
||||
push_error(message)
|
||||
assert(false)
|
||||
|
||||
func _to_string() -> String:
|
||||
var str = message
|
||||
for value in stack:
|
||||
str += "\r\n%s:%s - at function %s" % [value.source, value.line, value.function]
|
||||
return str
|
||||
|
||||
class NotImplemented extends Error:
|
||||
static var _message: String = "NotImplementedError: %s is not implemented"
|
||||
|
||||
func _init(name: String):
|
||||
super(_message % name)
|
||||
|
||||
class InvalidArgument extends Error:
|
||||
static var _message: String = 'InvalidArgumentError: %s is not a valid argument'
|
||||
|
||||
func _init(arg: Variant):
|
||||
super(_message % arg)
|
1
godot/addons/error/error.gd.uid
Normal file
1
godot/addons/error/error.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://ds0dnuvhjij4h
|
24
godot/addons/iterator/index.gd
Normal file
24
godot/addons/iterator/index.gd
Normal file
|
@ -0,0 +1,24 @@
|
|||
class_name IndexedIterator extends Iterator
|
||||
|
||||
class Indexed extends RefCounted:
|
||||
var value: Variant
|
||||
var index: int
|
||||
|
||||
func _init(_value: Variant, _index: int) -> void:
|
||||
value = _value
|
||||
index = _index
|
||||
|
||||
var _iter: Iterator
|
||||
var _index: int = 0
|
||||
|
||||
func _init(iter: Iterator) -> void:
|
||||
_iter = iter
|
||||
|
||||
func _add_index(value: Variant) -> Indexed:
|
||||
return Indexed.new(value, _index)
|
||||
|
||||
func clone() -> IndexedIterator:
|
||||
return IndexedIterator.new(_iter.clone())
|
||||
|
||||
func next() -> Option:
|
||||
return _iter.next().map(_add_index)
|
1
godot/addons/iterator/index.gd.uid
Normal file
1
godot/addons/iterator/index.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://b2w3v1h5ex4tm
|
23
godot/addons/iterator/iterator.gd
Normal file
23
godot/addons/iterator/iterator.gd
Normal file
|
@ -0,0 +1,23 @@
|
|||
class_name Iterator extends RefCounted
|
||||
|
||||
func clone() -> Iterator:
|
||||
return Iterator.new()
|
||||
|
||||
func next() -> Option:
|
||||
return Option.none
|
||||
|
||||
func into_peekable() -> PeekableIter:
|
||||
return PeekableIter.new(self)
|
||||
|
||||
func into_indexed() -> IndexedIterator:
|
||||
return IndexedIterator.new(self)
|
||||
|
||||
func _iter_init(iter: Array) -> bool:
|
||||
return _iter_next(iter)
|
||||
|
||||
func _iter_next(iter: Array) -> bool:
|
||||
iter[0] = next()
|
||||
return iter[0].is_some()
|
||||
|
||||
func _iter_get(iter: Variant) -> Variant:
|
||||
return iter.unwrap()
|
1
godot/addons/iterator/iterator.gd.uid
Normal file
1
godot/addons/iterator/iterator.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://r3doxerf7d0j
|
17
godot/addons/iterator/list.gd
Normal file
17
godot/addons/iterator/list.gd
Normal file
|
@ -0,0 +1,17 @@
|
|||
class_name ListIterator extends Iterator
|
||||
|
||||
var _value: Variant
|
||||
var _iter: RangeIterator
|
||||
|
||||
func _init(value: Variant, iter: RangeIterator) -> void:
|
||||
_value = value
|
||||
_iter = iter
|
||||
|
||||
func _at(index: int) -> Variant:
|
||||
return _value[index]
|
||||
|
||||
func clone() -> ListIterator:
|
||||
return ListIterator.new(_value, _iter.clone())
|
||||
|
||||
func next() -> Option:
|
||||
return _iter.next().map(_at)
|
1
godot/addons/iterator/list.gd.uid
Normal file
1
godot/addons/iterator/list.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://hpnk6jd2353w
|
23
godot/addons/iterator/peekable.gd
Normal file
23
godot/addons/iterator/peekable.gd
Normal file
|
@ -0,0 +1,23 @@
|
|||
class_name PeekableIter extends Iterator
|
||||
|
||||
var _iter: Iterator
|
||||
var _peeked: Variant
|
||||
|
||||
func _init(iter: Iterator) -> void:
|
||||
_iter = iter
|
||||
|
||||
func clone() -> PeekableIter:
|
||||
return PeekableIter.new(_iter.clone())
|
||||
|
||||
func peek() -> Option:
|
||||
if _peeked == null:
|
||||
_peeked = _iter.next()
|
||||
return _peeked
|
||||
|
||||
func next() -> Option:
|
||||
if _peeked == null:
|
||||
return _iter.next()
|
||||
else:
|
||||
var value = _peeked
|
||||
_peeked = null
|
||||
return value
|
1
godot/addons/iterator/peekable.gd.uid
Normal file
1
godot/addons/iterator/peekable.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://u6wma683vqer
|
19
godot/addons/iterator/range.gd
Normal file
19
godot/addons/iterator/range.gd
Normal file
|
@ -0,0 +1,19 @@
|
|||
class_name RangeIterator extends Iterator
|
||||
|
||||
var _index: int
|
||||
var _to: int
|
||||
var _step: int
|
||||
|
||||
func _init(from: int, to: int, step: int = 1) -> void:
|
||||
_index = from - 1
|
||||
_to = to
|
||||
_step = step
|
||||
|
||||
func clone() -> RangeIterator:
|
||||
return RangeIterator.new(_index, _to, _step)
|
||||
|
||||
func next() -> Option:
|
||||
if _index < _to:
|
||||
_index += 1
|
||||
return Option.some(_index)
|
||||
else: return Option.none
|
1
godot/addons/iterator/range.gd.uid
Normal file
1
godot/addons/iterator/range.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://dqqwqcdx75cfu
|
16
godot/addons/iterator/take_while.gd
Normal file
16
godot/addons/iterator/take_while.gd
Normal file
|
@ -0,0 +1,16 @@
|
|||
class_name TakeWhileIter extends Iterator
|
||||
|
||||
var _iter: Iterator
|
||||
var _predicate: Callable
|
||||
|
||||
func _init(iter: Iterator, predicate: Callable) -> void:
|
||||
_iter = iter
|
||||
_predicate = predicate
|
||||
|
||||
func clone() -> TakeWhileIter:
|
||||
return self
|
||||
|
||||
func next() -> Option:
|
||||
match _iter.next().filter(_predicate):
|
||||
var x when x.is_some(): return x
|
||||
_: return Option.none
|
1
godot/addons/iterator/take_while.gd.uid
Normal file
1
godot/addons/iterator/take_while.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://cdj83mvbbfvjj
|
18
godot/addons/iterator/variant.gd
Normal file
18
godot/addons/iterator/variant.gd
Normal file
|
@ -0,0 +1,18 @@
|
|||
class_name VariantIterator extends Iterator
|
||||
|
||||
var _iterable: Variant
|
||||
var _state: Array
|
||||
|
||||
func _init(value) -> void:
|
||||
_iterable = value
|
||||
_state = value._iter_init([])
|
||||
|
||||
func clone() -> VariantIterator:
|
||||
var new = VariantIterator.new(_iterable)
|
||||
new._state = _state
|
||||
return new
|
||||
|
||||
func next() -> Option:
|
||||
if _iterable._iter_next(_state):
|
||||
return Option.some(_iterable._iter_get(_state[0]))
|
||||
else: return Option.none
|
1
godot/addons/iterator/variant.gd.uid
Normal file
1
godot/addons/iterator/variant.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://g86f3fcv5pra
|
87
godot/addons/monads/option.gd
Normal file
87
godot/addons/monads/option.gd
Normal file
|
@ -0,0 +1,87 @@
|
|||
class_name Option extends RefCounted
|
||||
|
||||
static var Unit = Option.some(null)
|
||||
|
||||
static func some(value: Variant) -> Option:
|
||||
return Some.new(value)
|
||||
|
||||
static var none: Option.None = None.new()
|
||||
|
||||
static func collect_some(options: Array[Option]) -> Option:
|
||||
match options:
|
||||
[]: return Option.none
|
||||
[var x]: return x
|
||||
_:
|
||||
var result = []
|
||||
|
||||
for option in options:
|
||||
if option.is_some():
|
||||
result.push_back(option.unwrap())
|
||||
else:
|
||||
return Option.none
|
||||
|
||||
return Option.some(result)
|
||||
|
||||
class Some extends Option:
|
||||
var value: Variant
|
||||
|
||||
func _init(val: Variant) -> void:
|
||||
value = val
|
||||
|
||||
func chain(fn: Callable) -> Option:
|
||||
return fn.call(value)
|
||||
|
||||
func filter(fn: Callable) -> Option:
|
||||
if fn.call(value): return self
|
||||
else: return Option.none
|
||||
|
||||
func flatten() -> Option:
|
||||
if value is Option:
|
||||
return value.flatten()
|
||||
else: return Option.some(value)
|
||||
|
||||
func map(fn: Callable) -> Option:
|
||||
return Option.some(fn.call(value))
|
||||
|
||||
func is_some() -> bool:
|
||||
return true
|
||||
|
||||
func is_none() -> bool:
|
||||
return false
|
||||
|
||||
func or_default(_default_value: Variant) -> Variant:
|
||||
return value
|
||||
|
||||
func or_else(_fn: Callable) -> Variant:
|
||||
return value
|
||||
|
||||
func unwrap() -> Variant:
|
||||
return value
|
||||
|
||||
class None extends Option:
|
||||
func chain(_fn: Callable) -> Option:
|
||||
return self
|
||||
|
||||
func filter(_f: Callable) -> Option:
|
||||
return self
|
||||
|
||||
func flatten() -> Option:
|
||||
return self
|
||||
|
||||
func map(_fn: Callable) -> Option:
|
||||
return self
|
||||
|
||||
func is_some() -> bool:
|
||||
return false
|
||||
|
||||
func is_none() -> bool:
|
||||
return true
|
||||
|
||||
func or_default(default_value: Variant) -> Variant:
|
||||
return default_value
|
||||
|
||||
func or_else(fn: Callable) -> Variant:
|
||||
return fn.call()
|
||||
|
||||
func unwrap() -> Variant:
|
||||
return null
|
1
godot/addons/monads/option.gd.uid
Normal file
1
godot/addons/monads/option.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://k2qcgaguq3o0
|
99
godot/addons/monads/result.gd
Normal file
99
godot/addons/monads/result.gd
Normal file
|
@ -0,0 +1,99 @@
|
|||
class_name Result extends RefCounted
|
||||
|
||||
static var Unit: Result = Result.ok(null)
|
||||
|
||||
static func ok(value: Variant) -> Result:
|
||||
return Ok.new(value)
|
||||
|
||||
static func err(error: Variant) -> Result:
|
||||
return Err.new(error)
|
||||
|
||||
static func collect_ok(results: Array[Result]) -> Result:
|
||||
match results:
|
||||
[]: return Result.Unit
|
||||
[var x]: return x
|
||||
_:
|
||||
var res = []
|
||||
|
||||
for result in results:
|
||||
if result.is_ok():
|
||||
res.push_back(result.unwrap())
|
||||
else:
|
||||
return result
|
||||
|
||||
return Result.ok(res)
|
||||
|
||||
class Ok extends Result:
|
||||
var value: Variant
|
||||
|
||||
func _init(value):
|
||||
self.value = value
|
||||
|
||||
func to_option() -> Option:
|
||||
return Option.some(value)
|
||||
|
||||
func chain(fn: Callable) -> Result:
|
||||
return fn.call(value)
|
||||
|
||||
func filter(fn: Callable, fail) -> Result:
|
||||
if fn.call(value):
|
||||
return self
|
||||
else:
|
||||
return Result.err(fail)
|
||||
|
||||
func map(fn: Callable) -> Result:
|
||||
return Result.ok(fn.call(value))
|
||||
|
||||
func is_ok() -> bool:
|
||||
return true
|
||||
|
||||
func is_err() -> bool:
|
||||
return false
|
||||
|
||||
func or_default(_default_value: Variant) -> Variant:
|
||||
return value
|
||||
|
||||
func or_else(_fn: Callable) -> Variant:
|
||||
return value
|
||||
|
||||
func unwrap() -> Variant:
|
||||
return value
|
||||
|
||||
func unwrap_err() -> Variant:
|
||||
return null
|
||||
|
||||
class Err extends Result:
|
||||
var error: Variant
|
||||
|
||||
func _init(error) -> void:
|
||||
self.error = error
|
||||
|
||||
func to_option() -> Option:
|
||||
return Option.none
|
||||
|
||||
func chain(_fn: Callable) -> Result:
|
||||
return self
|
||||
|
||||
func filter(_fn: Callable, fail) -> Result:
|
||||
return Result.err(fail)
|
||||
|
||||
func map(fn: Callable) -> Result:
|
||||
return self
|
||||
|
||||
func is_ok() -> bool:
|
||||
return false
|
||||
|
||||
func is_err() -> bool:
|
||||
return true
|
||||
|
||||
func or_default(default_value: Variant) -> Variant:
|
||||
return default_value
|
||||
|
||||
func or_else(fn: Callable) -> Variant:
|
||||
return fn.call()
|
||||
|
||||
func unwrap() -> Variant:
|
||||
return null
|
||||
|
||||
func unwrap_err() -> Variant:
|
||||
return error
|
1
godot/addons/monads/result.gd.uid
Normal file
1
godot/addons/monads/result.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://do2wtq5541j5d
|
0
godot/addons/serde/binary.gd
Normal file
0
godot/addons/serde/binary.gd
Normal file
1
godot/addons/serde/binary.gd.uid
Normal file
1
godot/addons/serde/binary.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://cnbk0hdc5ngxo
|
62
godot/addons/serde/encoding.gd
Normal file
62
godot/addons/serde/encoding.gd
Normal file
|
@ -0,0 +1,62 @@
|
|||
class_name Encoding extends RefCounted
|
||||
|
||||
enum Type {
|
||||
Ascii,
|
||||
Utf8,
|
||||
Utf16,
|
||||
Utf32,
|
||||
Wchar
|
||||
}
|
||||
|
||||
static var Ascii = from(Type.Ascii)
|
||||
static var Utf8 = from(Type.Utf8)
|
||||
static var Utf16 = from(Type.Utf16)
|
||||
static var Utf32 = from(Type.Utf32)
|
||||
static var Wchar = from(Type.Wchar)
|
||||
|
||||
var type: Type
|
||||
|
||||
func _init(_type: Type) -> void:
|
||||
type = _type
|
||||
|
||||
static func from(type: Type) -> Encoding:
|
||||
return Encoding.new(type)
|
||||
|
||||
static func byte_size_of(encoding: Type) -> int:
|
||||
match encoding:
|
||||
Type.Ascii: return 1
|
||||
Type.Utf8: return 1
|
||||
Type.Utf16: return 2
|
||||
Type.Utf32: return 4
|
||||
Type.Wchar:
|
||||
match OS.get_name():
|
||||
"Windows": return 2
|
||||
_: return 4
|
||||
return -1
|
||||
|
||||
func byte_size() -> int:
|
||||
return byte_size_of(type)
|
||||
|
||||
static func encode_str_as(value: String, encoding: Type) -> PackedByteArray:
|
||||
match encoding:
|
||||
Type.Ascii: return value.to_ascii_buffer()
|
||||
Type.Utf8: return value.to_utf8_buffer()
|
||||
Type.Utf16: return value.to_utf16_buffer()
|
||||
Type.Utf32: return value.to_utf32_buffer()
|
||||
Type.Wchar: return value.to_wchar_buffer()
|
||||
return PackedByteArray()
|
||||
|
||||
func encode_str(value: String) -> PackedByteArray:
|
||||
return encode_str_as(value, type)
|
||||
|
||||
static func decode_str_as(value: PackedByteArray, encoding: Type) -> String:
|
||||
match encoding:
|
||||
Type.Ascii: return value.get_string_from_ascii()
|
||||
Type.Utf8: return value.get_string_from_utf8()
|
||||
Type.Utf16: return value.get_string_from_utf16()
|
||||
Type.Utf32: return value.get_string_from_utf32()
|
||||
Type.Wchar: return value.get_string_from_wchar()
|
||||
return ""
|
||||
|
||||
func decode_str(value: PackedByteArray) -> String:
|
||||
return decode_str_as(value, type)
|
1
godot/addons/serde/encoding.gd.uid
Normal file
1
godot/addons/serde/encoding.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://mkxfk1awv1fv
|
364
godot/addons/serde/json.gd
Normal file
364
godot/addons/serde/json.gd
Normal file
|
@ -0,0 +1,364 @@
|
|||
class_name Json
|
||||
|
||||
static func stringify(value: Variant, allow_eval: bool = false) -> String:
|
||||
var ser = Json.Serializer.new(allow_eval)
|
||||
Serde.serialize(ser, value, allow_eval)
|
||||
return ser.output
|
||||
|
||||
static func parse_string(value: String, into: Variant = null, allow_eval: bool = false) -> Variant:
|
||||
var de = Json.Deserializer.from_string(value)
|
||||
if into != null and into.has_method(Serde.DeserializeMethod):
|
||||
return into.call(Serde.DeserializeMethod, de)
|
||||
else:
|
||||
return de.deserialize_any(Serde.GenericVisitor.new())
|
||||
|
||||
class SerializeSeq extends Serde.SerializeSeq:
|
||||
var ser: Json.Serializer
|
||||
var first: bool = true
|
||||
|
||||
func _init(ser: Json.Serializer) -> void:
|
||||
self.ser = ser
|
||||
ser.write('[')
|
||||
|
||||
func serialize_element(value: Variant) -> Result:
|
||||
if not first: ser.write(',')
|
||||
first = false
|
||||
Serde.serialize(ser, value, ser.allow_eval)
|
||||
return Result.Unit
|
||||
|
||||
func end() -> Result:
|
||||
ser.write(']')
|
||||
return Result.Unit
|
||||
|
||||
class SerializeMap extends Serde.SerializeMap:
|
||||
var ser: Json.Serializer
|
||||
var first: bool = true
|
||||
|
||||
func _init(ser: Json.Serializer) -> void:
|
||||
self.ser = ser
|
||||
ser.write('{')
|
||||
|
||||
func serialize_key(value: Variant) -> Result:
|
||||
if not first: ser.write(',')
|
||||
first = false
|
||||
Serde.serialize(ser, value, ser.allow_eval)
|
||||
return Result.Unit
|
||||
|
||||
func serialize_value(value: Variant) -> Result:
|
||||
ser.write(':')
|
||||
Serde.serialize(ser, value, ser.allow_eval)
|
||||
return Result.Unit
|
||||
|
||||
func end() -> Result:
|
||||
ser.write('}')
|
||||
return Result.Unit
|
||||
|
||||
class Serializer extends Serde.Serializer:
|
||||
var output: String
|
||||
var allow_eval: bool
|
||||
|
||||
func _init(allow_eval: bool = false) -> void:
|
||||
self.allow_eval = allow_eval
|
||||
|
||||
func write(value: String) -> Result:
|
||||
output += value
|
||||
return Result.Unit
|
||||
|
||||
func write_string(value: Variant) -> Result:
|
||||
return write(str(value))
|
||||
|
||||
func serialize_nil() -> Result:
|
||||
return write("null")
|
||||
|
||||
func serialize_bool(value: bool) -> Result:
|
||||
return write_string(value)
|
||||
|
||||
func serialize_int(value: int):
|
||||
return write_string(value)
|
||||
|
||||
func serialize_float(value: float) -> Result:
|
||||
return write_string(value)
|
||||
|
||||
func serialize_string(value: String):
|
||||
return write('"%s"' % value)
|
||||
|
||||
func serialize_seq(_len: int):
|
||||
return Json.SerializeSeq.new(self)
|
||||
|
||||
func serialize_dict(_len: int):
|
||||
return Json.SerializeMap.new(self)
|
||||
|
||||
func serialize_object(_name: StringName, len: int):
|
||||
return serialize_dict(len)
|
||||
|
||||
class Parser extends RefCounted:
|
||||
var de: Json.Deserializer
|
||||
var iter: PeekableIter
|
||||
|
||||
func _init(de: Json.Deserializer) -> void:
|
||||
self.de = de
|
||||
iter = de._iter
|
||||
|
||||
static func eq(a: Variant, b: Variant) -> bool:
|
||||
return a == b
|
||||
|
||||
static func _join(value: Array) -> String:
|
||||
return "".join(value)
|
||||
|
||||
static func _collect(results: Array[Result]) -> Result:
|
||||
return Result.collect_ok(results).map(_join)
|
||||
|
||||
func any() -> Result:
|
||||
match iter.peek():
|
||||
var x when x.is_some():
|
||||
return Result.ok(iter.next().unwrap())
|
||||
_: return Result.err(Error.new("eof"))
|
||||
|
||||
func char(ch: String) -> Result:
|
||||
match iter.peek():
|
||||
var x when x.filter(eq.bind(ch)).is_some(): return Result.ok(iter.next().unwrap())
|
||||
var x: return Result.err(Error.new('expecting "%s", got "%s"' % [ch, x.unwrap()]))
|
||||
|
||||
func str(value: String) -> Result:
|
||||
for i in range(0, value.length()):
|
||||
var ch = self.char(value[i])
|
||||
if ch.is_err(): return ch
|
||||
return Result.ok(value)
|
||||
|
||||
func any_of(parsers: Array[Callable]) -> Result:
|
||||
for parser in parsers:
|
||||
var result = parser.call()
|
||||
if result.is_ok(): return result
|
||||
return Result.err(Error.new('none of the provided parsers matched input'))
|
||||
|
||||
func all_of(parsers: Array) -> Result:
|
||||
var results: Array[String] = []
|
||||
for parser in parsers:
|
||||
match parser.call():
|
||||
var x when x.is_ok(): results.append(x.unwrap())
|
||||
var x: return x
|
||||
return Result.ok(results)
|
||||
|
||||
func many(parser: Callable, limit: int = 1000) -> Result:
|
||||
var results: Array[String] = []
|
||||
var value = parser.call()
|
||||
|
||||
while value.is_ok() and limit > 0:
|
||||
results.append(value.unwrap())
|
||||
value = parser.call()
|
||||
limit -= 1
|
||||
|
||||
if limit <= 0: return Result.err(Error.new("executed too many times (%s)" % limit))
|
||||
elif len(results) == 0: return Result.err(Error.new("many matched nothing"))
|
||||
else: return Result.ok(results)
|
||||
|
||||
func until(parser: Callable) -> Result:
|
||||
return many(
|
||||
func ():
|
||||
match parser.call():
|
||||
var x when x.is_err(): return any()
|
||||
_: return Result.err(null)
|
||||
)
|
||||
|
||||
func negate(parser: Callable) -> Result:
|
||||
match parser.call():
|
||||
var x when x.is_ok(): return Result.err('negated parser passed with value "%s"' % x.unwrap())
|
||||
_: return Result.Unit
|
||||
|
||||
func skip(parser: Callable) -> Result:
|
||||
return parser.call().chain(func(_v: Variant) -> Result: return Result.ok(''))
|
||||
|
||||
func any_char(chars: String) -> Result:
|
||||
for ch in chars:
|
||||
if self.char(ch).is_ok(): return Result.ok(ch)
|
||||
return Result.err(Error.new('expected any of "%s"' % chars))
|
||||
|
||||
func optional(parser: Callable, default_value: Variant = '') -> Result.Ok:
|
||||
match parser.call():
|
||||
var x when x.is_ok(): return x
|
||||
_: return Result.ok(default_value)
|
||||
|
||||
func ws() -> Result:
|
||||
return any_char(' \t')
|
||||
|
||||
func skip_ws() -> Result:
|
||||
return skip(many.bind(ws))
|
||||
|
||||
func parse_sign() -> Result:
|
||||
return any_char('+-')
|
||||
|
||||
func parse_digit() -> Result:
|
||||
return any_char('1234567890')
|
||||
|
||||
func parse_digits() -> Result:
|
||||
return many(parse_digit).map("".join)
|
||||
|
||||
func parse_integer() -> Result:
|
||||
if self.char('0').is_ok(): return Result.ok(0)
|
||||
var sign = optional(parse_sign)
|
||||
var digits = parse_digits()
|
||||
return _collect([sign, digits])
|
||||
|
||||
func parse_exponent() -> Result:
|
||||
var e = any_char('eE')
|
||||
var sign = optional(parse_sign)
|
||||
var digits = parse_digits()
|
||||
return _collect([e, sign, digits])
|
||||
|
||||
func parse_fractional() -> Result:
|
||||
var point = self.char('.')
|
||||
var digits = parse_digits()
|
||||
var exp = optional(parse_exponent)
|
||||
return _collect([point, digits, exp])
|
||||
|
||||
func parse_float() -> Result:
|
||||
var integer = parse_integer()
|
||||
var fractional = optional(parse_fractional)
|
||||
return _collect([integer, fractional])
|
||||
|
||||
func parse_string() -> Result:
|
||||
var quote = char.bind('"')
|
||||
var slash = self.char.bind('\\')
|
||||
var unescaped_quote = all_of.bind([negate.bind(slash), quote])
|
||||
|
||||
var open = skip(quote)
|
||||
var str_value = until(unescaped_quote).map(_join)
|
||||
return _collect([open, str_value])
|
||||
|
||||
class SeqAccess extends Serde.SeqAccess:
|
||||
var de: Json.Deserializer
|
||||
var first: bool = true
|
||||
var parser: Parser:
|
||||
get: return de._parser
|
||||
|
||||
func _init(de: Json.Deserializer) -> void:
|
||||
self.de = de
|
||||
|
||||
func next_element() -> Result:
|
||||
parser.skip_ws()
|
||||
|
||||
if parser.char(']').is_ok():
|
||||
return Result.ok(Option.Unit)
|
||||
|
||||
if not first and parser.char(',').is_err():
|
||||
return Result.err(Error.new('expected comma'))
|
||||
|
||||
first = false
|
||||
|
||||
parser.skip_ws()
|
||||
return de.deserialize_any(Serde.GenericVisitor.new()).map(Option.some)
|
||||
|
||||
class MapAccess extends Serde.MapAccess:
|
||||
var de: Json.Deserializer
|
||||
var first: bool = true
|
||||
|
||||
var iter: PeekableIter:
|
||||
get: return de._iter
|
||||
|
||||
var parser: Parser:
|
||||
get: return de._parser
|
||||
|
||||
func _init(de: Json.Deserializer) -> void:
|
||||
self.de = de
|
||||
|
||||
func next_key() -> Result:
|
||||
parser.skip_ws()
|
||||
|
||||
if iter.peek().filter(Parser.eq.bind('}')).is_some():
|
||||
return Result.ok(Option.Unit)
|
||||
|
||||
if not first:
|
||||
var comma = parser.char(',')
|
||||
if comma.is_err(): return comma
|
||||
|
||||
first = false
|
||||
parser.skip_ws()
|
||||
var key = de.deserialize_any(Serde.GenericVisitor.new()).map(Option.some)
|
||||
return key
|
||||
|
||||
func next_value() -> Result:
|
||||
parser.skip_ws()
|
||||
|
||||
var colon = parser.char(':')
|
||||
if colon.is_err(): return colon
|
||||
|
||||
parser.skip_ws()
|
||||
return de.deserialize_any(Serde.GenericVisitor.new()).map(Option.some)
|
||||
|
||||
class Deserializer extends Serde.Deserializer:
|
||||
var _input: String
|
||||
var _iter: PeekableIter
|
||||
var _parser: Parser
|
||||
|
||||
func _init(value: String) -> void:
|
||||
_input = value
|
||||
_iter = ListIterator.new(_input, RangeIterator.new(0, len(_input))).into_peekable()
|
||||
_parser = Parser.new(self)
|
||||
|
||||
static func from_string(value: String) -> Json.Deserializer:
|
||||
return Json.Deserializer.new(value)
|
||||
|
||||
func deserialize_any(visitor: Visitor):
|
||||
var next = _iter.peek()
|
||||
if next.is_none(): return Result.err(Error.new("eof"))
|
||||
match next.unwrap():
|
||||
'n': return deserialize_nil(visitor)
|
||||
't', 'f': return deserialize_bool(visitor)
|
||||
'"': return deserialize_string(visitor)
|
||||
'+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return deserialize_float(visitor)
|
||||
'[': return deserialize_seq(visitor)
|
||||
'{': return deserialize_dict(visitor)
|
||||
var x: return Result.err(Error.new('unexpected character "%s" at position %s' % [x, 0]))
|
||||
|
||||
func deserialize_nil(visitor: Visitor):
|
||||
_parser.skip_ws()
|
||||
match _parser.str('null'):
|
||||
var x when x.is_ok(): return Result.ok(visitor.visit_nil())
|
||||
var x: return x
|
||||
|
||||
func deserialize_bool(visitor: Visitor):
|
||||
_parser.skip_ws()
|
||||
return _parser.any_of([_parser.str.bind('true'), _parser.str.bind('false')]).map(visitor.visit_bool)
|
||||
|
||||
func deserialize_int(visitor: Visitor):
|
||||
_parser.skip_ws()
|
||||
return _parser.parse_integer().chain(Convert.FromString.to_int).map(visitor.visit_int)
|
||||
|
||||
func deserialize_float(visitor: Visitor):
|
||||
_parser.skip_ws()
|
||||
return _parser.parse_float().chain(Convert.FromString.to_float).map(visitor.visit_float)
|
||||
|
||||
func deserialize_string(visitor: Visitor):
|
||||
_parser.skip_ws()
|
||||
return _parser.parse_string().map(visitor.visit_string)
|
||||
|
||||
func _deserialize_complex(open: Callable, close: Callable, on_success: Callable):
|
||||
_parser.skip_ws()
|
||||
var open_result = open.call()
|
||||
if open_result.is_err(): return open_result
|
||||
|
||||
var value = on_success.call()
|
||||
|
||||
var close_result = close.call()
|
||||
if close_result.is_err(): return close_result
|
||||
return Result.ok(value)
|
||||
|
||||
func deserialize_seq(visitor: Visitor):
|
||||
var open = _parser.char.bind('[')
|
||||
var close = _parser.char.bind(']')
|
||||
var visit = func() -> Variant:
|
||||
return visitor.visit_seq(Json.SeqAccess.new(self))
|
||||
|
||||
return _deserialize_complex(open, close, visit)
|
||||
|
||||
func deserialize_dict(visitor: Visitor):
|
||||
var open = _parser.char.bind('{')
|
||||
var close = _parser.char.bind('}')
|
||||
var visit = func() -> Variant:
|
||||
return visitor.visit_dict(Json.MapAccess.new(self))
|
||||
|
||||
return _deserialize_complex(open, close, visit)
|
||||
|
||||
func deserialize_object(_name: StringName, _fields: Array[StringName], visitor: Visitor):
|
||||
return deserialize_dict(visitor)
|
1
godot/addons/serde/json.gd.uid
Normal file
1
godot/addons/serde/json.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://cohemdkrxsa8o
|
228
godot/addons/serde/serde.gd
Normal file
228
godot/addons/serde/serde.gd
Normal file
|
@ -0,0 +1,228 @@
|
|||
class_name Serde
|
||||
|
||||
const SerializeMethod = &"serialize"
|
||||
const DeserializeMethod = &"deserialize"
|
||||
|
||||
enum SerdeType {
|
||||
Nil,
|
||||
Bool,
|
||||
Int,
|
||||
Float,
|
||||
String,
|
||||
Seq,
|
||||
Dict,
|
||||
Object
|
||||
}
|
||||
|
||||
static func to_serde_type(godot_type: int) -> Result:
|
||||
match godot_type:
|
||||
TYPE_NIL: return Result.ok(Result.ok(SerdeType.Nil))
|
||||
TYPE_BOOL: return Result.ok(Result.ok(SerdeType.Bool))
|
||||
TYPE_INT: return Result.ok(Result.ok(SerdeType.Int))
|
||||
TYPE_FLOAT: return Result.ok(SerdeType.Float)
|
||||
TYPE_STRING: return Result.ok(SerdeType.String)
|
||||
TYPE_STRING_NAME: return Result.ok(SerdeType.String)
|
||||
TYPE_NODE_PATH: return Result.ok(SerdeType.String)
|
||||
|
||||
TYPE_VECTOR2: return Result.ok(SerdeType.Seq)
|
||||
TYPE_VECTOR2I: return Result.ok(SerdeType.Seq)
|
||||
TYPE_VECTOR3: return Result.ok(SerdeType.Seq)
|
||||
TYPE_VECTOR3I: return Result.ok(SerdeType.Seq)
|
||||
TYPE_VECTOR4I: return Result.ok(SerdeType.Seq)
|
||||
TYPE_VECTOR4I: return Result.ok(SerdeType.Seq)
|
||||
|
||||
TYPE_RECT2: return Result.ok(SerdeType.Object)
|
||||
TYPE_RECT2I: return Result.ok(SerdeType.Object)
|
||||
TYPE_AABB: return Result.ok(SerdeType.Object)
|
||||
|
||||
TYPE_TRANSFORM2D: return Result.ok(SerdeType.Object)
|
||||
TYPE_BASIS: return Result.ok(SerdeType.Object)
|
||||
TYPE_TRANSFORM3D: return Result.ok(SerdeType.Object)
|
||||
TYPE_PLANE: return Result.ok(SerdeType.Object)
|
||||
TYPE_PROJECTION: return Result.ok(SerdeType.Object)
|
||||
TYPE_QUATERNION: return Result.ok(SerdeType.Seq)
|
||||
|
||||
TYPE_COLOR: return Result.ok(SerdeType.Seq)
|
||||
TYPE_RID: return Result.ok(SerdeType.Int)
|
||||
TYPE_OBJECT: return Result.ok(SerdeType.Object)
|
||||
TYPE_DICTIONARY: return Result.ok(SerdeType.Dict)
|
||||
|
||||
TYPE_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
TYPE_PACKED_BYTE_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
TYPE_PACKED_COLOR_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
TYPE_PACKED_INT32_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
TYPE_PACKED_INT64_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
TYPE_PACKED_STRING_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
TYPE_PACKED_FLOAT32_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
TYPE_PACKED_FLOAT64_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
TYPE_PACKED_VECTOR2_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
TYPE_PACKED_VECTOR3_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
TYPE_PACKED_VECTOR4_ARRAY: return Result.ok(SerdeType.Seq)
|
||||
|
||||
TYPE_SIGNAL: return Result.err("Refusing to (de)serialize Signal")
|
||||
TYPE_CALLABLE: return Result.err("Refusing to (de)serialize Callable")
|
||||
|
||||
_: return Result.err(Error.InvalidArgument.new(godot_type))
|
||||
|
||||
static func _serialize_seq(serializer: Serializer, value: Variant) -> Variant:
|
||||
var ser = serializer.serialize_seq(len(value))
|
||||
for element in value:
|
||||
ser.serialize_element(element)
|
||||
return ser.end()
|
||||
|
||||
static func _serialize_dict(serializer: Serializer, value: Dictionary) -> Variant:
|
||||
var ser: SerializeMap = serializer.serialize_dict(value.size())
|
||||
for key in value.keys():
|
||||
ser.serialize_entry(key, value[key])
|
||||
return ser.end()
|
||||
|
||||
static func get_object_name(value: Variant) -> Option:
|
||||
var name: Option = Option.none
|
||||
|
||||
if value.has_method("get_script"):
|
||||
var script_name = value.get_script().get_global_name()
|
||||
if script_name != null: name = Option.some(script_name)
|
||||
|
||||
if name == null and value.has_method("get_class"):
|
||||
var native_name = value.get_class()
|
||||
if native_name != null: name = Option.some(native_name)
|
||||
|
||||
return name
|
||||
|
||||
static func _serialize_object(serializer: Serializer, value: Variant) -> Variant:
|
||||
var object_name = get_object_name(value).unwrap()
|
||||
var ser = serializer.serialize_object(object_name, len(value.get_property_list()))
|
||||
ser.serialize(value)
|
||||
return ser.end()
|
||||
|
||||
static func default_serialize(serializer: Serializer, value: Variant, allow_eval: bool = false) -> Variant:
|
||||
match to_serde_type(typeof(value)).unwrap():
|
||||
SerdeType.Nil: return serializer.serialize_nil()
|
||||
SerdeType.Bool: return serializer.serialize_bool(value)
|
||||
SerdeType.Int: return serializer.serialize_int(value)
|
||||
SerdeType.Float: return serializer.serialize_float(value)
|
||||
SerdeType.String: return serializer.serialize_string(value)
|
||||
SerdeType.Seq: return _serialize_seq(serializer, value)
|
||||
SerdeType.Dict: return _serialize_dict(serializer, value)
|
||||
SerdeType.Object: return _serialize_object(serializer, value)
|
||||
return Result.err("could not deserialize type %s" % typeof(value))
|
||||
|
||||
|
||||
static func serialize(serializer: Serializer, value: Variant, allow_eval: bool = false) -> Variant:
|
||||
if typeof(value) == TYPE_OBJECT and value.has_method(SerializeMethod):
|
||||
return value.call(serializer, value, allow_eval)
|
||||
else:
|
||||
return default_serialize(serializer, value, allow_eval)
|
||||
|
||||
class SerializeSeq extends RefCounted:
|
||||
func serialize_element(element: Variant): Error.NotImplemented.raise('serialize_element')
|
||||
func end(): Error.NotImplemented.raise('end')
|
||||
|
||||
class SerializeMap extends RefCounted:
|
||||
func serialize_key(key: Variant): Error.NotImplemented.raise('serialize_key')
|
||||
func serialize_value(value: Variant): Error.NotImplemented.raise('serialize_value')
|
||||
func end(): Error.NotImplemented.raise('end')
|
||||
func serialize_entry(key: Variant, value: Variant):
|
||||
return Result.collect_ok([serialize_key(key), serialize_value(value)])
|
||||
|
||||
class SerializeObject extends RefCounted:
|
||||
func serialize_field(name: StringName, value: Variant): Error.NotImplemented.raise('serialize_field')
|
||||
func serialize(object: Variant): Error.NotImplemented.raise('serialize')
|
||||
func end(): Error.NotImplemented.raise('end')
|
||||
|
||||
class Serializer extends RefCounted:
|
||||
func serialize_nil(): Error.NotImplemented.raise('serialize_nil')
|
||||
func serialize_bool(_value: bool): Error.NotImplemented.raise('serialize_bool')
|
||||
func serialize_int(_value: int): Error.NotImplemented.raise('serialize_int')
|
||||
func serialize_float(_value: float): Error.NotImplemented.raise('serialize_float')
|
||||
func serialize_string(_value: String): Error.NotImplemented.raise('serialize_string')
|
||||
func serialize_seq(_len: int): Error.NotImplemented.raise('serialize_string')
|
||||
func serialize_dict(_len: int): Error.NotImplemented.raise('serialize_string')
|
||||
func serialize_object(_name: StringName, _len: int): Error.NotImplemented.raise('serialize_string')
|
||||
|
||||
class Visitor extends RefCounted:
|
||||
func visit_nil(): Error.NotImplemented.raise('visit_nil')
|
||||
func visit_bool(_value: bool): Error.NotImplemented.raise('visit_bool')
|
||||
func visit_int(_value: int): Error.NotImplemented.raise('visit_int')
|
||||
func visit_float(_value: float): Error.NotImplemented.raise('visit_float')
|
||||
func visit_string(_value: String): Error.NotImplemented.raise('visit_string')
|
||||
func visit_seq(_access: SeqAccess): Error.NotImplemented.raise('visit_seq')
|
||||
func visit_dict(_access: MapAccess): Error.NotImplemented.raise('visit_dict')
|
||||
|
||||
class GenericVisitor extends Visitor:
|
||||
func visit_nil(): return null
|
||||
func visit_bool(value: bool):
|
||||
print('bool', value)
|
||||
return value
|
||||
func visit_int(value: int):
|
||||
print('int', value)
|
||||
return value
|
||||
func visit_float(value: float):
|
||||
print('float', value)
|
||||
return value
|
||||
func visit_string(value: String):
|
||||
print('str', value)
|
||||
return value
|
||||
func visit_seq(access: SeqAccess):
|
||||
print('seq', access)
|
||||
return access.collect()
|
||||
func visit_dict(access: MapAccess):
|
||||
var a = access.collect()
|
||||
print('dict', a)
|
||||
return a
|
||||
|
||||
class AccessIterable extends Iterator:
|
||||
var _next: Callable
|
||||
|
||||
func _init(next: Callable) -> void:
|
||||
_next = next
|
||||
|
||||
func next() -> Option:
|
||||
return _next.call().to_option().flatten()
|
||||
|
||||
class SeqAccess extends RefCounted:
|
||||
func next_element(): Error.NotImplemented.raise('next_element')
|
||||
|
||||
func iterate() -> AccessIterable:
|
||||
return AccessIterable.new(next_element)
|
||||
|
||||
func collect() -> Array:
|
||||
var list = []
|
||||
|
||||
for item in iterate():
|
||||
list.append(item)
|
||||
|
||||
return list
|
||||
|
||||
class MapAccess extends RefCounted:
|
||||
func next_key(): Error.NotImplemented.raise('next_key')
|
||||
func next_value(): Error.NotImplemented.raise('next_value')
|
||||
|
||||
func next_entry() -> Result:
|
||||
var key = next_key()
|
||||
var val = next_value()
|
||||
return Result.collect_ok([key, val])
|
||||
|
||||
func iterate() -> AccessIterable:
|
||||
return AccessIterable.new(next_entry)
|
||||
|
||||
func collect() -> Dictionary:
|
||||
var dict: Dictionary = {}
|
||||
|
||||
print('collecting map')
|
||||
for entry in iterate():
|
||||
print('entry', entry)
|
||||
dict.set(entry[0], entry[1])
|
||||
|
||||
return dict
|
||||
|
||||
class Deserializer extends RefCounted:
|
||||
func deserialize_any(_visitor: Visitor): Error.NotImplemented.raise('deserialize_any')
|
||||
func deserialize_nil(_visitor: Visitor): Error.NotImplemented.raise('deserialize_nil')
|
||||
func deserialize_bool(_visitor: Visitor): Error.NotImplemented.raise('deserialize_bool')
|
||||
func deserialize_int(_visitor: Visitor): Error.NotImplemented.raise('deserialize_int')
|
||||
func deserialize_float(_visitor: Visitor): Error.NotImplemented.raise('deserialize_float')
|
||||
func deserialize_string(_visitor: Visitor): Error.NotImplemented.raise('deserialize_string')
|
||||
func deserialize_seq(_visitor: Visitor): Error.NotImplemented.raise('deserialize_seq')
|
||||
func deserialize_dict(_visitor: Visitor): Error.NotImplemented.raise('deserialize_dict')
|
||||
func deserialize_object(_name: StringName, _fields: Array[StringName], _visitor: Visitor): Error.NotImplemented.raise('deserialize_object')
|
1
godot/addons/serde/serde.gd.uid
Normal file
1
godot/addons/serde/serde.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://clfdg2pslks74
|
BIN
godot/assets/Glock 17 Gen 4/Glock17.fbx
Normal file
BIN
godot/assets/Glock 17 Gen 4/Glock17.fbx
Normal file
Binary file not shown.
38
godot/assets/Glock 17 Gen 4/Glock17.fbx.import
Normal file
38
godot/assets/Glock 17 Gen 4/Glock17.fbx.import
Normal file
|
@ -0,0 +1,38 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://mii66yx7ep0m"
|
||||
path="res://.godot/imported/Glock17.fbx-21a41422b406849d0ac156c344e49ded.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/Glock 17 Gen 4/Glock17.fbx"
|
||||
dest_files=["res://.godot/imported/Glock17.fbx-21a41422b406849d0ac156c344e49ded.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=true
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
fbx/importer=0
|
||||
fbx/allow_geometry_helper_nodes=false
|
||||
fbx/embedded_image_handling=1
|
BIN
godot/assets/Glock 17 Gen 4/MagazineOnly.blend
Normal file
BIN
godot/assets/Glock 17 Gen 4/MagazineOnly.blend
Normal file
Binary file not shown.
53
godot/assets/Glock 17 Gen 4/MagazineOnly.blend.import
Normal file
53
godot/assets/Glock 17 Gen 4/MagazineOnly.blend.import
Normal file
|
@ -0,0 +1,53 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://bsamn3hu8mypn"
|
||||
path="res://.godot/imported/MagazineOnly.blend-03c199d61b3da2f3a886fbf595d4fdb8.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/Glock 17 Gen 4/MagazineOnly.blend"
|
||||
dest_files=["res://.godot/imported/MagazineOnly.blend-03c199d61b3da2f3a886fbf595d4fdb8.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
blender/nodes/visible=0
|
||||
blender/nodes/active_collection_only=false
|
||||
blender/nodes/punctual_lights=true
|
||||
blender/nodes/cameras=true
|
||||
blender/nodes/custom_properties=true
|
||||
blender/nodes/modifiers=1
|
||||
blender/meshes/colors=false
|
||||
blender/meshes/uvs=true
|
||||
blender/meshes/normals=true
|
||||
blender/meshes/export_geometry_nodes_instances=false
|
||||
blender/meshes/tangents=true
|
||||
blender/meshes/skins=2
|
||||
blender/meshes/export_bones_deforming_mesh_only=false
|
||||
blender/materials/unpack_enabled=true
|
||||
blender/materials/export_materials=1
|
||||
blender/animation/limit_playback=true
|
||||
blender/animation/always_sample=true
|
||||
blender/animation/group_tracks=true
|
BIN
godot/assets/Glock 17 Gen 4/MagazineOnly.fbx
Normal file
BIN
godot/assets/Glock 17 Gen 4/MagazineOnly.fbx
Normal file
Binary file not shown.
38
godot/assets/Glock 17 Gen 4/MagazineOnly.fbx.import
Normal file
38
godot/assets/Glock 17 Gen 4/MagazineOnly.fbx.import
Normal file
|
@ -0,0 +1,38 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://b1flnaqxpsntg"
|
||||
path="res://.godot/imported/MagazineOnly.fbx-c5c1e9faa3577f6cfda078f5a38aa9af.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/Glock 17 Gen 4/MagazineOnly.fbx"
|
||||
dest_files=["res://.godot/imported/MagazineOnly.fbx-c5c1e9faa3577f6cfda078f5a38aa9af.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=true
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
fbx/importer=0
|
||||
fbx/allow_geometry_helper_nodes=false
|
||||
fbx/embedded_image_handling=1
|
BIN
godot/assets/Glock 17 Gen 4/Main.blend
Normal file
BIN
godot/assets/Glock 17 Gen 4/Main.blend
Normal file
Binary file not shown.
53
godot/assets/Glock 17 Gen 4/Main.blend.import
Normal file
53
godot/assets/Glock 17 Gen 4/Main.blend.import
Normal file
|
@ -0,0 +1,53 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://clc8ic0w44pqb"
|
||||
path="res://.godot/imported/Main.blend-949e4928fb46c2598347c692921a4209.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/Glock 17 Gen 4/Main.blend"
|
||||
dest_files=["res://.godot/imported/Main.blend-949e4928fb46c2598347c692921a4209.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
blender/nodes/visible=0
|
||||
blender/nodes/active_collection_only=false
|
||||
blender/nodes/punctual_lights=true
|
||||
blender/nodes/cameras=true
|
||||
blender/nodes/custom_properties=true
|
||||
blender/nodes/modifiers=1
|
||||
blender/meshes/colors=false
|
||||
blender/meshes/uvs=true
|
||||
blender/meshes/normals=true
|
||||
blender/meshes/export_geometry_nodes_instances=false
|
||||
blender/meshes/tangents=true
|
||||
blender/meshes/skins=2
|
||||
blender/meshes/export_bones_deforming_mesh_only=false
|
||||
blender/materials/unpack_enabled=true
|
||||
blender/materials/export_materials=1
|
||||
blender/animation/limit_playback=true
|
||||
blender/animation/always_sample=true
|
||||
blender/animation/group_tracks=true
|
BIN
godot/assets/Glock 17 Gen 4/Main.glb
Normal file
BIN
godot/assets/Glock 17 Gen 4/Main.glb
Normal file
Binary file not shown.
37
godot/assets/Glock 17 Gen 4/Main.glb.import
Normal file
37
godot/assets/Glock 17 Gen 4/Main.glb.import
Normal file
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://5a023hrws3gx"
|
||||
path="res://.godot/imported/Main.glb-313ef174cbfc4d23192b83a144919b40.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/Glock 17 Gen 4/Main.glb"
|
||||
dest_files=["res://.godot/imported/Main.glb-313ef174cbfc4d23192b83a144919b40.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=1
|
||||
gltf/embedded_image_handling=1
|
BIN
godot/assets/Glock 17 Gen 4/MainRender.png
Normal file
BIN
godot/assets/Glock 17 Gen 4/MainRender.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 MiB |
34
godot/assets/Glock 17 Gen 4/MainRender.png.import
Normal file
34
godot/assets/Glock 17 Gen 4/MainRender.png.import
Normal file
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cnqli7mte5jsn"
|
||||
path="res://.godot/imported/MainRender.png-809411c3f2bc242eb5c881659d87b16b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/Glock 17 Gen 4/MainRender.png"
|
||||
dest_files=["res://.godot/imported/MainRender.png-809411c3f2bc242eb5c881659d87b16b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
godot/assets/level.glb
Normal file
BIN
godot/assets/level.glb
Normal file
Binary file not shown.
37
godot/assets/level.glb.import
Normal file
37
godot/assets/level.glb.import
Normal file
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://cwrgvwx3lfwf6"
|
||||
path="res://.godot/imported/level.glb-dadcc56a2e5f0c7946f5dd2ed4295803.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/level.glb"
|
||||
dest_files=["res://.godot/imported/level.glb-dadcc56a2e5f0c7946f5dd2ed4295803.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=1
|
||||
gltf/embedded_image_handling=1
|
BIN
godot/assets/player.glb
Normal file
BIN
godot/assets/player.glb
Normal file
Binary file not shown.
9035
godot/assets/player.glb.import
Normal file
9035
godot/assets/player.glb.import
Normal file
File diff suppressed because it is too large
Load diff
1
godot/icon.svg
Normal file
1
godot/icon.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
|
After Width: | Height: | Size: 994 B |
37
godot/icon.svg.import
Normal file
37
godot/icon.svg.import
Normal file
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://djmxd4580q6xs"
|
||||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.svg"
|
||||
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
57
godot/project.godot
Normal file
57
godot/project.godot
Normal file
|
@ -0,0 +1,57 @@
|
|||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=5
|
||||
|
||||
[application]
|
||||
|
||||
config/name="signalis-eb"
|
||||
run/main_scene="uid://dttyp3682enn7"
|
||||
config/features=PackedStringArray("4.4", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[global_group]
|
||||
|
||||
persist=""
|
||||
|
||||
[input]
|
||||
|
||||
move_up={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_down={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_left={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_right={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
run={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
interact={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[layer_names]
|
||||
|
||||
3d_physics/layer_2="interaction"
|
16
godot/rust.gdextension
Normal file
16
godot/rust.gdextension
Normal file
|
@ -0,0 +1,16 @@
|
|||
[configuration]
|
||||
entry_symbol = "gdext_rust_init"
|
||||
compatibility_minimum = 4.1
|
||||
reloadable = true
|
||||
|
||||
[libraries]
|
||||
linux.debug.x86_64 = "res://../rust/target/debug/libsignalis_rs.so"
|
||||
linux.release.x86_64 = "res://../rust/target/release/libsignalis_rs.so"
|
||||
windows.debug.x86_64 = "res://../rust/target/debug/signalis_rs.dll"
|
||||
windows.release.x86_64 = "res://../rust/target/release/signalis_rs.dll"
|
||||
macos.debug = "res://../rust/target/debug/libsignalis_rs.dylib"
|
||||
macos.release = "res://../rust/target/release/libsignalis_rs.dylib"
|
||||
macos.debug.arm64 = "res://../rust/target/debug/libsignalis_rs.dylib"
|
||||
macos.release.arm64 = "res://../rust/target/release/libsignalis_rs.dylib"
|
||||
|
||||
|
1
godot/rust.gdextension.uid
Normal file
1
godot/rust.gdextension.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://vb34isrum50a
|
80
godot/scenes/level.tscn
Normal file
80
godot/scenes/level.tscn
Normal file
|
@ -0,0 +1,80 @@
|
|||
[gd_scene load_steps=9 format=3 uid="uid://dttyp3682enn7"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://crbrniwi6kd3p" path="res://scenes/player.tscn" id="1_2q6dc"]
|
||||
[ext_resource type="Script" uid="uid://ds8lef4lc6xuj" path="res://src/door.gd" id="2_w8frs"]
|
||||
[ext_resource type="Script" uid="uid://dyghf5fq7s72x" path="res://src/interactable.gd" id="3_w8frs"]
|
||||
[ext_resource type="Script" uid="uid://pdpejp2xor23" path="res://src/persistence.gd" id="4_mx8sn"]
|
||||
|
||||
[sub_resource type="PlaneMesh" id="PlaneMesh_rd3vj"]
|
||||
|
||||
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_w7c3h"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_w8frs"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_mx8sn"]
|
||||
size = Vector3(2, 2.5, 0.5)
|
||||
|
||||
[node name="Node3D" type="Node3D"]
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(50, 0, 0, 0, 50, 0, 0, 0, 50, 0, 0, 0)
|
||||
mesh = SubResource("PlaneMesh_rd3vj")
|
||||
|
||||
[node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"]
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"]
|
||||
shape = SubResource("WorldBoundaryShape3D_w7c3h")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("1_2q6dc")]
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.866025, 0.5, 0, -0.5, 0.866025, 0, 10, 15.3526)
|
||||
projection = 1
|
||||
size = 15.0
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 10, 0)
|
||||
|
||||
[node name="Door" type="StaticBody3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 5)
|
||||
collision_layer = 3
|
||||
script = ExtResource("2_w8frs")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Door"]
|
||||
transform = Transform3D(2, 0, 0, 0, 2.5, 0, 0, 0, 0.5, 0, 1.25, 0)
|
||||
mesh = SubResource("BoxMesh_w8frs")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Door"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.25, 0)
|
||||
shape = SubResource("BoxShape3D_mx8sn")
|
||||
|
||||
[node name="Interactable" type="Node3D" parent="Door"]
|
||||
script = ExtResource("3_w8frs")
|
||||
|
||||
[node name="Control" type="Control" parent="."]
|
||||
layout_mode = 3
|
||||
anchors_preset = 0
|
||||
offset_right = 40.0
|
||||
offset_bottom = 40.0
|
||||
|
||||
[node name="Persistence" type="Node" parent="Control"]
|
||||
script = ExtResource("4_mx8sn")
|
||||
metadata/_custom_type_script = "uid://pdpejp2xor23"
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Control"]
|
||||
layout_mode = 0
|
||||
offset_right = 40.0
|
||||
offset_bottom = 40.0
|
||||
|
||||
[node name="SaveButton" type="Button" parent="Control/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Save"
|
||||
|
||||
[node name="LoadButton" type="Button" parent="Control/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Load
|
||||
"
|
||||
|
||||
[connection signal="interacted" from="Door/Interactable" to="Door" method="_on_interact"]
|
||||
[connection signal="pressed" from="Control/HBoxContainer/SaveButton" to="Control/Persistence" method="save"]
|
||||
[connection signal="pressed" from="Control/HBoxContainer/LoadButton" to="Control/Persistence" method="load"]
|
143
godot/scenes/player.tscn
Normal file
143
godot/scenes/player.tscn
Normal file
File diff suppressed because one or more lines are too long
5
godot/scenes/player_mesh.tscn
Normal file
5
godot/scenes/player_mesh.tscn
Normal file
|
@ -0,0 +1,5 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://dpmbimh6m4ari"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://05nocsdvnsy5" path="res://assets/player.glb" id="1_mvwvq"]
|
||||
|
||||
[node name="Mesh" instance=ExtResource("1_mvwvq")]
|
8
godot/src/door.gd
Normal file
8
godot/src/door.gd
Normal file
|
@ -0,0 +1,8 @@
|
|||
class_name Door extends StaticBody3D
|
||||
|
||||
const Interactor = preload("res://src/interactor.gd")
|
||||
|
||||
@export var locked: bool = false
|
||||
|
||||
func _on_interact(_interactor: Interactor):
|
||||
print('interacting!! with the door!!')
|
1
godot/src/door.gd.uid
Normal file
1
godot/src/door.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://ds8lef4lc6xuj
|
1
godot/src/file.gd.uid
Normal file
1
godot/src/file.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://xwi0ehjmeqdu
|
7
godot/src/interactable.gd
Normal file
7
godot/src/interactable.gd
Normal file
|
@ -0,0 +1,7 @@
|
|||
extends Node3D
|
||||
|
||||
const Interactor = preload("res://src/interactor.gd")
|
||||
signal interacted(interactor: Interactor)
|
||||
|
||||
func interact(interactor: Node):
|
||||
interacted.emit(interactor)
|
1
godot/src/interactable.gd.uid
Normal file
1
godot/src/interactable.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://dyghf5fq7s72x
|
72
godot/src/interactor.gd
Normal file
72
godot/src/interactor.gd
Normal file
|
@ -0,0 +1,72 @@
|
|||
extends Node3D
|
||||
|
||||
const Interactable = preload("res://src/interactable.gd")
|
||||
const EnterSignals: Array[String] = ["area_entered", "body_entered"]
|
||||
const ExitSignals: Array[String] = ["area_exited", "body_exited"]
|
||||
|
||||
@export var area: Area3D
|
||||
|
||||
class InteractableNode:
|
||||
var _body: CollisionObject3D
|
||||
var _interactable: Interactable
|
||||
|
||||
var global_position: Vector3:
|
||||
get: return _body.global_position
|
||||
|
||||
func _init(body: CollisionObject3D, interactable: Interactable):
|
||||
_body = body
|
||||
_interactable = interactable
|
||||
|
||||
func interact(interactor: Node):
|
||||
_interactable.interact(interactor)
|
||||
|
||||
func squared_distance_to(b: InteractableNode) -> float:
|
||||
return global_position.distance_squared_to(b.global_position)
|
||||
|
||||
var interactables: Array[InteractableNode] = []
|
||||
var _sorted: bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
_connect_many(area, EnterSignals, _on_object_entered)
|
||||
_connect_many(area, ExitSignals, _on_object_exited)
|
||||
|
||||
func _connect_many(node: Node, signals: Array[String], fn: Callable):
|
||||
for signal_name in signals:
|
||||
node.connect(signal_name, fn)
|
||||
|
||||
func _on_object_entered(object: CollisionObject3D):
|
||||
_sorted = false
|
||||
var child = NodeExt.find_child_variant(object, Interactable)
|
||||
if child.is_some():
|
||||
interactables.append(InteractableNode.new(object, child.unwrap() as Interactable))
|
||||
|
||||
func is_same_object(object: CollisionObject3D, node: InteractableNode) -> bool:
|
||||
return object == node._body
|
||||
|
||||
func _on_object_exited(object: CollisionObject3D):
|
||||
var index = interactables.find_custom(
|
||||
func(node): return is_same_object(object, node)
|
||||
)
|
||||
|
||||
if index >= 0:
|
||||
interactables.remove_at(index)
|
||||
|
||||
func _distance_from(node: InteractableNode) -> float:
|
||||
return global_position.distance_squared_to(node.global_position)
|
||||
|
||||
func _distance_compare(a: InteractableNode, b: InteractableNode):
|
||||
return _distance_from(a) > _distance_from(b)
|
||||
|
||||
func _sort_by_distance():
|
||||
interactables.sort_custom(_distance_compare)
|
||||
_sorted = true
|
||||
|
||||
func interact(interactable: InteractableNode):
|
||||
interactable.interact(self)
|
||||
|
||||
func interact_nearest():
|
||||
if not _sorted:
|
||||
_sort_by_distance()
|
||||
|
||||
if len(interactables) > 0:
|
||||
return interact(interactables[0])
|
1
godot/src/interactor.gd.uid
Normal file
1
godot/src/interactor.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://c3wlcxy4vnm2i
|
40
godot/src/node_ext.gd
Normal file
40
godot/src/node_ext.gd
Normal file
|
@ -0,0 +1,40 @@
|
|||
class_name NodeExt
|
||||
extends Object
|
||||
|
||||
class NodeChildIterator:
|
||||
var _node: Node
|
||||
var _include_internal: bool
|
||||
var _index: int
|
||||
var _length: int
|
||||
|
||||
func _init(node: Node, include_internal: bool) -> void:
|
||||
_node = node
|
||||
_include_internal = include_internal
|
||||
_index = 0
|
||||
_length = node.get_child_count(include_internal)
|
||||
|
||||
func _continue() -> bool:
|
||||
return (_index < _length)
|
||||
|
||||
func _iter_init(_iter: Array) -> bool:
|
||||
_index = 0
|
||||
return _continue()
|
||||
|
||||
func _iter_next(_iter: Array) -> bool:
|
||||
_index += 1
|
||||
return _continue()
|
||||
|
||||
func _iter_get(_iter: Variant) -> Variant:
|
||||
return _node.get_child(_index, _include_internal)
|
||||
|
||||
static func find_child(node: Node, predicate: Callable, include_internal: bool = false) -> Option:
|
||||
for child in NodeChildIterator.new(node, include_internal):
|
||||
if predicate.call(child):
|
||||
return Option.some(child)
|
||||
return Option.none
|
||||
|
||||
static func find_child_variant(node: Node, variant: Variant, include_internal: bool = false) -> Option:
|
||||
for child in NodeChildIterator.new(node, include_internal):
|
||||
if is_instance_of(child, variant):
|
||||
return Option.some(child)
|
||||
return Option.none
|
1
godot/src/node_ext.gd.uid
Normal file
1
godot/src/node_ext.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://bi44258j42pt4
|
86
godot/src/persistence.gd
Normal file
86
godot/src/persistence.gd
Normal file
|
@ -0,0 +1,86 @@
|
|||
class_name Persistence extends Node
|
||||
|
||||
@export var path = "user://saves/data.sav"
|
||||
@export var group_name = "persist"
|
||||
|
||||
const PersistenceOptionsMethod = "_get_persistence_options"
|
||||
const SaveMethod = "on_save"
|
||||
const OnBeforeLoadMethod = "on_before_load"
|
||||
const LoadMethod = "on_load"
|
||||
|
||||
# TODO: binary (de)serialization
|
||||
|
||||
static func get_instance_data(node: Node):
|
||||
return {
|
||||
path = node.get_path(),
|
||||
scene = node.scene_file_path,
|
||||
data = JSON.from_native(node.call(SaveMethod))
|
||||
}
|
||||
|
||||
func save() -> Result:
|
||||
DirAccess.make_dir_recursive_absolute(path.get_base_dir())
|
||||
var file = FileAccess.open(path, FileAccess.WRITE)
|
||||
var nodes = get_tree().get_nodes_in_group(group_name)
|
||||
|
||||
for node in nodes:
|
||||
if node.scene_file_path.is_empty():
|
||||
push_warning('"%s" is not instanced, skipping' % node.name)
|
||||
continue
|
||||
|
||||
if not node.has_method("on_save"):
|
||||
push_warning('"%s" does not have a "%s" method, skipping' % [node.name, SaveMethod])
|
||||
continue
|
||||
|
||||
var data = get_instance_data(node)
|
||||
file.store_line(Json.stringify(data))
|
||||
|
||||
return Result.Unit
|
||||
|
||||
func _get_or_add(instance_data: Dictionary) -> Variant:
|
||||
var node_path: NodePath = instance_data['path']
|
||||
var scene_path = instance_data['scene']
|
||||
var node = get_node_or_null(node_path)
|
||||
|
||||
if node.is_queued_for_deletion():
|
||||
await node.tree_exited
|
||||
node = null
|
||||
|
||||
if node == null:
|
||||
node = load(scene_path).instantiate()
|
||||
var parent = node_path.slice(0, node_path.get_name_count() - 1)
|
||||
get_node(parent).call_deferred('add_child', node)
|
||||
|
||||
return node
|
||||
|
||||
func load(fail_on_err: bool = false) -> Result:
|
||||
if not FileAccess.file_exists(path):
|
||||
return Result.err('ENOENT: "%s" does not exist' % path)
|
||||
|
||||
get_tree().call_group(group_name, OnBeforeLoadMethod)
|
||||
|
||||
var file = FileAccess.open(path, FileAccess.READ)
|
||||
|
||||
var length = file.get_length()
|
||||
while file.get_position() < length:
|
||||
var line = file.get_line()
|
||||
var result = Json.parse_string(line)
|
||||
|
||||
if result.is_err():
|
||||
if fail_on_err: return result
|
||||
else:
|
||||
push_error('could not read save entry. error: "%s"' % result.unwrap_err())
|
||||
continue
|
||||
|
||||
var save_data = result.unwrap()
|
||||
|
||||
var instance = await _get_or_add(save_data)
|
||||
|
||||
if not instance.has_method(LoadMethod):
|
||||
push_warning('"%s" does not have a "%s" method' % [instance.name, LoadMethod])
|
||||
instance.queue_free()
|
||||
continue
|
||||
|
||||
var instance_data = JSON.to_native(save_data.data)
|
||||
instance.call(LoadMethod, instance_data)
|
||||
|
||||
return Result.Unit
|
1
godot/src/persistence.gd.uid
Normal file
1
godot/src/persistence.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://pdpejp2xor23
|
38
godot/src/player.gd
Normal file
38
godot/src/player.gd
Normal file
|
@ -0,0 +1,38 @@
|
|||
class_name Player extends CharacterBody3D
|
||||
|
||||
@export var walk_speed: float = 4.0
|
||||
@export var run_speed: float = 6.0
|
||||
|
||||
@onready var input = $Input
|
||||
@onready var interactor = $Interactor
|
||||
|
||||
var is_carrying_item = false
|
||||
|
||||
func _ready() -> void:
|
||||
input.connect("interact", _on_interact)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
move_and_rotate(delta)
|
||||
|
||||
func move_and_rotate(_delta: float):
|
||||
var speed = run_speed if input.is_running else walk_speed
|
||||
velocity = input.next_velocity(speed)
|
||||
if !velocity.is_zero_approx():
|
||||
look_at(global_position + velocity, Vector3.UP, true)
|
||||
move_and_slide()
|
||||
|
||||
func _on_interact():
|
||||
interactor.interact_nearest()
|
||||
|
||||
func on_save():
|
||||
return {
|
||||
position = position,
|
||||
rotation = rotation
|
||||
}
|
||||
|
||||
func on_before_load():
|
||||
pass
|
||||
|
||||
func on_load(data: Dictionary):
|
||||
position = data.position
|
||||
rotation = data.rotation
|
1
godot/src/player.gd.uid
Normal file
1
godot/src/player.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://50vv0ta67tgl
|
28
godot/src/player_input.gd
Normal file
28
godot/src/player_input.gd
Normal file
|
@ -0,0 +1,28 @@
|
|||
class_name PlayerInput extends Node
|
||||
|
||||
signal run
|
||||
signal interact
|
||||
|
||||
var is_running: bool = false
|
||||
var is_interacting: bool = false
|
||||
|
||||
var movement_dir: Vector2:
|
||||
get: return Input.get_vector(
|
||||
'move_left', 'move_right',
|
||||
'move_up', 'move_down'
|
||||
).normalized()
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
var running = Input.is_action_pressed("run")
|
||||
if running != is_running:
|
||||
run.emit(running)
|
||||
is_running = running
|
||||
|
||||
var was_interacting = is_interacting
|
||||
is_interacting = Input.is_action_pressed("interact")
|
||||
|
||||
if is_interacting and not was_interacting:
|
||||
interact.emit()
|
||||
|
||||
func next_velocity(speed: float, dir: Vector2 = movement_dir) -> Vector3:
|
||||
return Vector3(dir.x, 0, dir.y) * speed
|
1
godot/src/player_input.gd.uid
Normal file
1
godot/src/player_input.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://cngjp2wws4ld2
|
1
rust/.gitignore
vendored
Normal file
1
rust/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
261
rust/Cargo.lock
generated
Normal file
261
rust/Cargo.lock
generated
Normal file
|
@ -0,0 +1,261 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdextension-api"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ec0a03c8f9c91e3d8eb7ca56dea81c7248c03826dd3f545f33cd22ef275d4d1"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.30.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b46b9ca4690308844c644e7c634d68792467260e051c8543e0c7871662b3ba7"
|
||||
|
||||
[[package]]
|
||||
name = "godot"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a39ac85e71bb02a09badd538b76e11945bf7ee5e02c30d46e38e7d3dac33763"
|
||||
dependencies = [
|
||||
"godot-core",
|
||||
"godot-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "godot-bindings"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "619afb7eda5a0f3e496d651b858ec7c03acf483a7cd36b7c4a7c0df96ae1a50e"
|
||||
dependencies = [
|
||||
"gdextension-api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "godot-cell"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c198c3760f5f2edb852ebdbcc83f948fa1436d6deb2000bbdadb99fc6858bfd"
|
||||
|
||||
[[package]]
|
||||
name = "godot-codegen"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7673ba4ef6a69205dc93909c5c5fc15f3c9159e1829b1ff1e7c4a94ba31f93f3"
|
||||
dependencies = [
|
||||
"godot-bindings",
|
||||
"heck",
|
||||
"nanoserde",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "godot-core"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1124ea2c9753d593691d16864edb57552f9321333a286f802932e3d8a56d70f3"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"godot-bindings",
|
||||
"godot-cell",
|
||||
"godot-codegen",
|
||||
"godot-ffi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "godot-ffi"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec84cddb0e58a8ad3639e88ba1f06a8350ddff4cc368a7d78c1cff1b46e7ff0a"
|
||||
dependencies = [
|
||||
"godot-bindings",
|
||||
"godot-codegen",
|
||||
"godot-macros",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "godot-macros"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8a41150c0d205c7b671402a3f06f1b89910d90c513a0442fa4b2b8ea6665969"
|
||||
dependencies = [
|
||||
"godot-bindings",
|
||||
"libc",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"venial",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "nanoserde"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a36fb3a748a4c9736ed7aeb5f2dfc99665247f1ce306abbddb2bf0ba2ac530a4"
|
||||
dependencies = [
|
||||
"nanoserde-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanoserde-derive"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a846cbc04412cf509efcd8f3694b114fc700a035fb5a37f21517f9fb019f1ebc"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signalis-rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"godot",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "venial"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a42528baceab6c7784446df2a10f4185078c39bf73dc614f154353f1a6b1229"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
12
rust/Cargo.toml
Normal file
12
rust/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "signalis-rs"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
godot = "0.3.0"
|
||||
serde = "1.0.219"
|
||||
serde_json = "1.0.140"
|
8
rust/src/lib.rs
Normal file
8
rust/src/lib.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use godot::prelude::*;
|
||||
|
||||
mod persist;
|
||||
|
||||
struct GodotExtension;
|
||||
|
||||
#[gdextension]
|
||||
unsafe impl ExtensionLibrary for GodotExtension {}
|
11
rust/src/persist.rs
Normal file
11
rust/src/persist.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
use godot::prelude::*;
|
||||
|
||||
#[derive(GodotClass)]
|
||||
pub struct Persist;
|
||||
|
||||
#[godot_api]
|
||||
impl IRefCounted for Persist {
|
||||
fn init(base: Base<RefCounted>) -> Self {
|
||||
Persist
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue