Major clean up and reorganization

- Upgraded to Godot 4
- Just remembered the basic principles are based on a tile editor, and dramatically simplified from there. Derp.
- New state machine and license display add-ons.
- Re-licensed under the GPL because Micropolis' assets aren't under a separate one.
This commit is contained in:
Tony Bark 2023-03-14 06:17:27 -04:00
parent 55ed76c914
commit c980445340
337 changed files with 5129 additions and 7661 deletions

View file

@ -1,24 +0,0 @@
extends Reference
var blackboard = {}
func set(key, value, blackboard_name = 'default'):
if not blackboard.has(blackboard_name):
blackboard[blackboard_name] = {}
blackboard[blackboard_name][key] = value
func get(key, default_value = null, blackboard_name = 'default'):
if has(key, blackboard_name):
return blackboard[blackboard_name].get(key, default_value)
return default_value
func has(key, blackboard_name = 'default'):
return blackboard.has(blackboard_name) and blackboard[blackboard_name].has(key) and blackboard[blackboard_name][key] != null
func erase(key, blackboard_name = 'default'):
if blackboard.has(blackboard_name):
blackboard[blackboard_name][key] = null

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg14360"
sodipodi:docname="action.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata14366">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14364" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview14362"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg14360" />
<path
d="M 8,4 C 5.792,4 4,5.792 4,8 c 0,2.208 1.792,4 4,4 2.208,0 4,-1.792 4,-4 C 12,5.792 10.208,4 8,4 Z M 8,0 C 3.584,0 0,3.584 0,8 c 0,4.416 3.584,8 8,8 4.416,0 8,-3.584 8,-8 C 16,3.584 12.416,0 8,0 Z M 8,14.4 C 4.464,14.4 1.6,11.536 1.6,8 1.6,4.464 4.464,1.6 8,1.6 c 3.536,0 6.4,2.864 6.4,6.4 0,3.536 -2.864,6.4 -6.4,6.4 z"
id="path14356"
style="fill:#efd7a5;fill-opacity:1;stroke-width:0.80000001"
inkscape:connector-curvature="0" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path14358"
inkscape:connector-curvature="0"
style="fill:none" />
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/action.svg-e8a91246d0ba9ba3cf84290d65648f06.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/action.svg"
dest_files=[ "res://.import/action.svg-e8a91246d0ba9ba3cf84290d65648f06.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg893"
sodipodi:docname="blackboard.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata899">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs897" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview895"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg893" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path889"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="M 0,8.888889 H 7.111111 V 0 H 0 Z M 0,16 H 7.111111 V 10.666667 H 0 Z m 8.888889,0 H 16 V 7.111111 H 8.888889 Z m 0,-16 V 5.333333 H 16 V 0 Z"
id="path891"
style="fill:#b2a5ef;fill-opacity:1;stroke-width:0.8888889"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/blackboard.svg-18d4dfd4f6de558de250b67251ff1e69.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/blackboard.svg"
dest_files=[ "res://.import/blackboard.svg-18d4dfd4f6de558de250b67251ff1e69.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg14360"
sodipodi:docname="category_bt.svg"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
<metadata
id="metadata14366">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14364" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1051"
id="namedview14362"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-6.0508475"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg14360" />
<path
d="M 8,4 C 5.792,4 4,5.792 4,8 c 0,2.208 1.792,4 4,4 2.208,0 4,-1.792 4,-4 C 12,5.792 10.208,4 8,4 Z M 8,0 C 3.584,0 0,3.584 0,8 c 0,4.416 3.584,8 8,8 4.416,0 8,-3.584 8,-8 C 16,3.584 12.416,0 8,0 Z M 8,14.4 C 4.464,14.4 1.6,11.536 1.6,8 1.6,4.464 4.464,1.6 8,1.6 c 3.536,0 6.4,2.864 6.4,6.4 0,3.536 -2.864,6.4 -6.4,6.4 z"
id="path14356"
style="fill:#b2a5ef;fill-opacity:1;stroke-width:0.80000001"
inkscape:connector-curvature="0" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path14358"
inkscape:connector-curvature="0"
style="fill:none" />
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/category_bt.svg-8537bebd1c5f62dca3d7ee7f17efeed4.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/category_bt.svg"
dest_files=[ "res://.import/category_bt.svg-8537bebd1c5f62dca3d7ee7f17efeed4.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg14360"
sodipodi:docname="category_composite.svg"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
<metadata
id="metadata14366">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14364" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1051"
id="namedview14362"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-6.0508475"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg14360" />
<path
d="M 8,4 C 5.792,4 4,5.792 4,8 c 0,2.208 1.792,4 4,4 2.208,0 4,-1.792 4,-4 C 12,5.792 10.208,4 8,4 Z M 8,0 C 3.584,0 0,3.584 0,8 c 0,4.416 3.584,8 8,8 4.416,0 8,-3.584 8,-8 C 16,3.584 12.416,0 8,0 Z M 8,14.4 C 4.464,14.4 1.6,11.536 1.6,8 1.6,4.464 4.464,1.6 8,1.6 c 3.536,0 6.4,2.864 6.4,6.4 0,3.536 -2.864,6.4 -6.4,6.4 z"
id="path14356"
style="fill:#a5efac;fill-opacity:1;stroke-width:0.80000001"
inkscape:connector-curvature="0" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path14358"
inkscape:connector-curvature="0"
style="fill:none" />
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/category_composite.svg-43f66e63a7ccfa5ac8ec6da0583b3246.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/category_composite.svg"
dest_files=[ "res://.import/category_composite.svg-43f66e63a7ccfa5ac8ec6da0583b3246.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg14360"
sodipodi:docname="category_decorator.svg"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
<metadata
id="metadata14366">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14364" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1051"
id="namedview14362"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-6.0508475"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg14360" />
<path
d="M 8,4 C 5.792,4 4,5.792 4,8 c 0,2.208 1.792,4 4,4 2.208,0 4,-1.792 4,-4 C 12,5.792 10.208,4 8,4 Z M 8,0 C 3.584,0 0,3.584 0,8 c 0,4.416 3.584,8 8,8 4.416,0 8,-3.584 8,-8 C 16,3.584 12.416,0 8,0 Z M 8,14.4 C 4.464,14.4 1.6,11.536 1.6,8 1.6,4.464 4.464,1.6 8,1.6 c 3.536,0 6.4,2.864 6.4,6.4 0,3.536 -2.864,6.4 -6.4,6.4 z"
id="path14356"
style="fill:#fc9c9c;fill-opacity:1;stroke-width:0.80000001"
inkscape:connector-curvature="0" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path14358"
inkscape:connector-curvature="0"
style="fill:none" />
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/category_decorator.svg-79d598d6456f32724156248e09d6eaf3.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/category_decorator.svg"
dest_files=[ "res://.import/category_decorator.svg-79d598d6456f32724156248e09d6eaf3.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg13771"
sodipodi:docname="condition.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata13777">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs13775" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview13773"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg13771" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path13767"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="M 14.222222,0 H 1.7777778 C 0.7911111,0 0,0.8 0,1.7777778 V 14.222222 C 0,15.2 0.7911111,16 1.7777778,16 H 14.222222 C 15.208889,16 16,15.2 16,14.222222 V 1.7777778 C 16,0.8 15.208889,0 14.222222,0 Z M 6.2222222,12.444444 1.7777778,8 3.0311111,6.7466667 6.2222222,9.9288889 12.968889,3.1822222 14.222222,4.4444444 Z"
id="path13769"
style="fill:#efd7a5;fill-opacity:1;stroke-width:0.8888889"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/condition.svg-57892684b10a64086f68c09c388b17e5.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/condition.svg"
dest_files=[ "res://.import/condition.svg-57892684b10a64086f68c09c388b17e5.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg5952"
sodipodi:docname="fail.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata5958">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs5956" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview5954"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-23.186441"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg5952"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
scale-x="1" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path5948"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="m 8.1694915,0.0338983 c -4.416,0 -7.99999997,3.584 -7.99999997,8 0,4.4159997 3.58399997,7.9999997 7.99999997,7.9999997 4.4160005,0 8.0000005,-3.584 8.0000005,-7.9999997 0,-4.416 -3.584,-8 -8.0000005,-8 z m 0.8,11.9999997 h -1.6 v -1.6 h 1.6 z m 0,-3.1999997 h -1.6 v -4.8 h 1.6 z"
id="path5950"
style="fill:#fc9c9c;fill-opacity:1;stroke-width:0.80000001"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/fail.svg-85247bd8065819a11b971d222d3d43bb.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/fail.svg"
dest_files=[ "res://.import/fail.svg-85247bd8065819a11b971d222d3d43bb.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg6553"
sodipodi:docname="inverter.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata6559">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6557" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview6555"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-22.881356"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg6553" />
<path
d="M 0,-8 H 24 V 16 H 0 Z m 0,0 H 24 V 16 H 0 Z m 0,0 H 24 V 16 H 0 Z"
id="path6549"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="M 14.222222,0 H 1.7777778 C 0.8,0 0,0.8 0,1.7777778 V 14.222222 C 0,15.2 0.8,16 1.7777778,16 H 14.222222 C 15.2,16 16,15.2 16,14.222222 V 1.7777778 C 16,0.8 15.2,0 14.222222,0 Z M 2.6666667,3.5555556 H 7.111111 V 4.8888889 H 2.6666667 Z M 14.222222,14.222222 H 1.7777778 L 14.222222,1.7777778 Z m -4,-2.666666 v 1.777777 h 1.333334 v -1.777777 h 1.777777 V 10.222222 H 11.555556 V 8.444444 h -1.333334 v 1.777778 H 8.444444 v 1.333334 z"
id="path6551"
style="fill:#fc9c9c;fill-opacity:1;stroke-width:0.8888889"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/inverter.svg-1f1b976d95de42c4ad99a92fa9a6c5d0.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/inverter.svg"
dest_files=[ "res://.import/inverter.svg-1f1b976d95de42c4ad99a92fa9a6c5d0.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg7154"
sodipodi:docname="limiter.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata7160">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs7158" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview7156"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg7154" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path7150"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="M 8.0685714,4.541598 10.79619,7.2768364 H 0 v 1.523809 H 10.79619 L 8.0609524,11.535884 9.142857,12.61017 13.714286,8.0387404 9.142857,3.4673123 Z M 14.47619,3.4673123 V 12.61017 H 16 V 3.4673123 Z"
id="path7152"
style="fill:#fc9c9c;fill-opacity:1;stroke-width:0.76190478"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/limiter.svg-b4c7646605c46f53c5e403fe21d8f584.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/limiter.svg"
dest_files=[ "res://.import/limiter.svg-b4c7646605c46f53c5e403fe21d8f584.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg12569"
sodipodi:docname="selector.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12575">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12573" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview12571"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg12569" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path12565"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="M 3.8101694,4 H 11.81017 v 2.4 l 3.2,-3.2 -3.2,-3.2 V 2.4 H 2.2101694 v 4.8 h 1.6 z M 11.81017,12 H 3.8101694 V 9.6 L 0.61016952,12.8 3.8101694,16 V 13.6 H 13.41017 V 8.8 h -1.6 z"
id="path12567"
style="fill:#a5efac;fill-opacity:1;stroke-width:0.80000001"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/selector.svg-78bccfc448bd1676b5a29bfde4b08e5b.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/selector.svg"
dest_files=[ "res://.import/selector.svg-78bccfc448bd1676b5a29bfde4b08e5b.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<rect id="path12565" x="0" y="-8" width="24" height="24" style="fill:none;fill-rule:nonzero;"/>
<g transform="matrix(0.571429,0,0,0.571429,7.42857,-585.2)">
<path d="M8,1038.1L5.626,1042.2L1,1043.3L4.236,1046.7L3.877,1051.38L8.016,1049.4L12.174,1051.34L11.778,1046.69L15,1043.3L10.374,1042.2L8,1038.1Z" style="fill:rgb(165,239,172);fill-rule:nonzero;"/>
</g>
<path id="path12567" d="M8.76,13.6L8.784,13.315L7.405,12L3.81,12L3.81,9.6L0.61,12.8L3.81,16L3.81,13.6L8.76,13.6ZM13.41,8.855L13.375,8.8L13.41,8.8L13.41,8.855ZM3.81,4L11.81,4L11.81,6.4L15.01,3.2L11.81,0L11.81,2.4L2.21,2.4L2.21,7.2L3.81,7.2L3.81,4Z" style="fill:rgb(165,239,172);fill-rule:nonzero;"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/selector_star.svg-368af7abfb9842c3f4258786871d1f03.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/selector_star.svg"
dest_files=[ "res://.import/selector_star.svg-368af7abfb9842c3f4258786871d1f03.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg13170"
sodipodi:docname="sequence.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata13176">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs13174" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview13172"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="17.186441"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg13170" />
<path
d="M 0,9.0376644 H 1.7777778 V 7.2598874 H 0 Z M 0,12.59322 H 1.7777778 V 10.815442 H 0 Z M 0,5.4821093 H 1.7777778 V 3.7043315 H 0 Z M 3.5555556,9.0376644 H 16 V 7.2598874 H 3.5555556 Z m 0,3.5555556 H 16 V 10.815442 H 3.5555556 Z m 0,-8.8888885 V 5.4821093 H 16 V 3.7043315 Z"
id="path13166"
style="fill:#a5efac;fill-opacity:1;stroke-width:0.8888889"
inkscape:connector-curvature="0" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path13168"
inkscape:connector-curvature="0"
style="fill:none" />
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/sequencer.svg-a7b0e1cc6b00c0067836f9a81d0b2f9b.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/sequencer.svg"
dest_files=[ "res://.import/sequencer.svg-a7b0e1cc6b00c0067836f9a81d0b2f9b.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<rect id="path13168" x="0" y="-8" width="24" height="24" style="fill:none;fill-rule:nonzero;"/>
<g transform="matrix(0.571429,0,0,0.571429,7.42857,-585.2)">
<path d="M8,1038.1L5.626,1042.2L1,1043.3L4.236,1046.7L3.877,1051.38L8.016,1049.4L12.174,1051.34L11.778,1046.69L15,1043.3L10.374,1042.2L8,1038.1Z" style="fill:rgb(165,239,172);fill-rule:nonzero;"/>
</g>
<path id="path13166" d="M0,12.593L1.778,12.593L1.778,10.815L0,10.815L0,12.593ZM5.728,10.815L3.556,10.815L3.556,12.593L7.416,12.593L5.728,10.815ZM0,9.038L1.778,9.038L1.778,7.26L0,7.26L0,9.038ZM10.976,7.26L3.556,7.26L3.556,9.038L9.946,9.038L10.976,7.26ZM13.024,7.26L14.054,9.038L16,9.038L16,7.26L13.024,7.26ZM0,5.482L1.778,5.482L1.778,3.704L0,3.704L0,5.482ZM3.556,3.704L3.556,5.482L16,5.482L16,3.704L3.556,3.704Z" style="fill:rgb(165,239,172);fill-rule:nonzero;"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/sequencer_star.svg-2385cbba0c38b4d4ec43e0996f8a3493.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/sequencer_star.svg"
dest_files=[ "res://.import/sequencer_star.svg-2385cbba0c38b4d4ec43e0996f8a3493.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg5317"
sodipodi:docname="succeed.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata5323">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs5321" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview5319"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-40.576272"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg5317" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path5313"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="M 8,0 C 3.584,0 0,3.584 0,8 c 0,4.416 3.584,8 8,8 4.416,0 8,-3.584 8,-8 C 16,3.584 12.416,0 8,0 Z M 6.4,12 2.4,8 3.528,6.872 6.4,9.736 12.472,3.664 13.6,4.8 Z"
id="path5315"
style="fill:#fc9c9c;fill-opacity:1;stroke-width:0.80000001"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/succeed.svg-c70f0a6f3d9b2864e4771942f0762307.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/succeed.svg"
dest_files=[ "res://.import/succeed.svg-c70f0a6f3d9b2864e4771942f0762307.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg61"
sodipodi:docname="tree.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata67">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs65" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview63"
showgrid="false"
inkscape:zoom="36.041667"
inkscape:cx="-2.3445086"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg61" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path57"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="m 16,8.0000002 v -6.4 h -5.6 v 2.4 H 5.6 v -2.4 H 0 v 6.4 h 5.6 v -2.4 H 7.2 V 13.6 h 3.2 V 16 H 16 V 9.6000002 H 10.4 V 12 H 8.7999998 V 5.6000002 H 10.4 v 2.4 z"
id="path59"
style="fill:#b2a5ef;fill-opacity:1;stroke-width:0.80000001"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -1,35 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/tree.svg-c0b20ed88b2fe300c0296f7236049076.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/tree.svg"
dest_files=[ "res://.import/tree.svg-c0b20ed88b2fe300c0296f7236049076.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1,8 +0,0 @@
extends BeehaveTree
class_name BeehaveNode, "../icons/action.svg"
enum { SUCCESS, FAILURE, RUNNING }
func tick(actor, blackboard):
pass

View file

@ -1,84 +0,0 @@
extends BeehaveTree
class_name BeehaveRoot, "../icons/tree.svg"
const Blackboard = preload("../blackboard.gd")
const SUCCESS = 0
const FAILURE = 1
const RUNNING = 2
enum ProcessMode {
PHYSICS_PROCESS,
IDLE,
MANUAL
}
export (ProcessMode) var process_mode = ProcessMode.PHYSICS_PROCESS setget set_process_mode
export (bool) var enabled = true
export (NodePath) var actor_node_path
var actor : Node
onready var blackboard = Blackboard.new()
func _ready():
if self.get_child_count() != 1:
push_error("Beehave error: Root %s should have one child (NodePath: %s)" % [self.name, self.get_path()])
disable()
return
actor = get_parent()
if actor_node_path:
actor = get_node(actor_node_path)
set_process_mode(self.process_mode)
func _process(delta):
tick(delta)
func _physics_process(delta):
tick(delta)
func tick(delta):
blackboard.set("delta", delta)
var status = self.get_child(0).tick(actor, blackboard)
if status != RUNNING:
blackboard.set("running_action", null)
func get_running_action():
if blackboard.has("running_action"):
return blackboard.get("running_action")
return null
func get_last_condition():
if blackboard.has("last_condition"):
return blackboard.get("last_condition")
return null
func get_last_condition_status():
if blackboard.has("last_condition_status"):
var status = blackboard.get("last_condition_status")
if status == SUCCESS:
return "SUCCESS"
elif status == FAILURE:
return "FAILURE"
else:
return "RUNNING"
return ""
func enable():
self.enabled = true
set_process_mode(self.process_mode)
func disable():
self.enabled = false
set_process(self.enabled)
set_physics_process(self.enabled)
func set_process_mode(value):
process_mode = value
set_process(process_mode == ProcessMode.IDLE)
set_physics_process(process_mode == ProcessMode.PHYSICS_PROCESS)

View file

@ -1,3 +0,0 @@
extends Node
class_name BeehaveTree

View file

@ -1,8 +0,0 @@
extends BeehaveNode
class_name Composite, "../../icons/category_composite.svg"
func _ready():
if self.get_child_count() < 1:
push_error("BehaviorTree Error: Composite %s should have at least one child (NodePath: %s)" % [self.name, self.get_path()])

View file

@ -1,18 +0,0 @@
extends Composite
class_name SelectorComposite, "../../icons/selector.svg"
func tick(actor, blackboard):
for c in get_children():
var response = c.tick(actor, blackboard)
if c is ConditionLeaf:
blackboard.set("last_condition", c)
blackboard.set("last_condition_status", response)
if response != FAILURE:
if c is ActionLeaf and response == RUNNING:
blackboard.set("running_action", c)
return response
return FAILURE

View file

@ -1,33 +0,0 @@
# Special implementation of a selector that will
# "wait" for running nodes and will not re-attempt
# to execute previous nodes until that node is either
# FAILED or SUCCEEDED
extends Composite
class_name SelectorStarComposite, "../../icons/selector_star.svg"
var last_execution_index = 0
func tick(actor, blackboard):
for c in get_children():
if c.get_index() < last_execution_index:
continue
var response = c.tick(actor, blackboard)
if c is ConditionLeaf:
blackboard.set("last_condition", c)
blackboard.set("last_condition_status", response)
if response != FAILURE:
if c is ActionLeaf and response == RUNNING:
blackboard.set("running_action", c)
if response == SUCCESS:
last_execution_index = 0
return response
else:
last_execution_index += 1
last_execution_index = 0
return FAILURE

View file

@ -1,18 +0,0 @@
extends Composite
class_name SequenceComposite, "../../icons/sequencer.svg"
func tick(actor, blackboard):
for c in get_children():
var response = c.tick(actor, blackboard)
if c is ConditionLeaf:
blackboard.set("last_condition", c)
blackboard.set("last_condition_status", response)
if response != SUCCESS:
if c is ActionLeaf and response == RUNNING:
blackboard.set("running_action", c)
return response
return SUCCESS

View file

@ -1,35 +0,0 @@
# Special implementation of sequencer who will execute
# successful nodes only once until all nodes were successful
extends Composite
class_name SequenceStarComposite, "../../icons/sequencer_star.svg"
var successful_index = 0
func tick(actor, blackboard):
for c in get_children():
if c.get_index() < successful_index:
continue
var response = c.tick(actor, blackboard)
if c is ConditionLeaf:
blackboard.set("last_condition", c)
blackboard.set("last_condition_status", response)
if response != SUCCESS:
if response == FAILURE:
successful_index = 0
if c is ActionLeaf and response == RUNNING:
blackboard.set("running_action", c)
return response
else:
successful_index += 1
if successful_index == get_child_count():
successful_index = 0
return SUCCESS
else:
successful_index = 0
return FAILURE

View file

@ -1,8 +0,0 @@
extends BeehaveNode
class_name Decorator, "../../icons/category_decorator.svg"
func _ready():
if self.get_child_count() != 1:
push_error("Beehave Error: Decorator %s should have only one child (NodePath: %s)" % [self.name, self.get_path()])

View file

@ -1,11 +0,0 @@
extends Decorator
class_name AlwaysFailDecorator, "../../icons/fail.svg"
func tick(action, blackboard):
for c in get_children():
var response = c.tick(action, blackboard)
if response == RUNNING:
return RUNNING
return FAILURE

View file

@ -1,17 +0,0 @@
extends Decorator
class_name InverterDecorator, "../../icons/inverter.svg"
func tick(action, blackboard):
for c in get_children():
var response = c.tick(action, blackboard)
if response == SUCCESS:
return FAILURE
if response == FAILURE:
return SUCCESS
if c is Leaf and response == RUNNING:
blackboard.set("running_action", c)
return RUNNING

View file

@ -1,19 +0,0 @@
extends Decorator
class_name LimiterDecorator, "../../icons/limiter.svg"
onready var cache_key = 'limiter_%s' % self.get_instance_id()
export (float) var max_count = 0
func tick(actor, blackboard):
var current_count = blackboard.get(cache_key)
if current_count == null:
current_count = 0
if current_count <= max_count:
blackboard.set(cache_key, current_count + 1)
return self.get_child(0).tick(actor, blackboard)
else:
return FAILED

View file

@ -1,11 +0,0 @@
extends Decorator
class_name AlwaysSucceedDecorator, "../../icons/succeed.svg"
func tick(action, blackboard):
for c in get_children():
var response = c.tick(action, blackboard)
if response == RUNNING:
return RUNNING
return SUCCESS

View file

@ -1,3 +0,0 @@
extends Leaf
class_name ActionLeaf, "../../icons/action.svg"

View file

@ -1,3 +0,0 @@
extends Leaf
class_name ConditionLeaf, "../../icons/condition.svg"

View file

@ -1,3 +0,0 @@
extends BeehaveNode
class_name Leaf, "../../icons/action.svg"

View file

@ -1,7 +0,0 @@
[plugin]
name="Beehave"
description="🐝 Behaviour Tree addon for Godot Engine"
author="bitbrain"
version="1.2.0"
script="plugin.gd"

View file

@ -1,5 +0,0 @@
tool
extends EditorPlugin
func _init():
print("Beehave initialized!")

View file

@ -1,70 +0,0 @@
# Godot Version Manager
<img src="https://raw.githubusercontent.com/fcazalet/godot-version-management/main/icon.png" width="64" height="64">
This addon is for developpers that want a centralized place for version naming / build number and then display it in game.
It allow you to configure version and build in project settings.
These configurations are synchronized to all existing export of your project.
Moreover configurations can be loaded for in game display.
## How to install it
You can find this addon in Godot AssetLibrary
See the Godot Addon install section : https://docs.godotengine.org/en/stable/tutorials/plugins/editor/installing_plugins.html
## How to use it for exports
Once the addon activated it add two entry in your project configuration:
- Application / Config / Version as String (application/config/version default to 0.0.1)
- Application / Config / Build as Integer (application/config/build default to 1)
You can change the version and the build numbers.
It will update all your exports versions value to the project config value.
Then you need to reload the project (Project / Reload current project).
See below section to know why you need to reload project.
For Android exports:
* version is version/name
* build is version/code
For iOS and MacOS exports:
* version is application/short_version
* build is application/version
For Windows Desktop exports:
* version is application/file_version and application/product_version
For HTML5 and UWP exports no versions specified.
## How to use it for in game display
The version and build numbers can be accessed for in game use like that:
```GDScript
# To get version string
var version = ProjectSettings.get_setting("application/config/version")
# To get build number
var build = ProjectSettings.get_setting("application/config/build")
```
## Why I need to reload project ?
The GodotVersionManager addon update the export-presets.cfg file.
Because of Godot keep in memory ExportsSettings and do not reload it from export-presets.cfg file you will need to reload your project.
When project is loaded Godot load in memory the export-presets.cfg .
## Support Me
You to buy me a coffee ?
<a href='https://ko-fi.com/J3J2COV54' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://cdn.ko-fi.com/cdn/kofi3.png?v=3' border='0' alt='Buy Me a Coffee' /></a>

View file

@ -1,78 +0,0 @@
# By Erasor
tool
extends EditorPlugin
const PLUGIN_NAME = "Godot-Version-Manager"
const DEBUG = true
# Use same name as https://github.com/godotengine/godot/pull/35555
const PROJECT_VERSION_SETTING = "application/config/version"
const PROJECT_BUILD_SETTING = "application/config/build"
const EXPORT_PRESETS_FILE = "res://export_presets.cfg"
var current_version
var current_build
func _enter_tree():
if not ProjectSettings.has_setting(PROJECT_VERSION_SETTING):
ProjectSettings.set_setting(PROJECT_VERSION_SETTING, "0.0.1")
if not ProjectSettings.has_setting(PROJECT_BUILD_SETTING):
ProjectSettings.set_setting(PROJECT_BUILD_SETTING, 1)
current_version = ProjectSettings.get_setting(PROJECT_VERSION_SETTING)
current_build = ProjectSettings.get_setting(PROJECT_BUILD_SETTING)
func _exit_tree():
# Do not remove the verson config, may conflict with https://github.com/godotengine/godot/pull/35555
pass
func apply_changes():
_update_export_presets()
func save_external_data():
_update_export_presets()
func _update_export_presets():
# If config version changed, update all exports
if ProjectSettings.get_setting(PROJECT_VERSION_SETTING) != current_version:
var export_config: ConfigFile = ConfigFile.new()
var err = export_config.load(EXPORT_PRESETS_FILE)
if err == OK:
# Loop limited to 100 exports
for i in range(0, 100):
var section = "preset." + str(i)
if export_config.has_section(section):
plugin_log("Update Export " + export_config.get_value(section, "platform"))
# Update Android exports configs
if export_config.get_value(section, "platform") == "Android":
export_config.set_value(section + ".options", 'version/name', ProjectSettings.get_setting(PROJECT_VERSION_SETTING))
export_config.set_value(section + ".options", 'version/code', ProjectSettings.get_setting(PROJECT_BUILD_SETTING))
if export_config.get_value(section, "platform") == "iOS" or export_config.get_value(section, "platform") == "Mac OSX":
export_config.set_value(section + ".options", 'application/short_version', ProjectSettings.get_setting(PROJECT_VERSION_SETTING))
export_config.set_value(section + ".options", 'application/version', ProjectSettings.get_setting(PROJECT_BUILD_SETTING))
if export_config.get_value(section, "platform") == "UWP":
# TODO parsing of version to minor/major
pass
if export_config.get_value(section, "platform") == "Windows Desktop":
export_config.set_value(section + ".options", 'application/file_version', ProjectSettings.get_setting(PROJECT_VERSION_SETTING))
export_config.set_value(section + ".options", 'application/product_version', ProjectSettings.get_setting(PROJECT_VERSION_SETTING))
else:
break
err = export_config.save(EXPORT_PRESETS_FILE)
ProjectSettings.save()
if err == OK:
plugin_log("All exports updated")
else:
plugin_log("Error saving " + EXPORT_PRESETS_FILE + ", exports not updated")
else:
plugin_log('Error open ' + EXPORT_PRESETS_FILE)
func plugin_log(message):
if (DEBUG):
var time : Dictionary = OS.get_datetime()
var date_string : String = "%02d:%02d" % [time.hour, time.minute]
print(date_string, " - ", PLUGIN_NAME, " - ", message)

View file

@ -1,8 +0,0 @@
[plugin]
name="Godot-Version-Manager"
description="Godot plugin to manage versions for exports.
It centralize the version number in project."
author="Erasor"
version="1.0.0"
script="godot_version_manager.gd"

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 Tomek
Copyright (c) 2022 Addons By Aura
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View file

@ -0,0 +1,47 @@
@icon("../icons/animation_state.png")
class_name AnimationState
extends State
## Plays an animation from the linked [member animation_player].
## The name of the animation to be played comes from the name of the node.
## Emitted when the animation started by this state has finished playing.
signal animation_finished
@export_range(0, 20, 1, "or_greater")
## How many times to play before emitting [signal State.choose_new_substate_requested].
## [b]If set to zero, it will go forever.[/b]
var loops := 0
var _loops_left := 0
func _init() -> void:
set_meta(&"description", "Plays the named animation from the linked AnimationPlayer.")
func _on_animation_finished(animation_name: StringName) -> void:
if animation_name != name: return
if loops == 0:
animation_player.play(name)
elif _loops_left <= 0:
choose_new_substate_requested.emit()
else:
_loops_left -= 1
animation_player.play(name)
func enter(set_target: Node, set_animation_player: AnimationPlayer, set_debug_mode := false) -> void:
super(set_target, set_animation_player, set_debug_mode)
assert(animation_player != null, "AnimationPlayer must be set, either directly or by an ancestor.")
animation_player.animation_finished.connect(_on_animation_finished)
_loops_left = loops - 1
animation_player.play(name)
func exit() -> void:
super()
animation_player.animation_finished.disconnect(_on_animation_finished)
animation_player.stop()

View file

@ -0,0 +1,139 @@
@icon("../icons/state_machine_debugger.png")
class_name StateMachineDebugger
extends Tree
## Displays an interactive state tree.
# This source code is a mess, I'm trying to make it less so.
@export
## Root state machine to reference.
var state_machine_root : State:
set(value):
state_machine_root = value
_setup_tree()
@export
## What color to make the item when a state is active.
var active_color := Color.FOREST_GREEN
@export
## Forcefully switch states by double-clicking them.
## Due to its nature, it has the potential to be destructive
## and/ or not behave completely how one might expect.
var allow_state_switching := false:
set(value):
allow_state_switching = value
if allow_state_switching:
item_activated.connect(_on_item_activated)
else:
item_activated.disconnect(_on_item_activated)
@export_group("Signals", "signal_")
@export
## Show when a state emits a relevant signal.
var signal_show := false:
set(value):
signal_show = value
if state_machine_root == null:
return
if signal_show:
connect_signals()
else:
disconnect_signals()
@export
## Which signals to connect to on each state, as long as they exist.
var signal_connections : Array[StringName] = [
&"entered",
&"exited",
&"choose_new_substate_requested",
&"animation_finished",
]
@export
## Delay before hiding signal.
var signal_hide_delay := 1.0
func _init() -> void:
columns = 2
func change_state_by_path(path: NodePath) -> void:
if not state_machine_root.has_node(path):
return
var state := state_machine_root
for i in path.get_name_count():
var part := path.get_name(i)
state = await state.change_state_name(part)
func connect_signals(state := state_machine_root) -> void:
if not state.has_meta(&"tree_item"):
return
for signal_name in signal_connections:
if state.has_signal(signal_name) and not \
state.is_connected(signal_name, _on_state_signal):
state.connect(signal_name, _on_state_signal.bind(signal_name, state.get_meta(&"tree_item")))
for child in(state.get_children() as Array[State]):
connect_signals(child)
func disconnect_signals(state := state_machine_root) -> void:
for signal_name in signal_connections:
if state.has_signal(signal_name) and \
state.is_connected(signal_name, _on_state_signal):
state.disconnect(signal_name, _on_state_signal)
for child in (state.get_children() as Array[State]):
disconnect_signals(child)
func _setup_tree(state := state_machine_root, parent_item: TreeItem = null) -> void:
if state == state_machine_root:
if get_root() != null:
disconnect_signals()
clear()
if state_machine_root == null:
return
# state.print_tree_pretty()
# TODO: add icons
var item := create_item(parent_item)
item.set_text(0, state.name)
item.set_metadata(0, state)
state.set_meta(&"tree_item", item)
connect_signals(state)
for child in (state.get_children() as Array[State]):
_setup_tree(child, item)
func _on_item_activated() -> void:
change_state_by_path(state_machine_root.get_path_to(
get_selected().get_metadata(0) as State))
func _on_state_signal(signal_name: StringName, state_item: TreeItem) -> void:
match signal_name:
&"entered":
for i in columns:
state_item.set_custom_color(i, active_color)
&"exited":
for i in columns:
state_item.clear_custom_color(i)
if not signal_show:
return
state_item.set_text(1, signal_name)
var timer := state_item.get_metadata(1) as SceneTreeTimer
if timer != null:
timer.timeout.disconnect(state_item.set_text)
timer = get_tree().create_timer(signal_hide_delay)
timer.timeout.connect(state_item.set_text.bind(1, ""))
state_item.set_metadata(1, timer)

View file

@ -0,0 +1,34 @@
@icon("../icons/random_state.png")
class_name RandomState
extends State
## Activates a random one of its substates.
## Useful in conjuction with [AnimationState] for random idles.
@export
## When one of its children asks for a state change,
## instead of picking another one itself, it defers that choice to its parent.
## Allows for nested random states for finer control over flow and probability.
var defer_choice := false
func _init() -> void:
set_meta(&"description", "Pseudo-randomly picks a state to start.")
func _ready() -> void:
randomize()
super()
# You can define which state is picked automatically (like on enter).
# If you would like to call it yourself, use the public version (choose_substate).
func _choose_substate() -> State:
if get_child_count() == 0:
return null
if defer_choice and _active_substate != null:
choose_new_substate_requested.emit()
return null
return get_child(randi() % get_child_count()) as State

View file

@ -0,0 +1,43 @@
@icon("../icons/sequence_state.png")
class_name SequenceState
extends State
## Executes its children in order, one after the other. Like an [Array] in [State] form!
@export_range(0, 20, 1, "or_greater")
## How many times the sequence should be looped through before emitting [signal State.choose_new_substate_requested].
## [b]If set to zero, it will go forever.[/b]
var loops := 1
var _loops_left := 0
func _init() -> void:
set_meta(&"description", "Starts its children one after the other in order, \
waiting for each one to be done before starting the next.")
# You can define which state is picked automatically (like on [method enter]).
# If you would like to call it yourself, use the public version ([method choose_substate]).
func _choose_substate() -> State:
if _active_substate == null:
return get_child(0) as State if get_child_count() > 0 else null
if _active_substate.get_index() == get_child_count() - 1:
if loops == 0:
return get_child(0) as State
elif _loops_left == 0:
choose_new_substate_requested.emit()
return null
else:
_loops_left -= 1
return get_child(0) as State
return get_child(_active_substate.get_index() + 1) as State
func enter(set_target: Node, set_animation_player: AnimationPlayer, set_debug := false) -> void:
super(set_target, set_animation_player, set_debug)
_loops_left = loops - 1

View file

@ -0,0 +1,291 @@
@icon("../icons/state.png")
class_name State
extends Node
## The bare, basic state. Use it if you want total control over the state-flow.
##
## Properties marked as [b](inherited)[/b] are passed to substates,
## meaning you don't have to set it on each individual state, only the root.
## You can override it of course, and that will be passed to all of [i]its[/i] children.
## Emitted between [method _enter] and [method _after_enter].
signal entered
## Emitted after [method _exit].
signal exited
## Emitted between [method _update] and [method _after_update]
signal updated
## Switched active substates.
signal active_substate_changed(new: State, old: State)
## A request for the parent to pick a new substate to activate.
## Mainly used by children of [RandomState], such as an [AnimationState].
signal choose_new_substate_requested
## Active or not.
enum Status {
INACTIVE, ## Inactive
ACTIVE, ## Active
}
@export
## The node that the states will act upon. [b](inherited)[/b]
## Doesn't actually get used in the addon scripts, it's just
## included for your convenience when scripting your own behaviour.
var target: Node:
set(value):
target = value
if _active_substate != null:
_active_substate.target = target
@export
## Where to play animations from. [b](inherited)[/b]
var animation_player: AnimationPlayer
@export_range(0, 120, 1, "or_greater")
## How many seconds the state should be active before emitting [signal choose_new_substate_requested].
## [b]If set to zero, it will go forever.[/b]
var timer := 0.0
@export
## Whether to force-restart the chosen substate in the callback for [signal choose_new_substate_requested] if it was already active.
var force := true
@export
## The state will not be activated under any circumstances.
var disabled := false:
set(value):
disabled = value
var root := is_root()
if root and not disabled:
enter(target, animation_player, debug_mode)
elif status == Status.ACTIVE:
exit()
@export
## Print a message avery time there is a state change. [b](inherited)[/b]
var debug_mode := false:
set(value):
debug_mode = value
if _active_substate != null:
_active_substate.debug_mode = debug_mode
## The status of this state, ie. whether it's running or not.
var status := Status.INACTIVE
# The substate that is currently active, if any.
var _active_substate: State:
set(value):
if _active_substate != null:
_active_substate.choose_new_substate_requested.disconnect(_on_choose_new_substate_requested)
active_substate_changed.emit(value, _active_substate)
_active_substate = value
if _active_substate != null:
_active_substate.choose_new_substate_requested.connect(_on_choose_new_substate_requested)
# If a timer is set, the object will be stored here.
var _timer_object: SceneTreeTimer
#########################
### VIRTUAL METHODS ###
#########################
func _init() -> void:
set_physics_process(false)
set_meta(&"description", "A bare, basic state - will only ever automatically start its first child.")
func _ready() -> void:
for child in get_children():
assert(child is State, "A State should not have any children that are not other States.")
if is_root() and not disabled:
enter(target, animation_player, debug_mode)
func _physics_process(delta: float) -> void:
if status == Status.INACTIVE:
set_physics_process(false)
return
update(delta)
## [b][parents, then children][/b] Called when the state is activated.
func _enter() -> void:
pass
## [b][children, then parents][/b] Called after the state is activated.
func _after_enter() -> void:
pass
## [b][parents, then children][/b] Called every physics frame (only when the state is active, of course).
func _update(delta: float) -> void:
pass
## [b][children, then parents][/b] Called at the end of every physics frame.
func _after_update(delta: float) -> void:
pass
## [b][parents, then children][/b] Called before the state is deactivated.
func _before_exit() -> void:
pass
## [b][children, then parents][/b] Called when the state is deactivated.
func _exit() -> void:
pass
## You can define which state is picked automatically (like on [method enter]).
## Return `null` to not change substate at all.
## If you would like to call it yourself, use the public version ([method choose_substate]).
func _choose_substate() -> State:
return get_child(0) as State if get_child_count() > 0 else null
########################
### PUBLIC METHODS ###
########################
## Switch to the specified substate by name. It is just a shortcut to [method change_state_node].
func change_state_name(name: String, force := false) -> State:
return await change_state_node(get_node_or_null(name) as State, force)
## Switch to the specified substate by node. If it is not a direct child, nothing will happen.
## If `force`, it will start a state again even if it's already running.
## It waits for the next [signal updated] to make sure it's not
## switching all over the place in one tick.
func change_state_node(node: State, force := false) -> State:
await updated
if (
node == null
or node.disabled
or (node.status != Status.INACTIVE and not force)
or node.get_parent() != self
):
return node
var old := _active_substate
_active_substate = node
if old != null:
old.exit()
_active_substate.enter(target, animation_player, debug_mode)
if debug_mode:
print(
("FORCE " if force else "") +
"STATE: " +
str(get_root().get_parent().get_path_to(_active_substate))
)
return _active_substate
## Return the currently active substate, if any.
func get_active_substate() -> State:
return _active_substate
## Public [method _choose_substate].
func choose_substate() -> State:
return _choose_substate()
## Shortcut for `change_state_node(choose_substate())`.
func change_to_next_substate(force := false) -> void:
await change_state_node(choose_substate(), force)
## Whether this state is the root of the state tree,
## ie. it is the common ancestor of all the others.
func is_root() -> bool:
# If your parent is not a state, then you are the root.
return not get_parent() is State
## Get the root state.
func get_root() -> State:
var node: State = self
while not node.is_root():
node = node.get_parent() as State
return node
## Runs [method _enter] and [method _after_enter],
## not a good idea to call it yourself unless you really know what you're doing.
func enter(set_target: Node, set_animation_player: AnimationPlayer, set_debug_mode: bool) -> void:
for child in get_children():
assert(child is State, "A State should not have any children that are not other States.")
_enter()
entered.emit()
status = Status.ACTIVE
if timer != 0:
_timer_object = get_tree().create_timer(timer)
_timer_object.timeout.connect(_on_timer_timeout)
set_physics_process(is_root())
# Only set them if they're not being overridden
if target == null:
target = set_target
if animation_player == null:
animation_player = set_animation_player
if debug_mode == false:
debug_mode = set_debug_mode
change_to_next_substate()
_after_enter()
## Runs [method _update] and [method _after_update],
## not a good idea to call it yourself unless you really know what you're doing.
func update(delta: float) -> void:
_update(delta)
updated.emit()
if _active_substate != null:
_active_substate.update(delta)
_after_update(delta)
## Runs [method _exit] and [method _before_exit],
## not a good idea to call it yourself unless you really know what you're doing.
func exit() -> void:
_before_exit()
status = Status.INACTIVE
if _active_substate != null:
_active_substate.exit()
_active_substate = null
if is_instance_valid(_timer_object):
_timer_object.timeout.disconnect(_on_timer_timeout)
_timer_object = null
_exit()
exited.emit()
set_physics_process(false)
#########################
### PRIVATE METHODS ###
#########################
#################
### CALLBACKS ###
#################
func _on_choose_new_substate_requested() -> void:
change_to_next_substate(force)
func _on_timer_timeout() -> void:
choose_new_substate_requested.emit()

View file

@ -0,0 +1,14 @@
extends State
const NEXT_STATE_ACTION = "demo_next_state"
func _enter() -> void:
if InputMap.has_action(NEXT_STATE_ACTION):
return
var input_event := InputEventKey.new()
input_event.keycode = KEY_TAB
InputMap.add_action(NEXT_STATE_ACTION)
InputMap.action_add_event(NEXT_STATE_ACTION, input_event)

View file

@ -0,0 +1,218 @@
[gd_scene load_steps=17 format=3 uid="uid://clnliyc6fmqy6"]
[ext_resource type="Script" path="res://addons/simple-state/classes/debugger.gd" id="1_rqf1w"]
[ext_resource type="Script" path="res://addons/simple-state/demo/description_box.gd" id="2_gktik"]
[ext_resource type="Script" path="res://addons/simple-state/classes/sequence_state.gd" id="3_4afa7"]
[ext_resource type="Script" path="res://addons/simple-state/demo/demo.gd" id="3_x0hcs"]
[ext_resource type="Script" path="res://addons/simple-state/classes/random_state.gd" id="4_wxjoe"]
[ext_resource type="Script" path="res://addons/simple-state/demo/emit_next.gd" id="6_kxcgl"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ysqm7"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_wxupu"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7gdgn"]
draw_center = false
border_width_left = 1
border_width_top = 1
border_width_right = 1
border_width_bottom = 1
[sub_resource type="Animation" id="Animation_5pgem"]
resource_name = "RESET"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("ColorRect:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 1)]
}
[sub_resource type="Animation" id="Animation_mwhj1"]
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("ColorRect:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(0, 0, 0, 1)]
}
[sub_resource type="Animation" id="Animation_yyph0"]
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("ColorRect:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(0, 0, 1, 1)]
}
[sub_resource type="Animation" id="Animation_xmkhy"]
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("ColorRect:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(0, 1, 0, 1)]
}
[sub_resource type="Animation" id="Animation_4pwkk"]
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("ColorRect:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 0, 0, 1)]
}
[sub_resource type="Animation" id="Animation_gt7hj"]
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("ColorRect:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 0, 1)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_01hf1"]
_data = {
"RESET": SubResource("Animation_5pgem"),
"black": SubResource("Animation_mwhj1"),
"blue": SubResource("Animation_yyph0"),
"green": SubResource("Animation_xmkhy"),
"red": SubResource("Animation_4pwkk"),
"yellow": SubResource("Animation_gt7hj")
}
[node name="SimpleStateDemo" type="Panel"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 10
theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 10
theme_override_constants/margin_bottom = 10
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 10
[node name="StateMachineDebugger" type="Tree" parent="MarginContainer/HBoxContainer" node_paths=PackedStringArray("state_machine_root")]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/relationship_line_width = 2
theme_override_constants/draw_guides = 0
theme_override_styles/panel = SubResource("StyleBoxEmpty_ysqm7")
theme_override_styles/focus = SubResource("StyleBoxEmpty_wxupu")
theme_override_styles/selected = SubResource("StyleBoxFlat_7gdgn")
theme_override_styles/selected_focus = SubResource("StyleBoxFlat_7gdgn")
select_mode = 1
script = ExtResource("1_rqf1w")
state_machine_root = NodePath("../../Root")
allow_state_switching = true
signal_show = true
[node name="DescriptionBox" type="Label" parent="MarginContainer/HBoxContainer" node_paths=PackedStringArray("tree")]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
autowrap_mode = 3
script = ExtResource("2_gktik")
tree = NodePath("../StateMachineDebugger")
show_descriptions = 2
[node name="InputInfo" type="Label" parent="MarginContainer/HBoxContainer/DescriptionBox"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -349.0
offset_top = -78.0
grow_horizontal = 0
grow_vertical = 0
text = "MOUSE CLICK on state: select
DOUBLE MOUSE CLICK on state: start
TAB: next substate (only has effect on leaves)"
horizontal_alignment = 2
vertical_alignment = 2
[node name="ColorRect" type="ColorRect" parent="MarginContainer"]
custom_minimum_size = Vector2(50, 50)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 8
[node name="AnimationPlayer" type="AnimationPlayer" parent="MarginContainer"]
libraries = {
"": SubResource("AnimationLibrary_01hf1")
}
[node name="Root" type="Node" parent="MarginContainer" node_paths=PackedStringArray("target", "animation_player")]
script = ExtResource("3_x0hcs")
target = NodePath("")
animation_player = NodePath("../AnimationPlayer")
[node name="SequenceState" type="Node" parent="MarginContainer/Root"]
script = ExtResource("3_4afa7")
[node name="RandomState" type="Node" parent="MarginContainer/Root/SequenceState"]
script = ExtResource("4_wxjoe")
defer_choice = true
[node name="red" type="Node" parent="MarginContainer/Root/SequenceState/RandomState"]
script = ExtResource("6_kxcgl")
[node name="yellow" type="Node" parent="MarginContainer/Root/SequenceState/RandomState"]
script = ExtResource("6_kxcgl")
[node name="green" type="Node" parent="MarginContainer/Root/SequenceState"]
script = ExtResource("6_kxcgl")
[node name="blue" type="Node" parent="MarginContainer/Root/SequenceState"]
script = ExtResource("6_kxcgl")
[node name="black" type="Node" parent="MarginContainer/Root"]
script = ExtResource("6_kxcgl")
timer = 1.0
metadata/description = "Will never start automatically, due to its parent being only a normal state."

View file

@ -0,0 +1,98 @@
extends Label
## Mode of description box rendering.
enum DisplayModes {
NONE, ## Description box completely hidden.
ACTIVE, ## Show descriptions of all active states.
SELECTION, ## Show description of last selected state (also includes manual switches).
}
@export
## [StateMachineDebugger] to reference.
var tree : StateMachineDebugger:
set(value):
tree = value
if show_descriptions == DisplayModes.SELECTION and \
not tree.item_selected.is_connected(_on_tree_item_selected):
tree.item_selected.connect(_on_tree_item_selected)
@export
## Show a description of a state.
## Looks for a string metadata value by the name of [code]description[/code] on each state.
var show_descriptions := DisplayModes.NONE:
set(value):
show_descriptions = value
match show_descriptions:
DisplayModes.NONE:
visible = false
DisplayModes.ACTIVE:
visible = true
if not is_instance_valid(tree):
return
if tree.item_selected.is_connected(_on_tree_item_selected):
tree.item_selected.disconnect(_on_tree_item_selected)
DisplayModes.SELECTION:
visible = true
if not is_instance_valid(tree):
return
if not tree.item_selected.is_connected(_on_tree_item_selected):
tree.item_selected.connect(_on_tree_item_selected)
var _active_states : Array[State] = []
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
visible = show_descriptions != DisplayModes.NONE
connect_signals()
func connect_signals(state := tree.state_machine_root) -> void:
if not state.has_meta(&"tree_item"):
return
for signal_name in tree.signal_connections:
if state.has_signal(signal_name) and not \
state.is_connected(signal_name, _on_state_signal):
state.connect(signal_name, _on_state_signal.bind(signal_name, state))
for child in(state.get_children() as Array[State]):
connect_signals(child)
func disconnect_signals(state := tree.state_machine_root) -> void:
for signal_name in tree.signal_connections:
if state.has_signal(signal_name) and \
state.is_connected(signal_name, _on_state_signal):
state.disconnect(signal_name, _on_state_signal)
for child in (state.get_children() as Array[State]):
disconnect_signals(child)
func _set_description_from_active_states() -> void:
text = ""
for state in _active_states:
text += ("" if state.is_root() else "\n\n") + \
state.name as String + \
": " + \
state.get_meta(&"description", "") as String
func _on_tree_item_selected() -> void:
text = tree.get_selected() \
.get_metadata(0).get_meta(&"description", "")
func _on_state_signal(signal_name: StringName, state: State) -> void:
match signal_name:
&"entered":
if show_descriptions == DisplayModes.ACTIVE:
_active_states.push_back(state)
_set_description_from_active_states()
&"exited":
if show_descriptions == DisplayModes.ACTIVE:
_active_states.pop_back()
_set_description_from_active_states()

View file

@ -0,0 +1,6 @@
extends AnimationState
func _update(_delta: float) -> void:
if Input.is_action_just_pressed(get_root().NEXT_STATE_ACTION):
choose_new_substate_requested.emit()

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cna1s8hi8xc58"
path="res://.godot/imported/animation_state.png-5f10255295e45d80e555d2885de83e22.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/simple-state/icons/animation_state.png"
dest_files=["res://.godot/imported/animation_state.png-5f10255295e45d80e555d2885de83e22.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

View file

@ -0,0 +1,2 @@
[InternetShortcut]
URL=http://www.kenney.nl/

View file

@ -0,0 +1,2 @@
[InternetShortcut]
URL=https://www.patreon.com/kenney/

View file

@ -0,0 +1,22 @@
Board Game Icons (1.0)
Created/distributed by Kenney (www.kenney.nl)
Creation date: 10-01-2022
------------------------------
License: (Creative Commons Zero, CC0)
http://creativecommons.org/publicdomain/zero/1.0/
This content is free to use in personal, educational and commercial projects.
Support us by crediting Kenney or www.kenney.nl (this is not mandatory)
------------------------------
Donate: http://support.kenney.nl
Patreon: http://patreon.com/kenney/
Follow on Twitter for updates:
http://twitter.com/KenneyNL

View file

@ -0,0 +1,14 @@
###############################################################################
Game icon pack by Kenney Vleugels (www.kenney.nl)
------------------------------
License (CC0)
http://creativecommons.org/publicdomain/zero/1.0/
You may use these graphics in personal and commercial projects.
Credit (Kenney or www.kenney.nl) would be nice but is not mandatory.
###############################################################################

View file

@ -0,0 +1,20 @@
Pictogrammers Free License
--------------------------
This icon collection is released as free, open source, and GPL friendly by
the [Pictogrammers](http://pictogrammers.com/). You may use it
for commercial projects, open source projects, or anything really.
# Icons: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
Some of the icons are redistributed under the Apache 2.0 license. All other
icons are either redistributed under their respective licenses or are
distributed under the Apache 2.0 license.
# Fonts: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
All web and desktop fonts are distributed under the Apache 2.0 license. Web
and desktop fonts contain some icons that are redistributed under the Apache
2.0 license. All other icons are either redistributed under their respective
licenses or are distributed under the Apache 2.0 license.
# Code: MIT (https://opensource.org/licenses/MIT)
The MIT license applies to all non-font and non-icon files.

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cgoc214akn2d6"
path="res://.godot/imported/random_state.png-0878745fbdc123f3f0d51012c73a7024.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/simple-state/icons/random_state.png"
dest_files=["res://.godot/imported/random_state.png-0878745fbdc123f3f0d51012c73a7024.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bcviu3dccvvm2"
path="res://.godot/imported/sequence_state.png-4718f2c926301319d99a0ccd15ff62fb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/simple-state/icons/sequence_state.png"
dest_files=["res://.godot/imported/sequence_state.png-4718f2c926301319d99a0ccd15ff62fb.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

View file

@ -0,0 +1,12 @@
Icon Sources
-----------
[0] Board Game Icons: https://kenney.nl/assets/board-game-icons
- state.png
- random_state.png
- sequence_state.png
[1] Game Icons: https://kenney.nl/assets/game-icons
- animation_state.png
[2] Pictogrammers: <https://pictogrammers.com/library/mdi/>
- state_machine_debugger.png (tinted)

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://msu07hn5ewo5"
path="res://.godot/imported/state.png-fa3dd722682a28f890f138dcc6e162af.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/simple-state/icons/state.png"
dest_files=["res://.godot/imported/state.png-fa3dd722682a28f890f138dcc6e162af.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b32u1sa3robj0"
path="res://.godot/imported/state_fullsize.png-41a4827bc36d7745ba55c17c0bc213e9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/simple-state/icons/state_fullsize.png"
dest_files=["res://.godot/imported/state_fullsize.png-41a4827bc36d7745ba55c17c0bc213e9.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dsglk01amsawf"
path="res://.godot/imported/state_machine_debugger.png-4af22f2c577f0756aa0b1d50ce679700.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/simple-state/icons/state_machine_debugger.png"
dest_files=["res://.godot/imported/state_machine_debugger.png-4af22f2c577f0756aa0b1d50ce679700.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

View file

@ -0,0 +1,7 @@
[plugin]
name="SimpleState"
description="A super-simple state machine. Lightweight and (hopefully) reliable."
author="AuraTheEnby"
version="1.3.2"
script="plugin.gd"

View file

@ -0,0 +1,25 @@
@tool
extends EditorPlugin
## It uses the icons provided by the scripts anyway, so
## we don't really need to specify the real ones here.
## Plus, it might help with enabling it before the project
## has been reloaded for the first time.
var placeholder_texture := PlaceholderTexture2D.new()
func _enter_tree() -> void:
add_custom_type("State", "Node", State, placeholder_texture)
add_custom_type("RandomState", "Node", RandomState, placeholder_texture)
add_custom_type("AnimationState", "Node", AnimationState, placeholder_texture)
add_custom_type("SequenceState", "Node", SequenceState, placeholder_texture)
add_custom_type("StateMachineDebugger", "Tree", StateMachineDebugger, placeholder_texture)
func _exit_tree() -> void:
remove_custom_type("State")
remove_custom_type("RandomState")
remove_custom_type("AnimationState")
remove_custom_type("SequenceState")
remove_custom_type("StateMachineDebugger")

View file

@ -0,0 +1,33 @@
# meta-default: true
extends _BASE_
# Called when the state is activated. (parents, then children)
func _enter() -> void:
pass
# Called after the state is activated. (children, then parents)
func _after_enter() -> void:
pass
# Called every physics frame (only when the state is active, of course). (parents, then children)
func _update(delta: float) -> void:
pass
# Called at the end of every physics frame. (children, then parents)
func _after_update(delta: float) -> void:
pass
# Called before the state is deactivated. (parents, then children)
func _before_exit() -> void:
pass
# Called when the state is deactivated. (children, then parents)
func _exit() -> void:
pass

View file

@ -0,0 +1,111 @@
[gd_scene load_steps=3 format=3 uid="uid://bbhv8iqdbkqbt"]
[ext_resource type="Script" path="res://scripts/license_gui.gd" id="1_esldu"]
[ext_resource type="Script" path="res://addons/simplelicense/api/LicenseManager.gd" id="2_cpb2k"]
[node name="LicenseGUI" type="Control"]
custom_minimum_size = Vector2(256, 256)
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_esldu")
load_locations = Array[String](["res://licenses", "res://addons/simplelicense/mod_example/licenses/"])
export_locations = Array[String](["user://licenses/game/", "user://licenses/mods/mod_1/"])
[node name="LicenseManager" type="Node" parent="."]
script = ExtResource("2_cpb2k")
[node name="background" type="Panel" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Label" type="Label" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.381076
anchor_right = 0.461806
anchor_bottom = 0.0401235
offset_left = 3.05176e-05
grow_horizontal = 2
text = "License Info"
metadata/_edit_use_anchors_ = true
[node name="Tree" type="Tree" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.00694444
anchor_top = 0.0462963
anchor_right = 0.404514
anchor_bottom = 0.987654
grow_vertical = 2
size_flags_horizontal = 2
hide_root = true
metadata/_edit_use_anchors_ = true
[node name="Text" type="TextEdit" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.434028
anchor_top = 0.0462963
anchor_right = 0.993056
anchor_bottom = 0.987654
offset_left = -8.0
grow_horizontal = 0
grow_vertical = 2
size_flags_horizontal = 3
editable = false
scroll_smooth = true
minimap_draw = true
metadata/_edit_use_anchors_ = true
[node name="btn_open_data_dir" type="Button" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.585069
anchor_top = 0.00308642
anchor_right = 0.696181
anchor_bottom = 0.0416667
grow_horizontal = 2
theme_override_font_sizes/font_size = 12
text = "Open Data Directory"
metadata/_edit_use_anchors_ = true
[node name="btn_save_licenses" type="Button" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.491319
anchor_top = 0.00308642
anchor_right = 0.56684
anchor_bottom = 0.0416667
grow_horizontal = 2
theme_override_font_sizes/font_size = 12
text = "Save Licenses"
metadata/_edit_use_anchors_ = true
[node name="op_locations" type="OptionButton" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.00694444
anchor_top = 0.00308642
anchor_right = 0.172743
anchor_bottom = 0.0416667
theme_override_font_sizes/font_size = 12
item_count = 2
popup/item_0/text = "a"
popup/item_0/id = 0
popup/item_1/text = "b"
popup/item_1/id = 1
metadata/_edit_use_anchors_ = true
[connection signal="item_activated" from="Tree" to="." method="_on_tree_item_activated"]
[connection signal="item_selected" from="Tree" to="." method="_on_tree_item_selected"]
[connection signal="pressed" from="btn_open_data_dir" to="." method="_on_btn_open_data_dir_pressed"]
[connection signal="pressed" from="btn_save_licenses" to="." method="_on_button_pressed"]
[connection signal="item_selected" from="op_locations" to="." method="_on_op_locations_item_selected"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://duvmbh55cyvev"
path="res://.godot/imported/Icon.png-451064bd72ea26ed7eb00aedd926556f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/simplelicense/Icon.png"
dest_files=["res://.godot/imported/Icon.png-451064bd72ea26ed7eb00aedd926556f.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

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 51 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dnr20t153it5i"
path="res://.godot/imported/Icon.svg-62b5bc5b7872f9c089f3b98f0084a03c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/simplelicense/Icon.svg"
dest_files=["res://.godot/imported/Icon.svg-62b5bc5b7872f9c089f3b98f0084a03c.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

View file

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View file

@ -0,0 +1,37 @@
A simple plugin, to make dealing with licensing simple.
Files: ./addons/simplelicense/*
License: CC0-1.0
Developed in Godot version: v4.0.beta.custom_build [166df0896]
Quick Example: (A License Viewer Scene, that you can also drop into one of your game scenes)
Run the Scene at
res://addons/simplelicense/GUI/LicenseGUI.tscn
look around, then
click on the "open data directory" button
then click on the "save licenses" button
and watch the data directory populate with license files
Quick Start:
1. Create a "LicenseLink" Resource file inside the
res://licenses/license_links/
2. Click on the the new Resource file, and try it out
There are docs on how to use it, so just F1 + LicenseLink, to find out more
3. Load license information
Create an instance of "LicenseManager" either in code or by adding the node to the scene
then call "load_license_information" on the LicenseManager
4. Export License information
call "export" function on the LicenseManager
it will populate the "user://" directory with your license files
one combined "COPYRIGHT.txt" file
and individual copyright files into "user://licenses/<license_identifier>.txt".
The license text will be formatted in the SPDX standard.
It's the way the Godot Engine does it.
in the Godot Editor: Help -> About Godot -> Third-party Licenses
There is more you can do, just visit the docs!
(Like support for loading mod's license information!)

View file

@ -0,0 +1,78 @@
class_name License
extends Resource
## Holds AUTO GENERATED License information
## SPDX-License-Identifier or similar to it. CASE SENSITIVE[br]
## Like "CC0-1.0"[br]
## See [url=https://spdx.org/licenses/]SPDX Identifier List[/url]
var identifier: String = ""
## The License's Name. [br]
## Like "CC0 1.0 Universal"
var name: String = ""
## License Terms; The text of a license file
var terms: String = ""
## Returns a string containing this license's information, formatted to [url=https://spdx.dev/resources/use/]SPDX Standards[/url]
func to_formatted_string() -> String:
return "License: {identifier}\n{terms}".format({
'identifier': identifier,
'terms': _add_line_padding(terms)
})
# wouldn't recomend using this, unless you know what your doing
# but if you do, this loads and parses all licenses (.txt files) in a directory,
# plus Godot's built-in Licenses
static func _load_licenses_in(dir: String):
var dict = {}
# get game licenses
var names = DirAccess.get_files_at(dir)
if names.size() == 0:
print_verbose("\nSimple License: No License files found in dir\n", dir, "\nif you have no license files there, then this can be ignored\n")
for _name in names:
var ext = _name.rsplit('.', false, 1)
if ext.size() == 0 or ext[-1] != 'txt':
continue
var l = new()
l.identifier = _name.split('.', false, 1)[0]
l.name = l.identifier
l.terms = FileAccess.open(dir.path_join(_name), FileAccess.READ).get_as_text()
dict[l.identifier] = l
# get licenses built into the Godot Engine
var tmp = Engine.get_license_info()
for id in tmp:
if dict.has(id):
continue
var l = new()
l.identifier = id
l.terms = tmp[id]
dict[id] = l
return dict
# this is for formatting individual lines accoring to SPDX standards
static func _add_line_padding(combined_lines: String, padding: String = " ") -> String:
if combined_lines.is_empty():
return combined_lines
var lines = combined_lines.split("\n")
var s = ""
for i in len(lines):
if lines[i].is_empty() or lines[i] == "\n":
if i+1 < len(lines):
s += padding + "." + "\n"
else:
s += '\n'
else:
s += padding + lines[i] + "\n"
s = s.strip_edges(false)
s += '\n'
return s

View file

@ -0,0 +1,178 @@
class_name LicenseLink
extends Resource
## Files that are under this license [br]
## [color=red]WARNING[/color] DO NOT put in any file that Godot Cannot load, via Resource.load() [br]
## or it will prevent the game from launching. files like .txt .csg etc
@export var link_files: Array[Resource]
## Directories that are under this license [br]
## The given file's Parent Directory will be tracked [br]
## [color=red]WARNING[/color] DO NOT put in any file that Godot Cannot load, via Resource.load() [br]
## or it will prevent the game from launching. files like .txt .csg etc
@export var link_dirs: Array[Resource]
## Files that are under this license [br]
## Note: These paths are [b]NOT[/b] automatically tracked, [br]
## you will have to, manually keep these paths up to date
@export var link_paths: Array
## Example: Godot_Icon, Custom Font Name, Your Games Name, etc
@export var componet_name: String = ""
## Gets included in [method to_formatted_string] right after [member componet_name] [br]
## as part of the "Comment:" Section of the SPDX format
@export var extra: String = ""
## SPDX-License-Identifier or similar to it. CASE SENSITIVE[br]
## Like "CC0-1.0" or more complex entries like [br]
## "CC0-1.0 or MIT" [br]
## "CC0-1.0 and MIT" [br]
## See [url=https://spdx.org/licenses/]SPDX Identifier List[/url]
@export var license_identifier: String = "" : set = _set_identifier
## who and when was the copyright was created [br]
## example [br]
## 2022, John Doe [br]
## (next entry) [br]
## 2022-2023, Jim Stirling, Corp xyz [br]
@export var copyright: Array[String]
var license: License
## Unlike [member license_identifier] this contains [b]ONLY[/b] the identifiers [br]
var license_identifiers: Array[String]
## Either "Godot Engine" or "Game" [br]
## This value is AUTO GENERATED [br]
## [b]DON'T SET THIS VALUE MANUALLY[/b], IT CAN BREAK THINGS
var component_of: String = ""
func _init() -> void:
_set_identifier(license_identifier)
func _set_identifier(v: String):
license_identifier = v
var tmp = v.replace(' and ', '!break!').replace(' or ', '!break!').split('!break!', false)
for x in tmp:
license_identifiers.append(x)
func _to_string() -> String:
return self.to_formatted_string()
## Returns a string containing this link's information, formatted to [url=https://spdx.dev/resources/use/]SPDX Standards[/url]
func to_formatted_string(hide_files: bool = false):
var _files = ""
if not hide_files:
for x in link_files:
_files += x.resource_path.replace("res://", " ./").strip_edges() + "\n"
for x in link_dirs:
_files += (
x.resource_path.replace("res://", " ./").rsplit("/", false, 1)[0].strip_edges()
+ "/*\n"
)
for x in link_paths:
_files += x.replace("res://", " ./").strip_edges() + "\n"
_files = _files.strip_edges()
var _comment = ""
if not componet_name.is_empty():
_comment += componet_name
if not extra.is_empty():
_comment += "\n"
if not extra.is_empty():
_comment += extra
return "Files:{files}\nComment:{comment}\nCopyright:{copyright}\nLicense:{identifier}\n".format(
{
"files": _add_line_padding(_files, " "),
"comment": _add_line_padding(_comment, " "),
"copyright": _add_line_padding("\n".join(copyright), " "),
"identifier": _add_line_padding(license_identifier, " "),
}
)
# wouldn't recomend using this, unless you know what your doing
# but if you do, this loads and parses all links (LicenseLink Resource files) in a directory,
# plus Godot's built-in Licenses
#
# exclude engine: excludes loading Godot's built-in license information
# this is for mods, in which the main game will have already shown the Godot Engine's Licensing
static func _load_links_in(dir: String, exclude_engine: bool = false):
var dict = {
'array': [],
'by_identifier': {},
'by_parent': {},
}
if not DirAccess.dir_exists_absolute(dir):
printerr('Simple License: LicenseLinks directory is missing! ', dir)
return dict
# get Game license links
var names = DirAccess.get_files_at(dir)
if len(names) == 0:
print_verbose("\nSimple License: No LicenseLinks found in dir\n", dir, "\nif you have no LicenseLinks there, then this can be ignored\n")
for name in names:
name = name.replace('.remap', '')
var path = dir.path_join(name)
var res = ResourceLoader.load(path)
if res is Resource and res.get("copyright") != null:
if res.component_of.is_empty():
res.component_of = "Game"
dict.array.append(res)
dict.by_identifier[res.license_identifier] = res
if not dict.by_parent.has(res.component_of):
dict.by_parent[res.component_of] = {}
dict.by_parent[res.component_of][res.license_identifier] = res
# Get Engine license links
if not exclude_engine:
for a in Engine.get_copyright_info():
var l = new()
l.componet_name = a.name
l.component_of = "Godot Engine"
l.link_paths = a.parts[0].files
l.license_identifier = a.parts[0].license
l.copyright.append_array(a.parts[0].copyright)
dict.array.append(l)
dict.by_identifier[l.license_identifier] = l
if not dict.by_parent.has(l.component_of):
dict.by_parent[l.component_of] = {}
if not dict.by_parent[l.component_of].has(l.license_identifier):
dict.by_parent[l.component_of][l.license_identifier] = l
return dict
# this is for formatting individual lines accoring to SPDX standards
static func _add_line_padding(combined_lines: String, padding: String) -> String:
if combined_lines.is_empty():
return combined_lines
var lines = combined_lines.split("\n")
var s = ""
for i in len(lines):
if lines[i].is_empty() or lines[i] == "\n":
if i+1 < len(lines):
s += padding + "." + "\n"
else:
s += '\n'
else:
s += padding + lines[i] + "\n"
s = s.strip_edges(false)
return s

View file

@ -0,0 +1,121 @@
class_name LicenseManager
extends Node
## loads license information from this directory and the sub-directory "license_links"
@export var load_dir: String = "res://licenses"
## export license information to this directory and the sub-directory "licenses"
@export var export_dir: String = "user://"
## This disables loading Godot's built-in license information [br]
## this is for mods, in which the main game will have already shown the Godot's built-in Licensing
@export var exclude_engine: bool = false
## contains all loaded [License]s [br]
## key = identifier [br]
## value = [License]
var licenses := {}
## contains all loaded [LicenseLink]s [br]
## with searching in mind [br]
## "array" [] [br]
## "by_identifier" {} license identifier [br]
## "by_parent" {} parent component name [br]
var license_links := {
'array': [],
'by_identifier': {},
'by_parent': {},
}
## Loads license information from [member load_dir] [br]
func load_license_information():
licenses.clear()
license_links.array.clear()
license_links.by_identifier.clear()
license_links.by_parent.clear()
if not DirAccess.dir_exists_absolute(load_dir):
printerr("Failed to find license directory ", load_dir)
return
licenses = License._load_licenses_in(load_dir)
if licenses.has('Expat') and not licenses.has('MIT'):
var l = licenses['Expat'].duplicate() as License
l.identifier = 'MIT'
licenses['MIT'] = l
license_links = LicenseLink._load_links_in(load_dir.path_join('license_links'), exclude_engine)
## Returns a single string "file", that is formatted in the SPDX Standard [br]
## that contains all licensing information, contained in this instance, [br]
## if only_links, then the returned data will omit the licensing term files
func get_combined_copyright(only_links: bool = false) -> String:
var lines = ""
var used_licenses = {}
# Links
for link in license_links.array:
if link is LicenseLink:
lines += link.to_formatted_string(link.component_of == 'Godot Engine')
lines += '\n'
used_licenses.merge(get_all_valid_licenses(link))
lines += '\n\n'
if only_links:
return lines
# License Terms
var values = used_licenses.values()
for i in len(values):
if i+1 < len(values):
lines += values[i].to_formatted_string() + '\n'
else:
lines += values[i].to_formatted_string()
return lines
## Returns all licenses that are "valid"/exist [br]
## Sometimes license files are missing, or Identifiers are incorrectly spelled, this helps with that.
func get_all_valid_licenses(link: LicenseLink) -> Dictionary:
var d = {}
for x in link.license_identifiers:
if licenses.has(x):
d[x] = licenses[x]
return d
## export all license information to [member export_dir] and the sub-directory "licenses"
func export(directory: String = ""):
if directory.is_empty():
directory = export_dir
var licenses_path = directory.path_join('licenses')
if not DirAccess.dir_exists_absolute(licenses_path):
DirAccess.make_dir_recursive_absolute(licenses_path)
# Export the combined license file
var f = FileAccess.open(directory.path_join('COPYRIGHT.txt'), FileAccess.WRITE)
if f is FileAccess:
f.store_string(self.get_combined_copyright())
# Export the slim license file
f = FileAccess.open(directory.path_join('COPYRIGHT_SLIM.txt'), FileAccess.WRITE)
if f is FileAccess:
f.store_string(self.get_combined_copyright(true))
# Export the individual license files
var used = {}
for i in license_links.array.size():
var license = license_links.array[i] as LicenseLink
var ids = self.get_all_valid_licenses(license)
used.merge(ids)
for id in ids:
var license_path = licenses_path.path_join(id)+'.txt'
f = FileAccess.open(license_path, FileAccess.WRITE)
f.store_string(licenses[id].to_formatted_string())

View file

@ -0,0 +1,14 @@
[gd_resource type="Resource" script_class="LicenseLink" load_steps=3 format=3 uid="uid://ch5muqo430mw"]
[ext_resource type="Script" path="res://addons/simplelicense/mod_example/mod_1.gd" id="1_3n7mw"]
[ext_resource type="Script" path="res://addons/simplelicense/api/LicenseLink.gd" id="1_gufc2"]
[resource]
script = ExtResource("1_gufc2")
link_files = Array[Resource]([])
link_dirs = Array[Resource]([ExtResource("1_3n7mw")])
link_paths = []
componet_name = "Mod 1"
extra = "extra info shown in the comment section of the link text"
license_identifier = "mod_1_license_identifier"
copyright = Array[String](["copyright year, (comma) name, (comma) company name"])

View file

@ -0,0 +1,15 @@
This is an example of the custom license terms for Mod_1
So like
MIT LICENSE TERMS
...
..
.
or
CC0 1.0 LICENSE TERMS
...
..
.

View file

@ -0,0 +1 @@
extends Node

View file

@ -0,0 +1,9 @@
[plugin]
name="SimpleLicense"
description="A simple license managment plugin.
Licensed under: CC0-1.0"
author="GradyTheDev"
version="1.1.2"
script="plugin.gd"

View file

@ -0,0 +1,12 @@
@tool
extends EditorPlugin
func _enter_tree() -> void:
# Initialization of the plugin goes here
pass
func _exit_tree() -> void:
# Clean-up of the plugin goes here.
pass

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB