Project commit
This commit is contained in:
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/
|
34
BSON Examples/dunk.gd
Normal file
34
BSON Examples/dunk.gd
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
extends Control
|
||||||
|
|
||||||
|
|
||||||
|
# These are set in dunk.tscn in the root node properties.
|
||||||
|
@export var JSONEditor: CodeEdit
|
||||||
|
@export var OutputLabel: Label
|
||||||
|
@export var CopyPopup: PopupPanel
|
||||||
|
|
||||||
|
|
||||||
|
func _on_button_pressed() -> void:
|
||||||
|
var n_json = JSON.parse_string(JSONEditor.text) # Could be Dictionary or null
|
||||||
|
if !n_json: return # JSON parse failed
|
||||||
|
|
||||||
|
var b_json := BSON.to_bson(n_json)
|
||||||
|
var d_json := BSON.from_bson(b_json)
|
||||||
|
|
||||||
|
OutputLabel.text = ("SERIALIZED BSON:\n"
|
||||||
|
+ str(b_json)
|
||||||
|
+ "\nDESERIALIZED JSON:\n"
|
||||||
|
+ str(d_json))
|
||||||
|
|
||||||
|
func _on_copy_pressed() -> void:
|
||||||
|
DisplayServer.clipboard_set(OutputLabel.text)
|
||||||
|
CopyPopup.show()
|
||||||
|
|
||||||
|
var timer := Timer.new()
|
||||||
|
timer.autostart = true
|
||||||
|
timer.one_shot = true
|
||||||
|
timer.wait_time = 1.5
|
||||||
|
add_child(timer)
|
||||||
|
|
||||||
|
await timer.timeout
|
||||||
|
timer.queue_free()
|
||||||
|
CopyPopup.hide()
|
131
BSON Examples/dunk.tscn
Normal file
131
BSON Examples/dunk.tscn
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://ckdfb5ggwslbk"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://BSON Examples/dunk.gd" id="1_p38ab"]
|
||||||
|
|
||||||
|
[node name="Dunk" type="Control" node_paths=PackedStringArray("JSONEditor", "OutputLabel", "CopyPopup")]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_p38ab")
|
||||||
|
JSONEditor = NodePath("Panel/JSONEdit")
|
||||||
|
OutputLabel = NodePath("Panel/Scroll/Output")
|
||||||
|
CopyPopup = NodePath("CopyPopup")
|
||||||
|
|
||||||
|
[node name="Panel" type="Panel" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 119.0
|
||||||
|
offset_top = 67.0
|
||||||
|
offset_right = -119.0
|
||||||
|
offset_bottom = -67.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="JSONEdit" type="CodeEdit" parent="Panel"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 86.0
|
||||||
|
offset_top = 14.0
|
||||||
|
offset_right = -86.0
|
||||||
|
offset_bottom = -277.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
text = "{
|
||||||
|
\"username\": \"johndoe\",
|
||||||
|
\"firstname\": \"John\",
|
||||||
|
\"lastname\": \"Doe\",
|
||||||
|
\"email\": {
|
||||||
|
\"adress\": \"john-doe@example.com\",
|
||||||
|
\"verified\": true
|
||||||
|
},
|
||||||
|
\"age\": 32,
|
||||||
|
\"phone\": {
|
||||||
|
\"number\": \"0123456789\",
|
||||||
|
\"verified\": false
|
||||||
|
},
|
||||||
|
\"assets\": [
|
||||||
|
\"foo\",
|
||||||
|
\"bar\",
|
||||||
|
42,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
3.14159265,
|
||||||
|
\"baz\"
|
||||||
|
]
|
||||||
|
}"
|
||||||
|
middle_mouse_paste_enabled = false
|
||||||
|
minimap_draw = true
|
||||||
|
gutters_draw_line_numbers = true
|
||||||
|
indent_automatic = true
|
||||||
|
auto_brace_completion_enabled = true
|
||||||
|
auto_brace_completion_highlight_matching = true
|
||||||
|
|
||||||
|
[node name="Dunk" type="Button" parent="Panel"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 364.0
|
||||||
|
offset_top = 243.0
|
||||||
|
offset_right = -364.0
|
||||||
|
offset_bottom = -228.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
text = "Run"
|
||||||
|
|
||||||
|
[node name="Copy" type="Button" parent="Panel"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 364.0
|
||||||
|
offset_top = 291.0
|
||||||
|
offset_right = -364.0
|
||||||
|
offset_bottom = -180.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
text = "Copy Output
|
||||||
|
"
|
||||||
|
|
||||||
|
[node name="Scroll" type="ScrollContainer" parent="Panel"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 83.0
|
||||||
|
offset_top = 346.0
|
||||||
|
offset_right = -83.0
|
||||||
|
offset_bottom = -11.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="Output" type="Label" parent="Panel/Scroll"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "This example will \"dunk\" your JSON into BSON and then convert it back to JSON.
|
||||||
|
Due to a quirk in the way Godot parses JSON, all integers will be parsed as floats.
|
||||||
|
This may be a bug in Godot."
|
||||||
|
horizontal_alignment = 1
|
||||||
|
autowrap_mode = 3
|
||||||
|
|
||||||
|
[node name="CopyPopup" type="PopupPanel" parent="."]
|
||||||
|
transparent_bg = true
|
||||||
|
position = Vector2i(492, 586)
|
||||||
|
size = Vector2i(164, 31)
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="CopyPopup"]
|
||||||
|
offset_left = 4.0
|
||||||
|
offset_top = 4.0
|
||||||
|
offset_right = 160.0
|
||||||
|
offset_bottom = 27.0
|
||||||
|
text = "Copied to clipboard!"
|
||||||
|
|
||||||
|
[connection signal="pressed" from="Panel/Dunk" to="." method="_on_button_pressed"]
|
||||||
|
[connection signal="pressed" from="Panel/Copy" to="." method="_on_copy_pressed"]
|
18
README.md
18
README.md
@ -1,3 +1,17 @@
|
|||||||
# godot-bson
|
# BSON for the Godot Engine
|
||||||
|
This is a simple BSON serializer and deserializer written in GDScript that is originally designed to be compatible with [JSON for Modern C++](https://json.nlohmann.me/)'s BSON components, but it can be used with any other BSON tool.
|
||||||
|
|
||||||
A BSON serializer/deserializer for the Godot Engine
|
From [bsonspec.org](https://bsonspec.org/):
|
||||||
|
BSON, short for Binary [JSON](http://json.org), is a binary-encoded serialization of JSON-like documents. Like JSON, BSON supports the embedding of documents and arrays within other documents and arrays.
|
||||||
|
|
||||||
|
This plugin is useful for server/client communication, interacting with MongoDB, reducing JSON file sizes, etc.
|
||||||
|
|
||||||
|
After enabling this plugin in your Godot project settings, you can access the BSON object with:
|
||||||
|
```
|
||||||
|
BSON.to_bson(Dictionary)
|
||||||
|
```
|
||||||
|
and
|
||||||
|
```
|
||||||
|
BSON.from_bson(PackedByteArray)
|
||||||
|
```
|
||||||
|
You can also test out this plugin with `/BSON Examples/dunk.tscn`. This example will take your JSON, serialize it to BSON, then deserialize it back to JSON.
|
||||||
|
269
addons/bson/bson.gd
Normal file
269
addons/bson/bson.gd
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
# COPYRIGHT 2025 Colormatic Studios and contributors.
|
||||||
|
# This file is the BSON serializer for the Godot Engine,
|
||||||
|
# published under the MIT license. https://opensource.org/license/MIT
|
||||||
|
|
||||||
|
class_name BSON
|
||||||
|
|
||||||
|
|
||||||
|
static func to_bson(data: Dictionary) -> PackedByteArray:
|
||||||
|
var document := dictionary_to_bytes(data)
|
||||||
|
document.append(0x00)
|
||||||
|
var buffer := PackedByteArray()
|
||||||
|
buffer.append_array(int32_to_bytes(document.size() + 4))
|
||||||
|
buffer.append_array(document)
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
static func get_byte_type(value: Variant) -> int:
|
||||||
|
match typeof(value):
|
||||||
|
TYPE_STRING:
|
||||||
|
return 0x02
|
||||||
|
TYPE_INT:
|
||||||
|
if abs(value as int) < 2147483647: # 32 bit signed integer limit
|
||||||
|
return 0x10
|
||||||
|
else:
|
||||||
|
return 0x12
|
||||||
|
TYPE_FLOAT:
|
||||||
|
return 0x01
|
||||||
|
TYPE_ARRAY:
|
||||||
|
return 0x04
|
||||||
|
TYPE_DICTIONARY:
|
||||||
|
return 0x03
|
||||||
|
TYPE_BOOL:
|
||||||
|
return 0x08
|
||||||
|
_:
|
||||||
|
push_error("BSON serialization error: Unsupported type: ", typeof(value))
|
||||||
|
return 0x00
|
||||||
|
|
||||||
|
static func int16_to_bytes(value: int) -> PackedByteArray:
|
||||||
|
var buffer := PackedByteArray()
|
||||||
|
buffer.resize(2)
|
||||||
|
buffer.encode_s16(0, value)
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
static func int32_to_bytes(value: int) -> PackedByteArray:
|
||||||
|
var buffer := PackedByteArray()
|
||||||
|
buffer.resize(4)
|
||||||
|
buffer.encode_s32(0, value)
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
static func int64_to_bytes(value: int) -> PackedByteArray:
|
||||||
|
var buffer := PackedByteArray()
|
||||||
|
buffer.resize(8)
|
||||||
|
buffer.encode_s64(0, value)
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
static func float_to_bytes(value: float) -> PackedByteArray:
|
||||||
|
var buffer := PackedByteArray()
|
||||||
|
buffer.resize(4)
|
||||||
|
buffer.encode_float(0, value)
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
static func double_to_bytes(value: float) -> PackedByteArray:
|
||||||
|
var buffer := PackedByteArray()
|
||||||
|
buffer.resize(8)
|
||||||
|
buffer.encode_double(0, value)
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
static func dictionary_to_bytes(dict: Dictionary) -> PackedByteArray:
|
||||||
|
var buffer := PackedByteArray()
|
||||||
|
|
||||||
|
for key: String in dict.keys():
|
||||||
|
buffer.append(get_byte_type(dict[key]))
|
||||||
|
var key_string_bytes := key.to_utf8_buffer()
|
||||||
|
buffer.append_array(key_string_bytes)
|
||||||
|
buffer.append(0x00)
|
||||||
|
buffer.append_array(serialize_variant(dict[key]))
|
||||||
|
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
static func array_to_bytes(array: Array[Variant]) -> PackedByteArray:
|
||||||
|
var buffer := PackedByteArray()
|
||||||
|
|
||||||
|
for index: int in range(array.size()):
|
||||||
|
buffer.append(get_byte_type(array[index]))
|
||||||
|
# For whatever reason, BSON wants array indexes to be strings. This makes no sense.
|
||||||
|
var s_index := str(index)
|
||||||
|
buffer.append_array(s_index.to_utf8_buffer())
|
||||||
|
buffer.append(0x00)
|
||||||
|
|
||||||
|
buffer.append_array(serialize_variant(array[index]))
|
||||||
|
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
static func serialize_variant(data: Variant) -> PackedByteArray:
|
||||||
|
var buffer := PackedByteArray()
|
||||||
|
match typeof(data):
|
||||||
|
TYPE_DICTIONARY:
|
||||||
|
var document := dictionary_to_bytes(data as Dictionary)
|
||||||
|
buffer.append_array(int32_to_bytes(document.size()))
|
||||||
|
buffer.append_array(document)
|
||||||
|
buffer.append(0x00)
|
||||||
|
TYPE_ARRAY:
|
||||||
|
var b_array := array_to_bytes(data as Array[Variant])
|
||||||
|
buffer.append_array(int32_to_bytes(b_array.size()))
|
||||||
|
buffer.append_array(b_array)
|
||||||
|
buffer.append(0x00)
|
||||||
|
TYPE_STRING:
|
||||||
|
var str_as_bytes := (data as String).to_utf8_buffer()
|
||||||
|
buffer.append_array(int32_to_bytes(str_as_bytes.size() + 1))
|
||||||
|
buffer.append_array(str_as_bytes)
|
||||||
|
buffer.append(0x00)
|
||||||
|
TYPE_INT:
|
||||||
|
if abs(data as int) < 2147483647: # 32 bit signed integer limit
|
||||||
|
buffer.append_array(int32_to_bytes(data as int))
|
||||||
|
else:
|
||||||
|
buffer.append_array(int64_to_bytes(data as int))
|
||||||
|
TYPE_FLOAT:
|
||||||
|
buffer.append_array(double_to_bytes(data as float))
|
||||||
|
TYPE_BOOL:
|
||||||
|
buffer.append((data as bool) if 0x01 else 0x00)
|
||||||
|
_:
|
||||||
|
buffer.append(0x00)
|
||||||
|
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
|
||||||
|
static func from_bson(data: PackedByteArray) -> Dictionary:
|
||||||
|
return Deserializer.new(data).read_dictionary()
|
||||||
|
|
||||||
|
|
||||||
|
class Deserializer:
|
||||||
|
var buffer: PackedByteArray
|
||||||
|
var read_position := 0
|
||||||
|
|
||||||
|
func _init(buffer: PackedByteArray):
|
||||||
|
self.buffer = buffer
|
||||||
|
|
||||||
|
func get_int8() -> int:
|
||||||
|
var value := buffer[read_position]
|
||||||
|
read_position += 1
|
||||||
|
return value
|
||||||
|
|
||||||
|
func get_int16() -> int:
|
||||||
|
var value := buffer.decode_s16(read_position)
|
||||||
|
read_position += 2
|
||||||
|
return value
|
||||||
|
|
||||||
|
func get_int32() -> int:
|
||||||
|
var value := buffer.decode_s32(read_position)
|
||||||
|
read_position += 4
|
||||||
|
return value
|
||||||
|
|
||||||
|
func get_int64() -> int:
|
||||||
|
var value := buffer.decode_s64(read_position)
|
||||||
|
read_position += 8
|
||||||
|
return value
|
||||||
|
|
||||||
|
func get_float() -> float:
|
||||||
|
var value := buffer.decode_float(read_position)
|
||||||
|
read_position += 4
|
||||||
|
return value
|
||||||
|
|
||||||
|
func get_double() -> float:
|
||||||
|
var value := buffer.decode_double(read_position)
|
||||||
|
read_position += 8
|
||||||
|
return value
|
||||||
|
|
||||||
|
func get_string() -> String:
|
||||||
|
var expected_size = get_int32()
|
||||||
|
var s_value: String
|
||||||
|
var iter := 0
|
||||||
|
while true:
|
||||||
|
iter += 1
|
||||||
|
var b_char := get_int8()
|
||||||
|
if b_char == 0x00: break
|
||||||
|
s_value += char(b_char)
|
||||||
|
if expected_size != iter: # Check if the string is terminated with 0x00
|
||||||
|
push_error("BSON deserialization error: String was the wrong size."
|
||||||
|
+ " Position: "
|
||||||
|
+ str(read_position - iter)
|
||||||
|
+ ", stated size: "
|
||||||
|
+ str(expected_size)
|
||||||
|
+ ", actual size: "
|
||||||
|
+ str(iter))
|
||||||
|
return s_value
|
||||||
|
|
||||||
|
func get_bool() -> bool:
|
||||||
|
return (get_int8() == 1)
|
||||||
|
|
||||||
|
func read_dictionary() -> Dictionary:
|
||||||
|
var object = {}
|
||||||
|
|
||||||
|
var expected_size := get_int32()
|
||||||
|
|
||||||
|
var iter := 0
|
||||||
|
while true:
|
||||||
|
iter += 1
|
||||||
|
var type := get_int8()
|
||||||
|
if type == 0x00: break
|
||||||
|
|
||||||
|
var key := ""
|
||||||
|
|
||||||
|
while true:
|
||||||
|
var k_char := get_int8()
|
||||||
|
if k_char == 0x00: break
|
||||||
|
key += char(k_char)
|
||||||
|
|
||||||
|
match type:
|
||||||
|
0x02: object[key] = get_string()
|
||||||
|
0x10: object[key] = get_int32()
|
||||||
|
0x12: object[key] = get_int64()
|
||||||
|
0x01: object[key] = get_double()
|
||||||
|
0x08: object[key] = get_bool()
|
||||||
|
0x04: object[key] = read_array()
|
||||||
|
0x03: object[key] = read_dictionary()
|
||||||
|
_:
|
||||||
|
push_error("BSON deserialization error: Unsupported type "
|
||||||
|
+ str(type)
|
||||||
|
+ " at byte "
|
||||||
|
+ str(read_position - 1))
|
||||||
|
|
||||||
|
if iter > expected_size:
|
||||||
|
push_warning("BSON deserialization warning: Dictionary is the wrong length."
|
||||||
|
+ " Expected dictionary length: "
|
||||||
|
+ str(expected_size)
|
||||||
|
+ ", Actual dictionary length: "
|
||||||
|
+ str(iter))
|
||||||
|
return object
|
||||||
|
|
||||||
|
func read_array() -> Array:
|
||||||
|
var array: Array
|
||||||
|
|
||||||
|
var expected_size := get_int32()
|
||||||
|
|
||||||
|
var iter := 0
|
||||||
|
while true:
|
||||||
|
iter += 1
|
||||||
|
var type := get_int8()
|
||||||
|
if type == 0x00: break
|
||||||
|
|
||||||
|
var key: String
|
||||||
|
|
||||||
|
while true:
|
||||||
|
var k_char := get_int8()
|
||||||
|
if k_char == 0x00: break
|
||||||
|
key += char(k_char)
|
||||||
|
|
||||||
|
# IMPORTANT: Since the array is being deserialized sequentially, we can
|
||||||
|
# use the Array.append() function. It would be better to set the index
|
||||||
|
# directly, but that is not possible. (It *could* cause null holes)
|
||||||
|
# The BSON specification unfortunately allows for null holes, but
|
||||||
|
# this deserializer will just remove any gaps. This could cause an
|
||||||
|
# index desynchronization between two programs communicating with BSON,
|
||||||
|
# but that means the other program has a buggy serializer.
|
||||||
|
match type:
|
||||||
|
0x02: array.append(get_string())
|
||||||
|
0x10: array.append(get_int32())
|
||||||
|
0x12: array.append(get_int64())
|
||||||
|
0x01: array.append(get_double())
|
||||||
|
0x08: array.append(get_bool())
|
||||||
|
0x04: array.append(read_array())
|
||||||
|
0x03: array.append(read_dictionary())
|
||||||
|
_: push_error("BSON deserialization error: Unsupported type: " + str(type))
|
||||||
|
if iter > expected_size:
|
||||||
|
push_warning("BSON deserialization warning: Array is the wrong length."
|
||||||
|
+ " Expected array length: "
|
||||||
|
+ str(expected_size)
|
||||||
|
+ ", Actual array length: "
|
||||||
|
+ str(iter))
|
||||||
|
return array
|
7
addons/bson/plugin.cfg
Normal file
7
addons/bson/plugin.cfg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[plugin]
|
||||||
|
|
||||||
|
name="BSON"
|
||||||
|
description="A BSON class to serialize and deserialize BSON in GDScript."
|
||||||
|
author="Colormatic Studios"
|
||||||
|
version=""
|
||||||
|
script="plugin.gd"
|
20
addons/bson/plugin.gd
Normal file
20
addons/bson/plugin.gd
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
@tool
|
||||||
|
extends EditorPlugin
|
||||||
|
|
||||||
|
|
||||||
|
const AUTOLOAD_NAME = "BSON"
|
||||||
|
|
||||||
|
|
||||||
|
#func _enter_tree() -> void:
|
||||||
|
# Initialization of the plugin goes here.
|
||||||
|
#pass
|
||||||
|
|
||||||
|
#func _exit_tree() -> void:
|
||||||
|
# Clean-up of the plugin goes here.
|
||||||
|
#pass
|
||||||
|
|
||||||
|
func _enable_plugin() -> void:
|
||||||
|
add_autoload_singleton(AUTOLOAD_NAME, "res://addons/bson/bson.gd")
|
||||||
|
|
||||||
|
func _disable_plugin() -> void:
|
||||||
|
remove_autoload_singleton(AUTOLOAD_NAME)
|
89
icon-full.svg
Normal file
89
icon-full.svg
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="423.74899"
|
||||||
|
height="91.300003"
|
||||||
|
viewBox="0 0 112.11691 24.156458"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||||
|
sodipodi:docname="icon-full.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#000000"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:zoom="2.0132505"
|
||||||
|
inkscape:cx="267.9746"
|
||||||
|
inkscape:cy="87.917524"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1008"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg1" /><defs
|
||||||
|
id="defs1" /><rect
|
||||||
|
style="fill:#383c3f;stroke-width:0.79375;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
id="rect1"
|
||||||
|
width="112.11691"
|
||||||
|
height="24.156458"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
ry="0" /><g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"><g
|
||||||
|
id="text1"
|
||||||
|
style="font-size:25.4px;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;fill:none;stroke:#ffffff;stroke-width:0.79375;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
aria-label="BSON{ }"><path
|
||||||
|
style="font-family:sans-serif;-inkscape-font-specification:sans-serif"
|
||||||
|
d="m 5.2694299,10.46546 v 6.784082 h 4.0183593 q 2.0215818,0 2.9889648,-0.830958 0.979785,-0.843359 0.979785,-2.567285 0,-1.736328 -0.979785,-2.554882 Q 11.309371,10.46546 9.2877892,10.46546 Z m 0,-7.6150394 v 5.5810546 h 3.7083008 q 1.8355473,0 2.7285153,-0.6821289 0.905371,-0.6945312 0.905371,-2.1083984 0,-1.4014648 -0.905371,-2.095996 Q 10.813278,2.8504206 8.9777307,2.8504206 Z M 2.7641565,0.7916316 h 6.3996093 q 2.8649412,0 4.4152342,1.190625 1.550293,1.190625 1.550293,3.3858398 0,1.699121 -0.79375,2.7037109 -0.79375,1.0045898 -2.331641,1.2526367 1.84795,0.396875 2.864942,1.661914 1.029394,1.252637 1.029394,3.137793 0,2.480469 -1.686718,3.832324 -1.686719,1.351856 -4.7997073,1.351856 H 2.7641565 Z M 30.843061,1.3993464 V 3.8426081 Q 29.416792,3.1604792 28.151753,2.8256159 26.886714,2.4907527 25.708491,2.4907527 q -2.046386,0 -3.162597,0.79375 -1.103809,0.7937499 -1.103809,2.2572265 0,1.227832 0.731738,1.8603515 0.744141,0.6201172 2.80293,1.0045898 l 1.513086,0.3100586 q 2.80293,0.5333008 4.12998,1.8851559 1.339453,1.339453 1.339453,3.59668 0,2.691309 -1.810742,4.080371 -1.79834,1.389062 -5.283398,1.389062 -1.314649,0 -2.80293,-0.297656 -1.475879,-0.297656 -3.063379,-0.880566 v -2.579688 q 1.525489,0.855762 2.988965,1.289844 1.463477,0.434082 2.877344,0.434082 2.145605,0 3.311426,-0.843359 1.16582,-0.84336 1.16582,-2.406055 0,-1.364258 -0.843359,-2.133203 -0.830957,-0.768945 -2.740918,-1.153418 l -1.525489,-0.297656 q -2.802929,-0.558106 -4.055566,-1.7487306 -1.252637,-1.190625 -1.252637,-3.3114257 0,-2.455664 1.723926,-3.8695312 1.736328,-1.41386718 4.774902,-1.41386718 1.302246,0 2.654102,0.23564453 1.351855,0.23564452 2.765722,0.70693355 z m 12.538768,1.0914063 q -2.728515,0 -4.34082,2.0339843 -1.599902,2.0339844 -1.599902,5.543848 0,3.49746 1.599902,5.531445 1.612305,2.033984 4.34082,2.033984 2.728516,0 4.316016,-2.033984 1.599902,-2.033985 1.599902,-5.531445 0,-3.5098636 -1.599902,-5.543848 -1.5875,-2.0339843 -4.316016,-2.0339843 z m 0,-2.03398438 q 3.894336,0 6.225977,2.61689448 2.33164,2.6044922 2.33164,6.9949222 0,4.378027 -2.33164,6.994921 -2.331641,2.604492 -6.225977,2.604492 -3.906738,0 -6.250781,-2.604492 -2.331641,-2.604492 -2.331641,-6.994921 0,-4.39043 2.331641,-6.9949222 2.344043,-2.61689448 6.250781,-2.61689448 z m 12.47676,0.33486328 h 3.373438 L 67.442378,16.282159 V 0.7916316 h 2.43086 V 19.308331 H 66.4998 L 58.289449,3.8178034 V 19.308331 h -2.43086 z"
|
||||||
|
id="path5" /><path
|
||||||
|
style="font-family:'Noto Sans';-inkscape-font-specification:'Noto Sans'"
|
||||||
|
d="m 81.205311,23.32153 q -2.3368,-0.0254 -3.683,-1.016 -1.3462,-0.990599 -1.3462,-3.022599 v -3.7338 q 0,-1.2954 -0.8128,-1.8288 -0.7874,-0.5588 -2.286,-0.5588 v -1.8542 q 1.4986,-0.0254 2.286,-0.5588 0.8128,-0.5334 0.8128,-1.8034003 v -3.7592 q 0,-2.0319999 1.397,-3.0225999 1.397,-0.9906 3.6322,-0.9906 v 1.8288 q -1.3208,0.0254 -2.0828,0.5842 -0.7366,0.5588 -0.7366,1.8033999 v 3.6576 q 0,2.6162003 -2.7686,3.0988003 v 0.1524 q 2.7686,0.4826 2.7686,3.0988 v 3.7338 q 0,1.2446 0.7366,1.778 0.7366,0.5588 2.0828,0.5842 z m 21.437599,-1.828799 q 1.3208,-0.0508 2.0574,-0.6096 0.762,-0.5334 0.762,-1.778 v -3.683 q 0,-2.6162 2.7686,-3.0988 v -0.1524 q -2.7686,-0.4826 -2.7686,-3.0988003 v -3.7084 q 0,-1.2445999 -0.7366,-1.7779999 -0.7366,-0.5588 -2.0828,-0.5842 v -1.8288 q 2.3368,0.0254 3.683,1.016 1.3462,0.9906 1.3462,3.0225999 v 3.7084 q 0,1.2954003 0.7874,1.8542003 0.8128,0.5334 2.3114,0.5334 v 1.8542 q -1.4986,0.0254 -2.3114,0.5588 -0.7874,0.5334 -0.7874,1.8034 v 3.7846 q 0,2.0066 -1.397,2.997199 -1.397,1.016 -3.6322,1.016 z"
|
||||||
|
id="path6" /></g><g
|
||||||
|
id="g1"
|
||||||
|
transform="matrix(0.26458332,0,0,0.26458332,74.979948,-4.7666463)"><g
|
||||||
|
fill="#ffffff"
|
||||||
|
transform="matrix(0.101,0,0,0.101,12.322,12.322)"
|
||||||
|
id="g4"><path
|
||||||
|
d="m 105,673 v 33 q 407,354 814,0 v -33 z"
|
||||||
|
id="path1" /><path
|
||||||
|
fill="#478cbf"
|
||||||
|
d="m 105,673 152,14 q 12,1 15,14 l 4,67 132,10 8,-61 q 2,-11 15,-15 h 162 q 13,4 15,15 l 8,61 132,-10 4,-67 q 3,-13 15,-14 L 919,673 V 427 q 30,-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,81 z m 0,33 v 39 c 0,276 813,276 814,0 v -39 l -134,12 -5,69 q -2,10 -14,13 l -162,11 q -12,0 -16,-11 L 578,735 H 446 l -10,65 q -4,11 -16,11 L 258,800 q -12,-3 -14,-13 l -5,-69 z"
|
||||||
|
id="path2" /><path
|
||||||
|
d="m 483,600 c 0,34 58,34 58,0 v -86 c 0,-34 -58,-34 -58,0 z"
|
||||||
|
id="path3" /><circle
|
||||||
|
cx="725"
|
||||||
|
cy="526"
|
||||||
|
r="90"
|
||||||
|
id="circle3" /><circle
|
||||||
|
cx="299"
|
||||||
|
cy="526"
|
||||||
|
r="90"
|
||||||
|
id="circle4" /></g><g
|
||||||
|
fill="#414042"
|
||||||
|
transform="matrix(0.101,0,0,0.101,12.322,12.322)"
|
||||||
|
id="g6"><circle
|
||||||
|
cx="307"
|
||||||
|
cy="532"
|
||||||
|
r="60"
|
||||||
|
id="circle5" /><circle
|
||||||
|
cx="717"
|
||||||
|
cy="532"
|
||||||
|
r="60"
|
||||||
|
id="circle6" /></g></g><path
|
||||||
|
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.79375;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 1.4552082,22.089884 H 71.311877"
|
||||||
|
id="path4"
|
||||||
|
sodipodi:nodetypes="cc" /></g></svg>
|
After Width: | Height: | Size: 6.9 KiB |
37
icon-full.svg.import
Normal file
37
icon-full.svg.import
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://c6htrl16c0eay"
|
||||||
|
path="res://.godot/imported/icon-full.svg-e72bf6bf218ce1384c33716fd0ad1d25.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://icon-full.svg"
|
||||||
|
dest_files=["res://.godot/imported/icon-full.svg-e72bf6bf218ce1384c33716fd0ad1d25.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
|
78
icon.svg
Normal file
78
icon.svg
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="150"
|
||||||
|
height="150"
|
||||||
|
viewBox="0 0 39.687495 39.687498"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||||
|
sodipodi:docname="icon.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#000000"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.55686275"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:zoom="4.026501"
|
||||||
|
inkscape:cx="71.029412"
|
||||||
|
inkscape:cy="68.049157"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1008"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1" /><defs
|
||||||
|
id="defs1" /><circle
|
||||||
|
style="fill:#383c3f;stroke:none;stroke-width:0.79375;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1"
|
||||||
|
id="path4"
|
||||||
|
cx="19.843748"
|
||||||
|
cy="19.843748"
|
||||||
|
r="19.843748" /><g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"><path
|
||||||
|
style="font-size:25.4px;font-family:'Noto Sans';-inkscape-font-specification:'Noto Sans';fill:none;stroke:#ffffff;stroke-width:0.716662;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
d="M 10.165941,29.842621 Q 8.0560869,29.819687 6.8406275,28.925293 5.6251681,28.030898 5.6251681,26.196242 v -3.371179 q 0,-1.169594 -0.7338622,-1.651191 -0.710929,-0.50453 -2.0639875,-0.50453 v -1.674124 q 1.3530585,-0.02293 2.0639875,-0.504529 0.7338622,-0.481597 0.7338622,-1.628257 v -3.394113 q 0,-1.834655 1.2613259,-2.72905 1.2613257,-0.8943948 3.279447,-0.8943948 v 1.6511908 q -1.1925263,0.02294 -1.8805221,0.527463 -0.6650626,0.504531 -0.6650626,1.628256 v 3.302381 q 0,2.362119 -2.4997184,2.797849 v 0.137599 q 2.4997184,0.435731 2.4997184,2.797851 v 3.371179 q 0,1.123727 0.6650626,1.605324 0.6650626,0.504531 1.8805221,0.527463 z M 29.521556,28.19143 q 1.192526,-0.04586 1.857589,-0.550396 0.687995,-0.481597 0.687995,-1.605324 v -3.325314 q 0,-2.362118 2.499719,-2.797849 V 19.774948 Q 32.06714,19.339217 32.06714,16.977098 v -3.348247 q 0,-1.123726 -0.665062,-1.605323 -0.665062,-0.50453 -1.880522,-0.527463 V 9.8448742 q 2.109854,0.022938 3.325313,0.9173278 1.215459,0.894395 1.215459,2.72905 v 3.348246 q 0,1.169594 0.71093,1.674123 0.733862,0.481597 2.086921,0.481597 v 1.674124 q -1.353059,0.02294 -2.086921,0.50453 -0.71093,0.481597 -0.71093,1.628257 v 3.417047 q 0,1.811722 -1.261325,2.706117 -1.261326,0.917328 -3.279447,0.917328 z"
|
||||||
|
id="text1"
|
||||||
|
aria-label="{ }" /><g
|
||||||
|
id="g1"
|
||||||
|
transform="matrix(0.20299097,0,0,0.20299097,6.8454249,6.7941697)"><g
|
||||||
|
fill="#ffffff"
|
||||||
|
transform="matrix(0.101,0,0,0.101,12.322,12.322)"
|
||||||
|
id="g4"><path
|
||||||
|
d="m 105,673 v 33 q 407,354 814,0 v -33 z"
|
||||||
|
id="path1" /><path
|
||||||
|
fill="#478cbf"
|
||||||
|
d="m 105,673 152,14 q 12,1 15,14 l 4,67 132,10 8,-61 q 2,-11 15,-15 h 162 q 13,4 15,15 l 8,61 132,-10 4,-67 q 3,-13 15,-14 L 919,673 V 427 q 30,-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,81 z m 0,33 v 39 c 0,276 813,276 814,0 v -39 l -134,12 -5,69 q -2,10 -14,13 l -162,11 q -12,0 -16,-11 L 578,735 H 446 l -10,65 q -4,11 -16,11 L 258,800 q -12,-3 -14,-13 l -5,-69 z"
|
||||||
|
id="path2" /><path
|
||||||
|
d="m 483,600 c 0,34 58,34 58,0 v -86 c 0,-34 -58,-34 -58,0 z"
|
||||||
|
id="path3" /><circle
|
||||||
|
cx="725"
|
||||||
|
cy="526"
|
||||||
|
r="90"
|
||||||
|
id="circle3" /><circle
|
||||||
|
cx="299"
|
||||||
|
cy="526"
|
||||||
|
r="90"
|
||||||
|
id="circle4" /></g><g
|
||||||
|
fill="#414042"
|
||||||
|
transform="matrix(0.101,0,0,0.101,12.322,12.322)"
|
||||||
|
id="g6"><circle
|
||||||
|
cx="307"
|
||||||
|
cy="532"
|
||||||
|
r="60"
|
||||||
|
id="circle5" /><circle
|
||||||
|
cx="717"
|
||||||
|
cy="532"
|
||||||
|
r="60"
|
||||||
|
id="circle6" /></g></g></g></svg>
|
After Width: | Height: | Size: 4.3 KiB |
37
icon.svg.import
Normal file
37
icon.svg.import
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://0iy4oa1unjrt"
|
||||||
|
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
|
20
project.godot
Normal file
20
project.godot
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
; 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="BSON for Godot"
|
||||||
|
run/main_scene="res://BSON Examples/dunk.tscn"
|
||||||
|
config/features=PackedStringArray("4.3", "Forward Plus")
|
||||||
|
config/icon="res://icon.svg"
|
||||||
|
|
||||||
|
[editor_plugins]
|
||||||
|
|
||||||
|
enabled=PackedStringArray("res://addons/bson/plugin.cfg")
|
Reference in New Issue
Block a user