Add project files

This commit is contained in:
ChaoticByte 2024-09-25 21:18:58 +02:00
commit ab339c8a2c
No known key found for this signature in database
81 changed files with 2567 additions and 0 deletions

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><path d="m9 1037.4v3.0547a4 4 0 0 1 1.0273.4258l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223z" fill-opacity=".99608"/><path d="m7 1.0801a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/></g></svg>

After

Width:  |  Height:  |  Size: 905 B

View file

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ddxpytkht0m5p"
path="res://.godot/imported/Progress1.svg-4c67bc9979d74bc8a460d9eb07a2c04c.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/Progress1.svg"
dest_files=["res://.godot/imported/Progress1.svg-4c67bc9979d74bc8a460d9eb07a2c04c.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=true
editor/convert_colors_with_editor_theme=true

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm-1.3203 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855z" fill-opacity=".99608"/></g></svg>

After

Width:  |  Height:  |  Size: 913 B

View file

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dowca7ike2thl"
path="res://.godot/imported/Progress2.svg-8504d77be0fc9a48adff096c00560fac.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/Progress2.svg"
dest_files=["res://.godot/imported/Progress2.svg-8504d77be0fc9a48adff096c00560fac.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=true
editor/convert_colors_with_editor_theme=true

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm4.8926 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m11.867 1045.4a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547z" fill-opacity=".99608"/></g></svg>

After

Width:  |  Height:  |  Size: 913 B

View file

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cwh8md6qipmdw"
path="res://.godot/imported/Progress3.svg-e38cf6a56b985d7e7fa7472e057ce3e5.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/Progress3.svg"
dest_files=["res://.godot/imported/Progress3.svg-e38cf6a56b985d7e7fa7472e057ce3e5.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=true
editor/convert_colors_with_editor_theme=true

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m10.027 1047.8a4 4 0 0 1 -1.0273.4277v3.0508a7 7 0 0 0 3.1855-1.3203z" fill-opacity=".99608"/></g></svg>

After

Width:  |  Height:  |  Size: 898 B

View file

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dm0jpqdjetv2c"
path="res://.godot/imported/Progress4.svg-2c536d8d07b08b10b0d56dd6b498e182.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/Progress4.svg"
dest_files=["res://.godot/imported/Progress4.svg-2c536d8d07b08b10b0d56dd6b498e182.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=true
editor/convert_colors_with_editor_theme=true

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-1.8398 2.4414a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.4258z" fill-opacity=".99608"/></g></svg>

After

Width:  |  Height:  |  Size: 913 B

View file

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bkj6kjyjyi7cd"
path="res://.godot/imported/Progress5.svg-6a2e86bfe29d7ef19937e393bd446959.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/Progress5.svg"
dest_files=["res://.godot/imported/Progress5.svg-6a2e86bfe29d7ef19937e393bd446959.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=true
editor/convert_colors_with_editor_theme=true

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-1.7324 5.1855a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508z" fill-opacity=".99608"/></g></svg>

After

Width:  |  Height:  |  Size: 915 B

View file

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bsljbs1aiyels"
path="res://.godot/imported/Progress6.svg-847d0e3ae51aa33e84715058ee9f1d88.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/Progress6.svg"
dest_files=["res://.godot/imported/Progress6.svg-847d0e3ae51aa33e84715058ee9f1d88.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=true
editor/convert_colors_with_editor_theme=true

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-2 .0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.42773v-3.0508zm6.5996 2.7344-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582z" fill-opacity=".99608"/></g></svg>

After

Width:  |  Height:  |  Size: 913 B

View file

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cct6crbhix7u8"
path="res://.godot/imported/Progress7.svg-0b5f28f5e4b7291603ae2f7b7f534bdc.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/Progress7.svg"
dest_files=["res://.godot/imported/Progress7.svg-0b5f28f5e4b7291603ae2f7b7f534bdc.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=true
editor/convert_colors_with_editor_theme=true

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><path d="m9 1.0781v3.0547a4 4 0 0 1 1.0273.42578l2.1582-2.1582a7 7 0 0 0 -3.1855-1.3223zm-6.5996 2.7363a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 .42578-1.0273l-2.1582-2.1582zm11.199 0-2.1582 2.1582a4 4 0 0 1 .42774 1.0273h3.0508a7 7 0 0 0 -1.3203-3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -.42773-1.0273h-3.0508zm10.787 0a4 4 0 0 1 -.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223-3.1855h-3.0547zm-5.8945 2.4414-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273-.42578zm4.0547 0a4 4 0 0 1 -1.0273.42774v3.0508a7 7 0 0 0 3.1855-1.3203l-2.1582-2.1582z" fill-opacity=".19608" transform="translate(0 1036.4)"/><path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273-.4277z" fill-opacity=".99608"/></g></svg>

After

Width:  |  Height:  |  Size: 897 B

View file

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dqc521iq12a7l"
path="res://.godot/imported/Progress8.svg-01a6c510553331c426b175a929f97995.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/Progress8.svg"
dest_files=["res://.godot/imported/Progress8.svg-01a6c510553331c426b175a929f97995.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=true
editor/convert_colors_with_editor_theme=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dmv3ld2otx1e2"
path="res://.godot/imported/border_bottom.png-57eaece612033b44553803bae1bed8cc.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/border_bottom.png"
dest_files=["res://.godot/imported/border_bottom.png-57eaece612033b44553803bae1bed8cc.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.7 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b4sio0j5om50s"
path="res://.godot/imported/border_top.png-189e90fa324f96478fce0fb20176c395.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/border_top.png"
dest_files=["res://.godot/imported/border_top.png-189e90fa324f96478fce0fb20176c395.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: 730 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ce2eojg0pwpov"
path="res://.godot/imported/dot1.png-ce212c4b64977cbf71f1ecdd531281cd.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/dot1.png"
dest_files=["res://.godot/imported/dot1.png-ce212c4b64977cbf71f1ecdd531281cd.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: 883 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cvwa5lg3qj0e2"
path="res://.godot/imported/dot2.png-e37c7300c62fe4f74a78c2c148fdcd38.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/dot2.png"
dest_files=["res://.godot/imported/dot2.png-e37c7300c62fe4f74a78c2c148fdcd38.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: 287 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://63wk5nib3r7q"
path="res://.godot/imported/embedded.png-cb03d2626ef24143491c5f1bf62cd67c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/embedded.png"
dest_files=["res://.godot/imported/embedded.png-cb03d2626ef24143491c5f1bf62cd67c.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: 332 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dgaa5faajesgv"
path="res://.godot/imported/horizontal-line2.png-cfa4f3add1c707a77eabccac70481cf7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/godot-rapier2d/generated/updater/assets/horizontal-line2.png"
dest_files=["res://.godot/imported/horizontal-line2.png-cfa4f3add1c707a77eabccac70481cf7.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,217 @@
@tool
extends Window
## Updater heaviliy inspired by GDUnit4's updater, but decoupled completely from GDUnit. Also did not
## include all the patching that included since it seemed to complicated to include for most projects.
signal updated
var config = UpdaterConfig.get_user_config()
var spinner_icon = "res://addons/%s/generated/updater/spinner.tres" % config.plugin_name
# Using this style of import avoids polluting user's namespaces
const UpdaterConfig = preload("updater_config.gd")
const SemVer = preload("updater_sem_ver.gd")
const HttpClient = preload("updater_http_client.gd")
const MarkDownReader = preload("updater_markdown_reader.gd")
const TEMP_FILE_NAME = "user://temp.zip"
@onready var _md_reader: MarkDownReader = MarkDownReader.new()
@onready var _http_client: HttpClient = $HttpClient
@onready var _header: Label = $Panel/GridContainer/PanelContainer/header
@onready var _content: RichTextLabel = $Panel/GridContainer/PanelContainer2/ScrollContainer/MarginContainer/content
@onready var _update_button: Button = $Panel/GridContainer/Panel/HBoxContainer/update
var _latest_version: SemVer
var _download_zip_url: String
func _ready():
hide()
_http_client.github_repo = config.github_repo
title = "%s Plugin Update" % config.plugin_name
var plugin :EditorPlugin = Engine.get_meta(config.editor_plugin_meta)
# wait a bit to allow the editor to initialize itself
await Engine.get_main_loop().create_timer(float(config.secs_before_check_for_update)).timeout
_check_for_updater()
func _check_for_updater():
var response = await _http_client.request_latest_version()
if response.code() != 200:
push_warning("Update information cannot be retrieved from GitHub! \n %s %s" % [response.response(), response.code()])
return
_latest_version = extract_latest_version(response)
var current_version := extract_current_version()
# if the current version is less than or equal to the skip version, skip the update
var skip_config = UpdaterConfig.get_skip_config()
if config.plugin_name in skip_config:
var skip_version: SemVer = SemVer.parse(skip_config[config.plugin_name])
if !_latest_version.is_greater(skip_version):
return
# if same version exit here no update need
if _latest_version.is_greater(current_version):
_download_zip_url = extract_zip_url(response)
_header.text = "Current version '%s'. A new version '%s' is available" % [current_version, _latest_version]
await show_update()
func show_update() -> void:
message_h4("\n\n\nRequest release infos ... [img=24x24]%s[/img]" % spinner_icon, Color.SNOW)
popup_centered_ratio(.5)
var content :String
var response: HttpClient.HttpResponse = await _http_client.request_releases()
if response.code() == 200:
content = await extract_releases(response, extract_current_version())
else:
message_h4("\n\n\nError checked request available releases!", Color.RED)
return
# finally force rescan to import images as textures
if Engine.is_editor_hint():
await rescan()
message(content, Color.WHITE_SMOKE)
_update_button.set_disabled(false)
func rescan() -> void:
if Engine.is_editor_hint():
if OS.is_stdout_verbose():
prints(".. reimport release resources")
var fs := EditorInterface.get_resource_filesystem()
fs.scan()
while fs.is_scanning():
if OS.is_stdout_verbose():
progress_bar(fs.get_scanning_progress() * 100 as int)
await Engine.get_main_loop().process_frame
await Engine.get_main_loop().process_frame
await Engine.get_main_loop().create_timer(1).timeout
func extract_current_version() -> SemVer:
var config_file = ConfigFile.new()
config_file.load('addons/%s/plugin.cfg' % config.plugin_name)
return SemVer.parse(config_file.get_value('plugin', 'version'))
static func extract_latest_version(response: HttpClient.HttpResponse) -> SemVer:
var body :Array = response.response()
return SemVer.parse(body[0]["name"])
func extract_current_flavour() -> String:
var config_file = ConfigFile.new()
config_file.load('addons/%s/plugin.cfg' % config.plugin_name)
return config_file.get_value('plugin', 'flavour')
func extract_zip_url(response: HttpClient.HttpResponse) -> String:
var flavour := extract_current_flavour()
return 'https://github.com/%s/releases/download/%s/%s.zip' % [config.github_repo, _latest_version, flavour]
func extract_releases(response: HttpClient.HttpResponse, current_version) -> String:
await get_tree().process_frame
var result := ""
for release in response.response():
if SemVer.parse(release["tag_name"]).equals(current_version):
break
var release_description :String = release["body"]
result += await _md_reader.to_bbcode(release_description)
return result
func message_h4(message :String, color :Color, clear := true) -> void:
if clear:
_content.clear()
_content.append_text("[font_size=36]%s[/font_size]" % _colored(message, color))
func message(message :String, color :Color) -> void:
_content.clear()
_content.append_text(_colored(message, color))
func progress_bar(p_progress :int, p_color :Color = Color.POWDER_BLUE):
if p_progress < 0:
p_progress = 0
if p_progress > 100:
p_progress = 100
printraw("scan [%-50s] %-3d%%\r" % ["".lpad(int(p_progress/2.0), "#").rpad(50, "-"), p_progress])
func _colored(message :String, color :Color) -> String:
return "[color=#%s]%s[/color]" % [color.to_html(), message]
func _skip_update():
# Store a setting in the config.
var skip_config = UpdaterConfig.get_skip_config() # Read this again in case it was changed
skip_config[config.plugin_name] = str(_latest_version)
# Write the config into the addons dir so it gets removed on update
UpdaterConfig.save_skip_config(skip_config)
func _on_update_pressed():
_update_button.set_disabled(true)
var updater_http_request = HTTPRequest.new()
updater_http_request.accept_gzip = true
add_child(updater_http_request)
message_h4("\n\n\nStaring download %s ... [img=24x24]%s[/img]" % [_download_zip_url, spinner_icon], Color.SNOW)
updater_http_request.request_completed.connect(_on_http_request_request_completed)
updater_http_request.request(_download_zip_url)
func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
if result != HTTPRequest.RESULT_SUCCESS:
message_h4("\n\n\nError downloading update!", Color.RED)
return
message_h4("\n\n\nSuccesfuly downloaded release. Saving file to user://temp.zip", Color.SNOW)
# Save the downloaded zip
var zip_file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE)
zip_file.store_buffer(body)
zip_file.close()
OS.move_to_trash(ProjectSettings.globalize_path("res://addons/%s" % config.plugin_name))
var zip_reader: ZIPReader = ZIPReader.new()
zip_reader.open(TEMP_FILE_NAME)
var files: PackedStringArray = zip_reader.get_files()
var base_path = files[1]
# Remove archive folder
files.remove_at(0)
# Remove assets folder
files.remove_at(0)
for path in files:
var new_file_path: String = path.replace(base_path, "")
if path.ends_with("/"):
DirAccess.make_dir_recursive_absolute("res://addons/%s" % new_file_path)
else:
var file: FileAccess = FileAccess.open("res://addons/%s" % new_file_path, FileAccess.WRITE)
file.store_buffer(zip_reader.read_file(path))
zip_reader.close()
DirAccess.remove_absolute(TEMP_FILE_NAME)
updated.emit()
print("Finished Updating.")
hide()
func _on_close_pressed():
hide()
if $Panel/GridContainer/Panel/HBoxContainer/skip_update.button_pressed:
_skip_update()
func _on_content_meta_clicked(meta :String):
var properties = str_to_var(meta)
if properties.has("url"):
OS.shell_open(properties.get("url"))
func _on_content_meta_hover_started(meta :String):
var properties = str_to_var(meta)
if properties.has("tool_tip"):
_content.set_tooltip_text(properties.get("tool_tip"))
func _on_content_meta_hover_ended(meta):
_content.set_tooltip_text("")
func _on_close_requested() -> void:
_on_close_pressed()

View file

@ -0,0 +1,117 @@
[gd_scene load_steps=3 format=3 uid="uid://br17ciqiitq6s"]
[ext_resource type="Script" path="res://addons/godot-rapier2d/generated/updater/download_update_panel.gd" id="1_uai4s"]
[ext_resource type="Script" path="res://addons/godot-rapier2d/generated/updater/updater_http_client.gd" id="2_qpn7s"]
[node name="Window" type="Window"]
disable_3d = true
gui_embed_subwindows = true
title = "godot-rapier2d Plugin Update"
initial_position = 1
size = Vector2i(800, 400)
visible = false
wrap_controls = true
transient = true
min_size = Vector2i(800, 400)
script = ExtResource("1_uai4s")
[node name="HttpClient" type="Node" parent="."]
script = ExtResource("2_qpn7s")
github_repo = "appsinacup/godot-rapier-physics"
[node name="Panel" type="Panel" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="GridContainer" type="VBoxContainer" parent="Panel"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
alignment = 1
[node name="PanelContainer" type="MarginContainer" parent="Panel/GridContainer"]
layout_mode = 2
theme_override_constants/margin_left = 4
theme_override_constants/margin_top = 4
theme_override_constants/margin_right = 4
theme_override_constants/margin_bottom = 4
[node name="header" type="Label" parent="Panel/GridContainer/PanelContainer"]
layout_mode = 2
size_flags_horizontal = 9
text = "Current version 'v0.7.20'. A new version 'v0.8.0' is available"
[node name="PanelContainer2" type="PanelContainer" parent="Panel/GridContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="ScrollContainer" type="ScrollContainer" parent="Panel/GridContainer/PanelContainer2"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="MarginContainer" type="MarginContainer" parent="Panel/GridContainer/PanelContainer2/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/margin_left = 4
theme_override_constants/margin_top = 4
theme_override_constants/margin_right = 4
theme_override_constants/margin_bottom = 4
[node name="content" type="RichTextLabel" parent="Panel/GridContainer/PanelContainer2/ScrollContainer/MarginContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
focus_mode = 2
bbcode_enabled = true
fit_content = true
selection_enabled = true
[node name="Panel" type="MarginContainer" parent="Panel/GridContainer"]
layout_mode = 2
size_flags_vertical = 4
theme_override_constants/margin_left = 4
theme_override_constants/margin_top = 4
theme_override_constants/margin_right = 4
theme_override_constants/margin_bottom = 4
[node name="HBoxContainer" type="HBoxContainer" parent="Panel/GridContainer/Panel"]
use_parent_material = true
layout_mode = 2
theme_override_constants/separation = 4
[node name="skip_update" type="CheckBox" parent="Panel/GridContainer/Panel/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 4
text = "Skip this version"
[node name="update" type="Button" parent="Panel/GridContainer/Panel/HBoxContainer"]
custom_minimum_size = Vector2(100, 40)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 4
text = "Update"
[node name="close" type="Button" parent="Panel/GridContainer/Panel/HBoxContainer"]
custom_minimum_size = Vector2(100, 40)
layout_mode = 2
size_flags_horizontal = 10
size_flags_vertical = 4
text = "Close"
[connection signal="close_requested" from="." to="." method="_on_close_requested"]
[connection signal="meta_clicked" from="Panel/GridContainer/PanelContainer2/ScrollContainer/MarginContainer/content" to="." method="_on_content_meta_clicked"]
[connection signal="meta_hover_ended" from="Panel/GridContainer/PanelContainer2/ScrollContainer/MarginContainer/content" to="." method="_on_content_meta_hover_ended"]
[connection signal="meta_hover_started" from="Panel/GridContainer/PanelContainer2/ScrollContainer/MarginContainer/content" to="." method="_on_content_meta_hover_started"]
[connection signal="pressed" from="Panel/GridContainer/Panel/HBoxContainer/update" to="." method="_on_update_pressed"]
[connection signal="pressed" from="Panel/GridContainer/Panel/HBoxContainer/close" to="." method="_on_close_pressed"]

View file

@ -0,0 +1,6 @@
{
"plugin_name": "godot-rapier2d",
"secs_before_check_for_update": 2,
"github_repo": "appsinacup/godot-rapier-physics",
"editor_plugin_meta": "Rapier2DEditorPlugin"
}

View file

@ -0,0 +1,30 @@
[gd_resource type="AnimatedTexture" load_steps=9 format=3 uid="uid://dljx0fmjlrbuh"]
[ext_resource type="Texture2D" uid="uid://ddxpytkht0m5p" path="res://addons/godot-rapier2d/generated/updater/assets/Progress1.svg" id="1_ctgew"]
[ext_resource type="Texture2D" uid="uid://dowca7ike2thl" path="res://addons/godot-rapier2d/generated/updater/assets/Progress2.svg" id="2_xwye8"]
[ext_resource type="Texture2D" uid="uid://cwh8md6qipmdw" path="res://addons/godot-rapier2d/generated/updater/assets/Progress3.svg" id="3_53vx7"]
[ext_resource type="Texture2D" uid="uid://dm0jpqdjetv2c" path="res://addons/godot-rapier2d/generated/updater/assets/Progress4.svg" id="4_eecnj"]
[ext_resource type="Texture2D" uid="uid://bkj6kjyjyi7cd" path="res://addons/godot-rapier2d/generated/updater/assets/Progress5.svg" id="5_auay0"]
[ext_resource type="Texture2D" uid="uid://bsljbs1aiyels" path="res://addons/godot-rapier2d/generated/updater/assets/Progress6.svg" id="6_fx28b"]
[ext_resource type="Texture2D" uid="uid://cct6crbhix7u8" path="res://addons/godot-rapier2d/generated/updater/assets/Progress7.svg" id="7_giugp"]
[ext_resource type="Texture2D" uid="uid://dqc521iq12a7l" path="res://addons/godot-rapier2d/generated/updater/assets/Progress8.svg" id="8_yppa0"]
[resource]
frames = 8
speed_scale = 2.5
frame_0/texture = ExtResource("1_ctgew")
frame_0/duration = 0.2
frame_1/texture = ExtResource("2_xwye8")
frame_1/duration = 0.2
frame_2/texture = ExtResource("3_53vx7")
frame_2/duration = 0.2
frame_3/texture = ExtResource("4_eecnj")
frame_3/duration = 0.2
frame_4/texture = ExtResource("5_auay0")
frame_4/duration = 0.2
frame_5/texture = ExtResource("6_fx28b")
frame_5/duration = 0.2
frame_6/texture = ExtResource("7_giugp")
frame_6/duration = 0.2
frame_7/texture = ExtResource("8_yppa0")
frame_7/duration = 0.2

View file

@ -0,0 +1,58 @@
extends RefCounted
## Expected format of config is a JSON file like:
## {
## "plugin_name": "plugin_updater",
## "secs_before_check_for_update": 5,
## "github_repo": "myyk/godot-plugin-updater",
## "editor_plugin_meta": "PluginUpdaterEditorPlugin"
## }
const PLUGIN_NAME: String = "godot-rapier2d" # This is replaced when code is generated
const PLUGIN_MAKER_CONFIG_PATH = "res://plugin-updater.json"
const PLUGIN_USER_CONFIG_PATH_FORMAT = "res://addons/%s/generated/updater/plugin-updater.json"
const PLUGIN_SKIP_CONFIG_PATH = "res://.godot/plugin-updater-skip.json"
static func get_user_config() -> Dictionary:
return _get_config(PLUGIN_USER_CONFIG_PATH_FORMAT % PLUGIN_NAME)
static func get_repo_config() -> Dictionary:
return _get_config(PLUGIN_MAKER_CONFIG_PATH)
static func _get_config(path: String) -> Dictionary:
var config = {
secs_before_check_for_update = 5,
}
if !FileAccess.file_exists(path):
push_error("plugin-updater: Needs a config at " + path)
var file: FileAccess = FileAccess.open(path, FileAccess.READ)
config.merge(JSON.parse_string(file.get_as_text()), true)
return config
# Skip config is a JSON file like:
# {
# "plugin_name_1": "1.0.0"
# "plugin_name_2": "1.2.3"
# }
static func get_skip_config() -> Dictionary:
if !FileAccess.file_exists(PLUGIN_SKIP_CONFIG_PATH):
return {}
var file: FileAccess = FileAccess.open(PLUGIN_SKIP_CONFIG_PATH, FileAccess.READ)
if file == null:
push_error("plugin-updater: Could not open file at " + PLUGIN_SKIP_CONFIG_PATH)
return {}
return JSON.parse_string(file.get_as_text())
static func save_skip_config(config: Dictionary) -> Error:
var file: FileAccess = FileAccess.open(PLUGIN_SKIP_CONFIG_PATH, FileAccess.WRITE)
if file == null:
push_error("plugin-updater: Could not open file at " + PLUGIN_SKIP_CONFIG_PATH)
return FileAccess.get_open_error()
file.store_string(JSON.stringify(config))
file.close()
return OK

View file

@ -0,0 +1,79 @@
@tool
extends Node
## Credits: Mostly copied from https://github.com/MikeSchulze/gdUnit4/blob/99b7c323f443e5fcc67f9a79b4df532727e8986f/addons/gdUnit4/src/update/GdUnitUpdateClient.gd
signal request_completed(response)
@export var github_repo = ""
class HttpResponse:
var _code :int
var _body :PackedByteArray
func _init(code_ :int, body_ :PackedByteArray):
_code = code_
_body = body_
func code() -> int:
return _code
func response() -> Variant:
var test_json_conv := JSON.new()
test_json_conv.parse(_body.get_string_from_utf8())
return test_json_conv.get_data()
func body() -> PackedByteArray:
return _body
var _http_request :HTTPRequest = HTTPRequest.new()
func _ready():
add_child(_http_request)
_http_request.connect("request_completed", Callable(self, "_on_request_completed"))
func _notification(what):
if what == NOTIFICATION_PREDELETE:
if is_instance_valid(_http_request):
_http_request.queue_free()
func request_latest_version() -> HttpResponse:
var error = _http_request.request("https://api.github.com/repos/%s/tags" % github_repo)
if error != OK:
var message = "request_latest_version failed: %d" % error
return HttpResponse.new(error, message.to_utf8_buffer())
return await self.request_completed
func request_releases() -> HttpResponse:
var error = _http_request.request("https://api.github.com/repos/%s/releases" % github_repo)
if error != OK:
var message = "request_releases failed: %d" % error
return HttpResponse.new(error, message.to_utf8_buffer())
return await self.request_completed
func request_image(url :String) -> HttpResponse:
var error = _http_request.request(url)
if error != OK:
var message = "request_image failed: %d" % error
return HttpResponse.new(error, message.to_utf8_buffer())
return await self.request_completed
func request_zip_package(url :String, file :String) -> HttpResponse:
_http_request.set_download_file(file)
var error = _http_request.request(url)
if error != OK:
var message = "request_zip_package failed: %d" % error
return HttpResponse.new(error, message.to_utf8_buffer())
return await self.request_completed
func _on_request_completed(_result :int, response_code :int, _headers :PackedStringArray, body :PackedByteArray):
if _http_request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED:
_http_request.set_download_file("")
request_completed.emit(HttpResponse.new(response_code, body))

View file

@ -0,0 +1,340 @@
extends RefCounted
const UpdaterConfig = preload("updater_config.gd")
var config = UpdaterConfig.get_user_config()
const FONT_H1 := 42
const FONT_H2 := 32
const FONT_H3 := 26
const FONT_H4 := 22
const FONT_H5 := 16
const FONT_H6 := 12
var HORIZONTAL_RULE: String = "[img=4000x2]res://addons/%s/generated/updater/assets/horizontal-line2.png[/img]\n" % config.plugin_name
const HEADER_RULE := "[font_size=%d]$1[/font_size]\n"
const HEADER_CENTERED_RULE := "[font_size=%d][center]$1[/center][/font_size]\n"
const image_download_folder := "res://cached/updater/"
const exclude_font_size := "\b(?!(?:(font_size))\b)"
var md_replace_patterns := [
# horizontal rules
[regex("(?m)^[ ]{0,3}---$"), HORIZONTAL_RULE],
[regex("(?m)^[ ]{0,3}___$"), HORIZONTAL_RULE],
[regex("(?m)^[ ]{0,3}\\*\\*\\*$"), HORIZONTAL_RULE],
# headers
[regex("(?m)^###### (.*)"), HEADER_RULE % FONT_H6],
[regex("(?m)^##### (.*)"), HEADER_RULE % FONT_H5],
[regex("(?m)^#### (.*)"), HEADER_RULE % FONT_H4],
[regex("(?m)^### (.*)"), HEADER_RULE % FONT_H3],
[regex("(?m)^## (.*)"), (HEADER_RULE + HORIZONTAL_RULE) % FONT_H2],
[regex("(?m)^# (.*)"), (HEADER_RULE + HORIZONTAL_RULE) % FONT_H1],
[regex("(?m)^(.+)=={2,}$"), HEADER_RULE % FONT_H1],
[regex("(?m)^(.+)--{2,}$"), HEADER_RULE % FONT_H2],
# html headers
[regex("<h1>((.*?\\R?)+)<\\/h1>"), (HEADER_RULE + HORIZONTAL_RULE) % FONT_H1],
[regex("<h1[ ]*align[ ]*=[ ]*\"center\">((.*?\\R?)+)<\\/h1>"), (HEADER_CENTERED_RULE + HORIZONTAL_RULE) % FONT_H1],
[regex("<h2>((.*?\\R?)+)<\\/h2>"), (HEADER_RULE + HORIZONTAL_RULE) % FONT_H2],
[regex("<h2[ ]*align[ ]*=[ ]*\"center\">((.*?\\R?)+)<\\/h2>"), (HEADER_CENTERED_RULE + HORIZONTAL_RULE) % FONT_H1],
[regex("<h3>((.*?\\R?)+)<\\/h3>"), HEADER_RULE % FONT_H3],
[regex("<h3[ ]*align[ ]*=[ ]*\"center\">((.*?\\R?)+)<\\/h3>"), HEADER_CENTERED_RULE % FONT_H3],
[regex("<h4>((.*?\\R?)+)<\\/h4>"), HEADER_RULE % FONT_H4],
[regex("<h4[ ]*align[ ]*=[ ]*\"center\">((.*?\\R?)+)<\\/h4>"), HEADER_CENTERED_RULE % FONT_H4],
[regex("<h5>((.*?\\R?)+)<\\/h5>"), HEADER_RULE % FONT_H5],
[regex("<h5[ ]*align[ ]*=[ ]*\"center\">((.*?\\R?)+)<\\/h5>"), HEADER_CENTERED_RULE % FONT_H5],
[regex("<h6>((.*?\\R?)+)<\\/h6>"), HEADER_RULE % FONT_H6],
[regex("<h6[ ]*align[ ]*=[ ]*\"center\">((.*?\\R?)+)<\\/h6>"), HEADER_CENTERED_RULE % FONT_H6],
# asterics
#[regex("(\\*)"), "xxx$1xxx"],
# extract/compile image references
[regex("!\\[(.*?)\\]\\[(.*?)\\]"), Callable(self, "process_image_references")],
# extract images with path and optional tool tip
[regex("!\\[(.*?)\\]\\((.*?)(( )+(.*?))?\\)"), Callable(self, "process_image")],
# links
[regex("([!]|)\\[(.+)\\]\\(([^ ]+?)\\)"), "[url={\"url\":\"$3\"}]$2[/url]"],
# links with tool tip
[regex("([!]|)\\[(.+)\\]\\(([^ ]+?)( \"(.+)\")?\\)"), "[url={\"url\":\"$3\", \"tool_tip\":\"$5\"}]$2[/url]"],
# embeded text
[regex("(?m)^[ ]{0,3}>(.*?)$"), "[img=50x14]res://addons/%s/generated/updater/assets/embedded.png[/img][i]$1[/i]" % config.plugin_name],
# italic + bold font
[regex("[_]{3}(.*?)[_]{3}"), "[i][b]$1[/b][/i]"],
[regex("[\\*]{3}(.*?)[\\*]{3}"), "[i][b]$1[/b][/i]"],
# bold font
[regex("<b>(.*?)<\\/b>"), "[b]$1[/b]"],
[regex("[_]{2}(.*?)[_]{2}"), "[b]$1[/b]"],
[regex("[\\*]{2}(.*?)[\\*]{2}"), "[b]$1[/b]"],
# italic font
[regex("<i>(.*?)<\\/i>"), "[i]$1[/i]"],
[regex(exclude_font_size+"_(.*?)_"), "[i]$1[/i]"],
[regex("\\*(.*?)\\*"), "[i]$1[/i]"],
# strikethrough font
[regex("<s>(.*?)</s>"), "[s]$1[/s]"],
[regex("~~(.*?)~~"), "[s]$1[/s]"],
[regex("~(.*?)~"), "[s]$1[/s]"],
# handling lists
# using an image for dots as workaroud because list is not supported checked Godot 3.x
[regex("(?m)^[ ]{0,1}[*\\-+] (.*)$"), list_replace(0)],
[regex("(?m)^[ ]{2,3}[*\\-+] (.*)$"), list_replace(1)],
[regex("(?m)^[ ]{4,5}[*\\-+] (.*)$"), list_replace(2)],
[regex("(?m)^[ ]{6,7}[*\\-+] (.*)$"), list_replace(3)],
[regex("(?m)^[ ]{8,9}[*\\-+] (.*)$"), list_replace(4)],
# code blocks, code blocks looks not like code blocks in richtext
[regex("```(javascript|python|shell|gdscript)([\\s\\S]*?\n)```"), code_block("$2", true)],
[regex("``([\\s\\S]*?)``"), code_block("$1")],
[regex("`([\\s\\S]*?)`{1,2}"), code_block("$1")],
]
var _img_replace_regex := RegEx.new()
var _image_urls := PackedStringArray()
var _on_table_tag := false
var _client
func regex(pattern :String) -> RegEx:
var regex_ := RegEx.new()
var err = regex_.compile(pattern)
if err != OK:
push_error("error '%s' checked pattern '%s'" % [err, pattern])
return null
return regex_
func _init():
_img_replace_regex.compile("\\[img\\]((.*?))\\[/img\\]")
func set_http_client(client) -> void:
_client = client
func _notification(what):
if what == NOTIFICATION_PREDELETE:
# finally remove_at the downloaded images
for image in _image_urls:
DirAccess.remove_absolute(image)
DirAccess.remove_absolute(image + ".import")
func list_replace(indent :int) -> String:
var replace_pattern: String = ("[img=12x12]res://addons/%s/generated/updater/assets/dot2.png[/img]" % config.plugin_name) if indent %2 else ("[img=12x12]res://addons/%s/generated/updater/assets/dot1.png[/img]" % config.plugin_name)
replace_pattern += " $1"
for index in indent:
replace_pattern = replace_pattern.insert(0, " ")
return replace_pattern
func code_block(replace :String, border :bool = false) -> String:
var cb := "[code][color=aqua][font_size=16]%s[/font_size][/color][/code]" % replace
if border:
return ("[img=1400x14]res://addons/%s/generated/updater/assets/border_top.png[/img]" % config.plugin_name)\
+ "[indent]" + cb + "[/indent]"\
+ ("[img=1400x14]res://addons/%s/generated/updater/assets/border_bottom.png[/img]\n" % config.plugin_name)
return cb
func to_bbcode(input :String) -> String:
input = process_tables(input)
for pattern in md_replace_patterns:
var regex_ :RegEx = pattern[0]
var bb_replace = pattern[1]
if bb_replace is Callable:
input = await bb_replace.call(regex_, input)
else:
input = regex_.sub(input, bb_replace, true)
return input + "\n"
func process_tables(input :String) -> String:
var bbcode := Array()
var lines := Array(input.split("\n"))
while not lines.is_empty():
if is_table(lines[0]):
bbcode.append_array(parse_table(lines))
continue
bbcode.append(lines.pop_front())
return "\n".join(PackedStringArray(bbcode))
class Table:
var _columns :int
var _rows := Array()
class Row:
var _cells := PackedStringArray()
func _init(cells :PackedStringArray,columns :int):
_cells = cells
for i in range(_cells.size(), columns):
_cells.append("")
func to_bbcode(cell_sizes :PackedInt32Array, bold :bool) -> String:
var cells := PackedStringArray()
for cell_index in _cells.size():
var cell :String = _cells[cell_index]
if cell.strip_edges() == "--":
cell = create_line(cell_sizes[cell_index])
if bold:
cell = "[b]%s[/b]" % cell
cells.append("[cell]%s[/cell]" % cell)
return "|".join(cells)
func create_line(length :int) -> String:
var line := ""
for i in length:
line += "-"
return line
func _init(columns :int):
_columns = columns
func parse_row(line :String) -> bool:
# is line containing cells?
if line.find("|") == -1:
return false
_rows.append(Row.new(line.split("|"), _columns))
return true
func calculate_max_cell_sizes() -> PackedInt32Array:
var cells_size := PackedInt32Array()
for column in _columns:
cells_size.append(0)
for row_index in _rows.size():
var row :Row = _rows[row_index]
for cell_index in row._cells.size():
var cell_size :int = cells_size[cell_index]
var size := row._cells[cell_index].length()
if size > cell_size:
cells_size[cell_index] = size
return cells_size
func to_bbcode() -> PackedStringArray:
var cell_sizes := calculate_max_cell_sizes()
var bb_code := PackedStringArray()
bb_code.append("[table=%d]" % _columns)
for row_index in _rows.size():
bb_code.append(_rows[row_index].to_bbcode(cell_sizes, row_index==0))
bb_code.append("[/table]\n")
return bb_code
func parse_table(lines :Array) -> PackedStringArray:
var line :String = lines[0]
var table := Table.new(line.count("|") + 1)
while not lines.is_empty():
line = lines.pop_front()
if not table.parse_row(line):
break
return table.to_bbcode()
func is_table(line :String) -> bool:
return line.find("|") != -1
func open_table(line :String) -> String:
_on_table_tag = true
return "[table=%d]" % (line.count("|") + 1)
func close_table() -> String:
_on_table_tag = false
return "[/table]"
func extract_cells(line :String, bold := false) -> String:
var cells := ""
for cell in line.split("|"):
if bold:
cell = "[b]%s[/b]" % cell
cells += "[cell]%s[/cell]" % cell
return cells
func process_image_references(p_regex :RegEx, p_input :String) -> String:
# exists references?
var matches := p_regex.search_all(p_input)
if matches.is_empty():
return p_input
# collect image references and remove_at it
var references := Dictionary()
var link_regex := regex("\\[(\\S+)\\]:(\\S+)([ ]\"(.*)\")?")
# create copy of original source to replace checked it
var input := p_input.replace("\r", "")
var extracted_references := p_input.replace("\r", "")
for reg_match in link_regex.search_all(input):
var line = reg_match.get_string(0) + "\n"
var ref = reg_match.get_string(1)
#var topl_tip = reg_match.get_string(4)
# collect reference and url
references[ref] = reg_match.get_string(2)
extracted_references = extracted_references.replace(line, "")
# replace image references by collected url's
for reference_key in references.keys():
var regex_key := regex("\\](\\[%s\\])" % reference_key)
for reg_match in regex_key.search_all(extracted_references):
var ref :String = reg_match.get_string(0)
var image_url :String = "](%s)" % references.get(reference_key)
extracted_references = extracted_references.replace(ref, image_url)
return extracted_references
func process_image(p_regex :RegEx, p_input :String) -> String:
var to_replace := PackedStringArray()
var tool_tips := PackedStringArray()
# find all matches
var matches := p_regex.search_all(p_input)
if matches.is_empty():
return p_input
for reg_match in matches:
# grap the parts to replace and store temporay because a direct replace will distort the offsets
to_replace.append(p_input.substr(reg_match.get_start(0), reg_match.get_end(0)))
# grap optional tool tips
tool_tips.append(reg_match.get_string(5))
# finally replace all findings
for replace in to_replace:
var re := p_regex.sub(replace, "[img]$2[/img]")
p_input = p_input.replace(replace, re)
return await _process_external_image_resources(p_input)
func _process_external_image_resources(input :String) -> String:
DirAccess.make_dir_recursive_absolute(image_download_folder)
# scan all img for external resources and download it
for value in _img_replace_regex.search_all(input):
if value.get_group_count() >= 1:
var image_url :String = value.get_string(1)
# if not a local resource we need to download it
if image_url.begins_with("http"):
if OS.is_stdout_verbose():
prints("download image:", image_url)
var response = await _client.request_image(image_url)
if response.code() == 200:
var image = Image.new()
var error = image.load_png_from_buffer(response.body())
if error != OK:
prints("Error creating image from response", error)
# replace characters where format characters
var new_url := image_download_folder + image_url.get_file().replace("_", "-")
if new_url.get_extension() != 'png':
new_url = new_url + '.png'
var err := image.save_png(new_url)
if err:
push_error("Can't save image to '%s'. Error: %s" % [new_url, error_string(err)])
_image_urls.append(new_url)
input = input.replace(image_url, new_url)
return input

View file

@ -0,0 +1,42 @@
extends RefCounted
## Credits: Copied from https://github.com/MikeSchulze/gdUnit4/blob/99b7c323f443e5fcc67f9a79b4df532727e8986f/addons/gdUnit4/src/core/GdUnit4Version.gd before edits.
const VERSION_PATTERN = "[center][color=#9887c4]gd[/color][color=#7a57d6]Unit[/color][color=#9887c4]4[/color] [color=#9887c4]${version}[/color][/center]"
var _major :int
var _minor :int
var _patch :int
func _init(major :int,minor :int,patch :int):
_major = major
_minor = minor
_patch = patch
static func parse(value :String):
var regex := RegEx.new()
regex.compile("[a-zA-Z:,-]+")
var cleaned := regex.sub(value, "", true)
var parts := cleaned.split(".")
var major := parts[0].to_int()
var minor := parts[1].to_int()
var patch := parts[2].to_int() if parts.size() > 2 else 0
return new(major, minor, patch)
func equals(other :) -> bool:
return _major == other._major and _minor == other._minor and _patch == other._patch
func is_greater(other :) -> bool:
if _major > other._major:
return true
if _major == other._major and _minor > other._minor:
return true
return _major == other._major and _minor == other._minor and _patch > other._patch
func _to_string() -> String:
return "v%d.%d.%d" % [_major, _minor, _patch]