Compare commits

...
Sign in to create a new pull request.

9 commits

Author SHA1 Message Date
407a59d3eb I give up 2025-05-01 01:03:40 +02:00
0490edb8ec This should be a Texture2D 2025-05-01 00:18:45 +02:00
d77486f91a Hat Guy is now a resource 2025-05-01 00:18:16 +02:00
b478843a03 Legacy import hat guy 2025-04-30 23:45:56 +02:00
47b8e556c1 Legacy import progress 2025-04-30 23:39:00 +02:00
8b3b1a5884 In the middle of it 2025-04-30 21:31:31 +02:00
4c64946609 Cleanup and stuff 2025-04-30 16:45:19 +02:00
72bcd912bb This is a bunch of strings
Helps with self documentation
2025-04-29 23:25:00 +02:00
137c317f09 Whose balls? 2025-04-29 22:04:22 +02:00
47 changed files with 967 additions and 406 deletions

View file

@ -21,11 +21,7 @@ var _socket := WebSocketPeer.new()
var _config := ConfigFile.new()
func _ready() -> void:
if Saving.settings.has("useStreamDeck"):
if !Saving.settings["useStreamDeck"]:
return
else:
if !Config.settings.useStreamDeck:
return
_load_config(_get_config_path())

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
uid://dqsikysw3ch7s

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dsir4ejkj8puy"
path="res://.godot/imported/eyes_closed.png-12c4263a2a91a0534f989bc9275bbd7d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://default_avatars/hat_guy/eyes_closed.png"
dest_files=["res://.godot/imported/eyes_closed.png-12c4263a2a91a0534f989bc9275bbd7d.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: 6.2 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://4x3v7t763j2w"
path="res://.godot/imported/eyes_open.png-b2522b2294c35a5797861e391ceb2ff8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://default_avatars/hat_guy/eyes_open.png"
dest_files=["res://.godot/imported/eyes_open.png-b2522b2294c35a5797861e391ceb2ff8.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: 6.5 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://brvu2i85mnr65"
path="res://.godot/imported/eyes_open_speaking.png-6409987f612bc32d553abbf3f7cc6ff1.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://default_avatars/hat_guy/eyes_open_speaking.png"
dest_files=["res://.godot/imported/eyes_open_speaking.png-6409987f612bc32d553abbf3f7cc6ff1.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: 55 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b7d05wfdvqbmo"
path="res://.godot/imported/hair.png-f53ac7b29afa34df1fea5a0fb7b9f2c9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://default_avatars/hat_guy/hair.png"
dest_files=["res://.godot/imported/hair.png-f53ac7b29afa34df1fea5a0fb7b9f2c9.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: 43 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://uvf6v845pqtw"
path="res://.godot/imported/hat.png-ff3f9691c4c57fb49dc1f851fddd1b84.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://default_avatars/hat_guy/hat.png"
dest_files=["res://.godot/imported/hat.png-ff3f9691c4c57fb49dc1f851fddd1b84.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,233 @@
[gd_resource type="Resource" script_class="AvatarData" load_steps=21 format=3 uid="uid://0i4r45tgno0q"]
[ext_resource type="Script" uid="uid://b73on8ic2acsv" path="res://scripts/avatar_data.gd" id="1_re035"]
[ext_resource type="Script" uid="uid://b07e67yn4uh6d" path="res://scripts/sprite_data.gd" id="2_cjoo4"]
[ext_resource type="Texture2D" uid="uid://kpb0f3fkimex" path="res://default_avatars/hat_guy/head.png" id="3_nklgv"]
[ext_resource type="Texture2D" uid="uid://b7d05wfdvqbmo" path="res://default_avatars/hat_guy/hair.png" id="3_qwcja"]
[ext_resource type="Texture2D" uid="uid://bgomt0jm4rca3" path="res://default_avatars/hat_guy/mouth_closed.png" id="4_ifxpp"]
[ext_resource type="Texture2D" uid="uid://bse3li76fy8pi" path="res://default_avatars/hat_guy/torso.png" id="4_yx2bh"]
[ext_resource type="Texture2D" uid="uid://jiw5ygsr5eus" path="res://default_avatars/hat_guy/mouth_open.png" id="5_au626"]
[ext_resource type="Texture2D" uid="uid://brvu2i85mnr65" path="res://default_avatars/hat_guy/eyes_open_speaking.png" id="6_3l3vd"]
[ext_resource type="Texture2D" uid="uid://4x3v7t763j2w" path="res://default_avatars/hat_guy/eyes_open.png" id="7_7j5wo"]
[ext_resource type="Texture2D" uid="uid://dsir4ejkj8puy" path="res://default_avatars/hat_guy/eyes_closed.png" id="8_od6o0"]
[ext_resource type="Texture2D" uid="uid://uvf6v845pqtw" path="res://default_avatars/hat_guy/hat.png" id="9_fqo7r"]
[sub_resource type="Resource" id="Resource_vd21u"]
script = ExtResource("2_cjoo4")
anim_speed = 0
clipped = false
costume_layers = Array[bool]([true, true, true, true, true, true, true, true, true, true])
drag_speed = 0
frames = 1
ignore_bounce = false
image = ExtResource("3_qwcja")
offset = Vector2(0, 0)
pos = Vector2(0, 0)
r_limit_max = 180
r_limit_min = -180
rot_drag = 0
show_blink = 0
show_talk = 0
stretch_amount = 2.0
x_amp = 0.0
x_frq = 0.0
y_amp = 0.0
y_frq = 0.0
zindex = -2.0
children = Array[ExtResource("2_cjoo4")]([])
[sub_resource type="Resource" id="Resource_2ut1u"]
script = ExtResource("2_cjoo4")
anim_speed = 0
clipped = false
costume_layers = Array[bool]([true, true, true, true, true, true, true, true, true, true])
drag_speed = 0
frames = 1
ignore_bounce = false
image = ExtResource("4_ifxpp")
offset = Vector2(0, 0)
pos = Vector2(0, 0)
r_limit_max = 180
r_limit_min = -180
rot_drag = 0
show_blink = 0
show_talk = 1.0
stretch_amount = 0.0
x_amp = 0.0
x_frq = 0.0
y_amp = 0.0
y_frq = 0.0
zindex = 0
children = Array[ExtResource("2_cjoo4")]([])
[sub_resource type="Resource" id="Resource_ifxpp"]
script = ExtResource("2_cjoo4")
anim_speed = 0
clipped = false
costume_layers = Array[bool]([true, true, true, true, true, true, true, true, true, true])
drag_speed = 0
frames = 1
ignore_bounce = false
image = ExtResource("5_au626")
offset = Vector2(0, 0)
pos = Vector2(0, 0)
r_limit_max = 180
r_limit_min = -180
rot_drag = 0
show_blink = 0
show_talk = 2.0
stretch_amount = 0.0
x_amp = 0.0
x_frq = 0.0
y_amp = 0.0
y_frq = 0.0
zindex = 0
children = Array[ExtResource("2_cjoo4")]([])
[sub_resource type="Resource" id="Resource_7j5wo"]
script = ExtResource("2_cjoo4")
anim_speed = 0
clipped = false
costume_layers = Array[bool]([true, true, true, true, true, true, true, true, true, true])
drag_speed = 0
frames = 1
ignore_bounce = false
image = ExtResource("6_3l3vd")
offset = Vector2(0, 0)
pos = Vector2(0, 0)
r_limit_max = 180
r_limit_min = -180
rot_drag = 0
show_blink = 1.0
show_talk = 2.0
stretch_amount = 0.0
x_amp = 0.0
x_frq = 0.0
y_amp = 0.0
y_frq = 0.0
zindex = 0
children = Array[ExtResource("2_cjoo4")]([])
[sub_resource type="Resource" id="Resource_dxpem"]
script = ExtResource("2_cjoo4")
anim_speed = 0
clipped = false
costume_layers = Array[bool]([true, true, true, true, true, true, true, true, true, true])
drag_speed = 0
frames = 1
ignore_bounce = false
image = ExtResource("7_7j5wo")
offset = Vector2(0, 0)
pos = Vector2(0, 0)
r_limit_max = 180
r_limit_min = -180
rot_drag = 0
show_blink = 1.0
show_talk = 1.0
stretch_amount = 0.0
x_amp = 0.0
x_frq = 0.0
y_amp = 0.0
y_frq = 0.0
zindex = 0
children = Array[ExtResource("2_cjoo4")]([])
[sub_resource type="Resource" id="Resource_sinbd"]
script = ExtResource("2_cjoo4")
anim_speed = 0
clipped = false
costume_layers = Array[bool]([true, true, true, true, true, true, true, true, true, true])
drag_speed = 0
frames = 1
ignore_bounce = false
image = ExtResource("8_od6o0")
offset = Vector2(0, 0)
pos = Vector2(0, 0)
r_limit_max = 180
r_limit_min = -180
rot_drag = 0
show_blink = 2.0
show_talk = 0
stretch_amount = 0.0
x_amp = 0.0
x_frq = 0.0
y_amp = 0.0
y_frq = 0.0
zindex = 0
children = Array[ExtResource("2_cjoo4")]([])
[sub_resource type="Resource" id="Resource_herda"]
script = ExtResource("2_cjoo4")
anim_speed = 0
clipped = false
costume_layers = Array[bool]([true, true, true, true, true, true, true, true, true, true])
drag_speed = 0
frames = 1
ignore_bounce = false
image = ExtResource("9_fqo7r")
offset = Vector2(-74, 92)
pos = Vector2(72, -89)
r_limit_max = 17.0
r_limit_min = -14.0
rot_drag = -1.0
show_blink = 0
show_talk = 0
stretch_amount = 0.0
x_amp = 0.0
x_frq = 0.0
y_amp = 0.0
y_frq = 0.0
zindex = 2.0
children = Array[ExtResource("2_cjoo4")]([])
[sub_resource type="Resource" id="Resource_dqjmw"]
script = ExtResource("2_cjoo4")
anim_speed = 0
clipped = false
costume_layers = Array[bool]([true, true, true, true, true, true, true, true, true, true])
drag_speed = 1.0
frames = 1
ignore_bounce = false
image = ExtResource("3_nklgv")
offset = Vector2(0, 0)
pos = Vector2(0, 0)
r_limit_max = 180
r_limit_min = -180
rot_drag = 0
show_blink = 0
show_talk = 0
stretch_amount = 0.0
x_amp = 0.0
x_frq = 0.0
y_amp = 0.0
y_frq = 0.0
zindex = 0
children = Array[ExtResource("2_cjoo4")]([SubResource("Resource_vd21u"), SubResource("Resource_2ut1u"), SubResource("Resource_ifxpp"), SubResource("Resource_7j5wo"), SubResource("Resource_dxpem"), SubResource("Resource_sinbd"), SubResource("Resource_herda")])
[sub_resource type="Resource" id="Resource_h4n0i"]
script = ExtResource("2_cjoo4")
anim_speed = 0
clipped = false
costume_layers = Array[bool]([true, true, true, true, true, true, true, true, true, true])
drag_speed = 0
frames = 1
ignore_bounce = false
image = ExtResource("4_yx2bh")
offset = Vector2(0, 0)
pos = Vector2(0, 0)
r_limit_max = 180
r_limit_min = -180
rot_drag = 0
show_blink = 0
show_talk = 0
stretch_amount = 0.25
x_amp = 9.0
x_frq = 0.004
y_amp = 11.0
y_frq = 0.008
zindex = -1.0
children = Array[ExtResource("2_cjoo4")]([SubResource("Resource_dqjmw")])
[resource]
script = ExtResource("1_re035")
sprites = Array[ExtResource("2_cjoo4")]([SubResource("Resource_h4n0i")])

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://kpb0f3fkimex"
path="res://.godot/imported/head.png-e2914718512a4a40501f60740e5be3e5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://default_avatars/hat_guy/head.png"
dest_files=["res://.godot/imported/head.png-e2914718512a4a40501f60740e5be3e5.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: 3.4 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bgomt0jm4rca3"
path="res://.godot/imported/mouth_closed.png-153cd499e9f8e1d7fedcfc4d6ff19f09.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://default_avatars/hat_guy/mouth_closed.png"
dest_files=["res://.godot/imported/mouth_closed.png-153cd499e9f8e1d7fedcfc4d6ff19f09.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: 5.8 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://jiw5ygsr5eus"
path="res://.godot/imported/mouth_open.png-18177d9c2351b894e0bd89033dcbd8bb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://default_avatars/hat_guy/mouth_open.png"
dest_files=["res://.godot/imported/mouth_open.png-18177d9c2351b894e0bd89033dcbd8bb.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: 19 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bse3li76fy8pi"
path="res://.godot/imported/torso.png-d468966dc8d74a1a04ac15ce2dcb5d59.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://default_avatars/hat_guy/torso.png"
dest_files=["res://.godot/imported/torso.png-d468966dc8d74a1a04ac15ce2dcb5d59.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

3
empty.tscn Normal file
View file

@ -0,0 +1,3 @@
[gd_scene format=3 uid="uid://blqhhndk1dwv7"]
[node name="Empty" type="Node2D"]

View file

@ -1,6 +1,6 @@
[configuration]
entry_symbol = "gdext_rust_init"
compatibility_minimum = 4.4
compatibility_minimum = 4.1
reloadable = true
[libraries]

View file

@ -0,0 +1 @@

View file

@ -1,144 +1,169 @@
use std::collections::HashSet;
use device_query::{DeviceQuery, DeviceState, Keycode};
use godot::{global::Key, prelude::*};
use godot::{classes::Engine, global::Key, prelude::*};
struct MyExtension;
const SINGLETON_NAME: &str = "BackgroundInputCapture";
#[gdextension]
unsafe impl ExtensionLibrary for MyExtension {}
unsafe impl ExtensionLibrary for MyExtension {
fn on_level_init(_level: InitLevel) {
Engine::singleton()
.register_singleton(SINGLETON_NAME, &BackgroundInputCapture::new_alloc());
}
fn on_level_deinit(_level: InitLevel) {
Engine::singleton().unregister_singleton(SINGLETON_NAME);
}
}
#[derive(GodotClass)]
#[class(init, base = Node)]
#[class(init, base = Object)]
pub struct BackgroundInputCapture {
device_state: DeviceState,
base: Base<Node>,
pressed_keys: HashSet<Keycode>,
base: Base<Object>,
}
#[godot_api]
impl BackgroundInputCapture {
#[func]
pub fn get_keys(&mut self) -> Vec<i32> {
self.device_state
.get_keys()
pub fn get_keys(&mut self) -> Dictionary {
let keys: HashSet<Keycode> = self.device_state.get_keys().into_iter().collect();
let just_pressed = keys.difference(&self.pressed_keys);
let just_released = self.pressed_keys.difference(&keys);
let output = just_pressed
.into_iter()
.filter_map(|k| {
Some(
match k {
Keycode::Key0 => Key::KEY_0,
Keycode::Key1 => Key::KEY_1,
Keycode::Key2 => Key::KEY_2,
Keycode::Key3 => Key::KEY_3,
Keycode::Key4 => Key::KEY_4,
Keycode::Key5 => Key::KEY_5,
Keycode::Key6 => Key::KEY_6,
Keycode::Key7 => Key::KEY_7,
Keycode::Key8 => Key::KEY_8,
Keycode::Key9 => Key::KEY_9,
Keycode::A => Key::A,
Keycode::B => Key::B,
Keycode::C => Key::C,
Keycode::D => Key::D,
Keycode::E => Key::E,
Keycode::F => Key::F,
Keycode::G => Key::G,
Keycode::H => Key::H,
Keycode::I => Key::I,
Keycode::J => Key::J,
Keycode::K => Key::K,
Keycode::L => Key::L,
Keycode::M => Key::M,
Keycode::N => Key::N,
Keycode::O => Key::O,
Keycode::P => Key::P,
Keycode::Q => Key::Q,
Keycode::R => Key::R,
Keycode::S => Key::S,
Keycode::T => Key::T,
Keycode::U => Key::U,
Keycode::V => Key::V,
Keycode::W => Key::W,
Keycode::X => Key::X,
Keycode::Y => Key::Y,
Keycode::Z => Key::Z,
Keycode::F1 => Key::F1,
Keycode::F2 => Key::F2,
Keycode::F3 => Key::F3,
Keycode::F4 => Key::F4,
Keycode::F5 => Key::F5,
Keycode::F6 => Key::F6,
Keycode::F7 => Key::F7,
Keycode::F8 => Key::F8,
Keycode::F9 => Key::F9,
Keycode::F10 => Key::F10,
Keycode::F11 => Key::F11,
Keycode::F12 => Key::F12,
Keycode::F13 => Key::F13,
Keycode::F14 => Key::F14,
Keycode::F15 => Key::F15,
Keycode::F16 => Key::F16,
Keycode::F17 => Key::F17,
Keycode::F18 => Key::F18,
Keycode::F19 => Key::F19,
Keycode::F20 => Key::F20,
Keycode::Escape => Key::ESCAPE,
Keycode::Space => Key::SPACE,
Keycode::LControl => return None,
Keycode::RControl => return None,
Keycode::LShift => return None,
Keycode::RShift => return None,
Keycode::LAlt => return None,
Keycode::RAlt => return None,
Keycode::Command => return None,
Keycode::RCommand => return None,
Keycode::LOption => return None,
Keycode::ROption => return None,
Keycode::LMeta => return None,
Keycode::RMeta => return None,
Keycode::Enter => Key::ENTER,
Keycode::Up => Key::UP,
Keycode::Down => Key::DOWN,
Keycode::Left => Key::LEFT,
Keycode::Right => Key::RIGHT,
Keycode::Backspace => Key::BACKSPACE,
Keycode::CapsLock => Key::CAPSLOCK,
Keycode::Tab => Key::TAB,
Keycode::Home => Key::HOME,
Keycode::End => Key::END,
Keycode::PageUp => Key::PAGEUP,
Keycode::PageDown => Key::PAGEDOWN,
Keycode::Insert => Key::INSERT,
Keycode::Delete => Key::DELETE,
Keycode::Numpad0 => Key::KP_0,
Keycode::Numpad1 => Key::KP_1,
Keycode::Numpad2 => Key::KP_2,
Keycode::Numpad3 => Key::KP_3,
Keycode::Numpad4 => Key::KP_4,
Keycode::Numpad5 => Key::KP_5,
Keycode::Numpad6 => Key::KP_6,
Keycode::Numpad7 => Key::KP_7,
Keycode::Numpad8 => Key::KP_8,
Keycode::Numpad9 => Key::KP_9,
Keycode::NumpadSubtract => Key::KP_SUBTRACT,
Keycode::NumpadAdd => Key::KP_ADD,
Keycode::NumpadDivide => Key::KP_DIVIDE,
Keycode::NumpadMultiply => Key::KP_MULTIPLY,
Keycode::NumpadEquals => Key::EQUAL,
Keycode::NumpadEnter => Key::KP_ENTER,
Keycode::NumpadDecimal => Key::KP_PERIOD,
Keycode::Grave => Key::QUOTELEFT,
Keycode::Minus => Key::MINUS,
Keycode::Equal => Key::EQUAL,
Keycode::LeftBracket => Key::BRACKETLEFT,
Keycode::RightBracket => Key::BRACKETRIGHT,
Keycode::BackSlash => Key::BACKSLASH,
Keycode::Semicolon => Key::SEMICOLON,
Keycode::Apostrophe => Key::APOSTROPHE,
Keycode::Comma => Key::COMMA,
Keycode::Dot => Key::PERIOD,
Keycode::Slash => Key::SLASH,
}
.to_godot(),
)
})
.collect()
.filter_map(|k| Some((keycode_to_key(k)?, true)))
.chain(
just_released
.into_iter()
.filter_map(|k| Some((keycode_to_key(k)?, false))),
)
.collect();
self.pressed_keys = keys;
output
}
}
fn keycode_to_key(key: &Keycode) -> Option<i32> {
Some(
match key {
Keycode::Key0 => Key::KEY_0,
Keycode::Key1 => Key::KEY_1,
Keycode::Key2 => Key::KEY_2,
Keycode::Key3 => Key::KEY_3,
Keycode::Key4 => Key::KEY_4,
Keycode::Key5 => Key::KEY_5,
Keycode::Key6 => Key::KEY_6,
Keycode::Key7 => Key::KEY_7,
Keycode::Key8 => Key::KEY_8,
Keycode::Key9 => Key::KEY_9,
Keycode::A => Key::A,
Keycode::B => Key::B,
Keycode::C => Key::C,
Keycode::D => Key::D,
Keycode::E => Key::E,
Keycode::F => Key::F,
Keycode::G => Key::G,
Keycode::H => Key::H,
Keycode::I => Key::I,
Keycode::J => Key::J,
Keycode::K => Key::K,
Keycode::L => Key::L,
Keycode::M => Key::M,
Keycode::N => Key::N,
Keycode::O => Key::O,
Keycode::P => Key::P,
Keycode::Q => Key::Q,
Keycode::R => Key::R,
Keycode::S => Key::S,
Keycode::T => Key::T,
Keycode::U => Key::U,
Keycode::V => Key::V,
Keycode::W => Key::W,
Keycode::X => Key::X,
Keycode::Y => Key::Y,
Keycode::Z => Key::Z,
Keycode::F1 => Key::F1,
Keycode::F2 => Key::F2,
Keycode::F3 => Key::F3,
Keycode::F4 => Key::F4,
Keycode::F5 => Key::F5,
Keycode::F6 => Key::F6,
Keycode::F7 => Key::F7,
Keycode::F8 => Key::F8,
Keycode::F9 => Key::F9,
Keycode::F10 => Key::F10,
Keycode::F11 => Key::F11,
Keycode::F12 => Key::F12,
Keycode::F13 => Key::F13,
Keycode::F14 => Key::F14,
Keycode::F15 => Key::F15,
Keycode::F16 => Key::F16,
Keycode::F17 => Key::F17,
Keycode::F18 => Key::F18,
Keycode::F19 => Key::F19,
Keycode::F20 => Key::F20,
Keycode::Escape => Key::ESCAPE,
Keycode::Space => Key::SPACE,
Keycode::LControl => return None,
Keycode::RControl => return None,
Keycode::LShift => return None,
Keycode::RShift => return None,
Keycode::LAlt => return None,
Keycode::RAlt => return None,
Keycode::Command => return None,
Keycode::RCommand => return None,
Keycode::LOption => return None,
Keycode::ROption => return None,
Keycode::LMeta => return None,
Keycode::RMeta => return None,
Keycode::Enter => Key::ENTER,
Keycode::Up => Key::UP,
Keycode::Down => Key::DOWN,
Keycode::Left => Key::LEFT,
Keycode::Right => Key::RIGHT,
Keycode::Backspace => Key::BACKSPACE,
Keycode::CapsLock => Key::CAPSLOCK,
Keycode::Tab => Key::TAB,
Keycode::Home => Key::HOME,
Keycode::End => Key::END,
Keycode::PageUp => Key::PAGEUP,
Keycode::PageDown => Key::PAGEDOWN,
Keycode::Insert => Key::INSERT,
Keycode::Delete => Key::DELETE,
Keycode::Numpad0 => Key::KP_0,
Keycode::Numpad1 => Key::KP_1,
Keycode::Numpad2 => Key::KP_2,
Keycode::Numpad3 => Key::KP_3,
Keycode::Numpad4 => Key::KP_4,
Keycode::Numpad5 => Key::KP_5,
Keycode::Numpad6 => Key::KP_6,
Keycode::Numpad7 => Key::KP_7,
Keycode::Numpad8 => Key::KP_8,
Keycode::Numpad9 => Key::KP_9,
Keycode::NumpadSubtract => Key::KP_SUBTRACT,
Keycode::NumpadAdd => Key::KP_ADD,
Keycode::NumpadDivide => Key::KP_DIVIDE,
Keycode::NumpadMultiply => Key::KP_MULTIPLY,
Keycode::NumpadEquals => Key::EQUAL,
Keycode::NumpadEnter => Key::KP_ENTER,
Keycode::NumpadDecimal => Key::KP_PERIOD,
Keycode::Grave => Key::QUOTELEFT,
Keycode::Minus => Key::MINUS,
Keycode::Equal => Key::EQUAL,
Keycode::LeftBracket => Key::BRACKETLEFT,
Keycode::RightBracket => Key::BRACKETRIGHT,
Keycode::BackSlash => Key::BACKSLASH,
Keycode::Semicolon => Key::SEMICOLON,
Keycode::Apostrophe => Key::APOSTROPHE,
Keycode::Comma => Key::COMMA,
Keycode::Dot => Key::PERIOD,
Keycode::Slash => Key::SLASH,
}
.to_godot(),
)
}

View file

@ -48,13 +48,6 @@ var bounceChange = 0.0
#IMPORTANT
var fileSystemOpen = false
#background input capture
signal emptiedCapture
signal pressedKey
var costumeKeys = ["1","2","3","4","5","6","7","8","9","0"]
signal spriteVisToggles(keysPressed:Array)
signal fatfuckingballs
func _ready():
Global.main = self
Global.fail = $Failed
@ -133,7 +126,6 @@ func _ready():
camera.position = origin.position
func _process(delta):
process_key_presses($BackgroundInputCapture.get_keys())
var hold = origin.get_parent().position.y
origin.get_parent().position.y += yVel * 0.0166
@ -269,9 +261,7 @@ func swapMode():
#Adds sprite object to scene
func add_image(path):
var rand = RandomNumberGenerator.new()
var id = rand.randi()
var id = randi()
var sprite = spriteObject.instantiate()
sprite.path = path
@ -300,7 +290,11 @@ func _on_load_button_pressed():
#LOAD AVATAR
func _on_load_dialog_file_selected(path):
var data = Saving.read_save(path)
var data
if path == "default":
data = load("res://default_avatars/hat_guy/hat_guy.tres")
else:
data = load(path)
if data == null:
return
@ -459,8 +453,7 @@ func _on_replace_dialog_visibility_changed():
func _on_duplicate_button_pressed():
if Global.heldSprite == null:
return
var rand = RandomNumberGenerator.new()
var id = rand.randi()
var id = randi()
var sprite = spriteObject.instantiate()
sprite.path = Global.heldSprite.path
@ -583,52 +576,3 @@ func _on_button_pressed():
func _on_settings_buttons_pressed():
settingsMenu.visible = !settingsMenu.visible
func process_key_presses(keys_pressed):
var keyStrings = []
for i in keys_pressed:
keyStrings.append(OS.get_keycode_string(i) if !OS.get_keycode_string(i).strip_edges().is_empty() else "Keycode" + str(i))
if fileSystemOpen:
return
if keyStrings.size() <= 0:
emit_signal("emptiedCapture")
return
if settingsMenu.awaitingCostumeInput >= 0:
if keyStrings[0] == "Keycode1":
if !settingsMenu.hasMouse:
emit_signal("pressedKey")
return
var currentButton = costumeKeys[settingsMenu.awaitingCostumeInput]
costumeKeys[settingsMenu.awaitingCostumeInput] = keyStrings[0]
Saving.settings["costumeKeys"] = costumeKeys
Global.pushUpdate("Changed costume " + str(settingsMenu.awaitingCostumeInput+1) + " hotkey from \"" + currentButton + "\" to \"" + keyStrings[0] + "\"")
emit_signal("pressedKey")
for key in keyStrings:
var i = costumeKeys.find(key)
if i >= 0:
changeCostume(i+1)
func bgInputSprite(node, keys_pressed):
if fileSystemOpen:
return
var keyStrings = []
for i in keys_pressed:
if keys_pressed[i]:
keyStrings.append(OS.get_keycode_string(i) if !OS.get_keycode_string(i).strip_edges().is_empty() else "Keycode" + str(i))
if keyStrings.size() <= 0:
emit_signal("fatfuckingballs")
return
spriteVisToggles.emit(keyStrings)

View file

@ -619,8 +619,6 @@ texture = ExtResource("24_joqmn")
[node name="Camera2D" type="Camera2D" parent="."]
position = Vector2(360, 360)
[node name="BackgroundInputCapture" type="BackgroundInputCapture" parent="."]
[node name="PushUpdates" parent="." instance=ExtResource("30_q43vl")]
z_index = 4090
position = Vector2(0, 720)

View file

@ -26,10 +26,10 @@ driver/enable_input=true
[autoload]
Saving="*res://autoload/saving.gd"
Global="*res://autoload/global.gd"
Config="*res://scripts/autoload/config.gd"
Global="*res://scripts/autoload/global.gd"
ElgatoStreamDeck="*res://addons/godot-streamdeck-addon/singleton.gd"
DefaultAvatarData="*res://autoload/defaultAvatarData.gd"
InputHandler="*res://scripts/autoload/input_handler.gd"
[debug]

View file

@ -40,58 +40,18 @@ var default = {
"2": { "drag": 4, "identification": 928082759, "offset": "Vector2(0, 0)", "parentId": 456157398, "path": "user://defaultAvatar/hair.png", "pos": "Vector2(0, 0)", "rotDrag": 0, "showBlink": 0, "showTalk": 0, "type": "sprite", "xAmp": 0, "xFrq": 0, "yAmp": 0, "yFrq": 0, "zindex": -2 }, "3": { "drag": 0, "identification": 346749260, "offset": "Vector2(0, 0)", "parentId": 456157398, "path": "user://defaultAvatar/mouth1.png", "pos": "Vector2(0, 0)", "rotDrag": 0, "showBlink": 0, "showTalk": 1, "type": "sprite", "xAmp": 0, "xFrq": 0, "yAmp": 0, "yFrq": 0, "zindex": 0 }, "4": { "drag": 0, "identification": 348929106, "offset": "Vector2(0, 0)", "parentId": 456157398, "path": "user://defaultAvatar/mouth2.png", "pos": "Vector2(0, 0)", "rotDrag": 0, "showBlink": 0, "showTalk": 2, "type": "sprite", "xAmp": 0, "xFrq": 0, "yAmp": 0, "yFrq": 0, "zindex": 0 }, "5": { "drag": 0, "identification": 66364456, "offset": "Vector2(0, 0)", "parentId": 456157398, "path": "user://defaultAvatar/eye1.png", "pos": "Vector2(0, 0)", "rotDrag": 0, "showBlink": 1, "showTalk": 2, "type": "sprite", "xAmp": 0, "xFrq": 0, "yAmp": 0, "yFrq": 0, "zindex": 0 }, "6": { "drag": 0, "identification": 261040117, "offset": "Vector2(0, 0)", "parentId": 456157398, "path": "user://defaultAvatar/eye2.png", "pos": "Vector2(0, 0)", "rotDrag": 0, "showBlink": 1, "showTalk": 1, "type": "sprite", "xAmp": 0, "xFrq": 0, "yAmp": 0, "yFrq": 0, "zindex": 0 }, "7": { "drag": 0, "identification": 291459997, "offset": "Vector2(0, 0)", "parentId": 456157398, "path": "user://defaultAvatar/eye3.png", "pos": "Vector2(0, 0)", "rotDrag": 0, "showBlink": 2, "showTalk": 0, "type": "sprite", "xAmp": 0, "xFrq": 0, "yAmp": 0, "yFrq": 0, "zindex": 0 }, "8": { "drag": 0, "identification": 148065686, "offset": "Vector2(-74, 92)", "parentId": 456157398, "path": "user://defaultAvatar/hat.png", "pos": "Vector2(72, -89)", "rotDrag": -2, "showBlink": 0, "showTalk": 0, "type": "sprite", "xAmp": 0, "xFrq": 0, "yAmp": 0, "yFrq": 0, "zindex": 2 } }
var settings = {
"newUser":true,
"lastAvatar":"",
"volume":0.185,
"sense":0.25,
"windowSize":Vector2i(1280,720),
"useStreamDeck":false,
"bounce":250,
"gravity":1000,
"maxFPS":60,
"secondsToMicReset":180,
"backgroundColor":var_to_str(Color(0.0,0.0,0.0,0.0)),
"filtering":false,
"costumeKeys":["1","2","3","4","5","6","7","8","9","0"],
"blinkSpeed":1.0,
"blinkChance":200,
"bounceOnCostumeChange":false,
}
var settings: Settings = Settings.new()
var settingsPath = "user://settings.pngtp"
func _ready():
var datas = read_save(settingsPath)
if datas == null:
return
else:
settings = datas.duplicate()
var loaded_settings = load(settingsPath)
if loaded_settings != null:
settings = loaded_settings
func _exit_tree():
write_settings(settingsPath)
func read_save(path):
if path == "default":
return DefaultAvatarData.data
if OS.has_feature('web'):
var JSONstr = JavaScriptBridge.eval("window.localStorage.getItem('" + key + "');")
if (JSONstr):
return JSON.parse_string(JSONstr)
else:
return null
else:
var file = FileAccess.open(path, FileAccess.READ)
if not file:
return null
var newData = JSON.parse_string(file.get_as_text())
file.close()
return newData
func write_save(path):
if OS.has_feature('web'):
JavaScriptBridge.eval("window.localStorage.setItem('" + key + "', '" + JSON.stringify(data) + "');")

View file

@ -13,7 +13,7 @@ var animationTick = 0
var filtering = false
#Object Selection
var heldSprite = null
var heldSprite: SpriteObject = null
var lastArray = []
var i = 0
@ -48,19 +48,11 @@ var micResetTime = 180
var updatePusherNode = null
var rand = RandomNumberGenerator.new()
func _ready():
spectrum = AudioServer.get_bus_effect_instance(1, 1)
if !Saving.settings.has("useStreamDeck"):
Saving.settings["useStreamDeck"] = false
Global.micResetTime = Config.settings.secondsToMicReset
if Saving.settings.has("secondsToMicReset"):
Global.micResetTime = Saving.settings["secondsToMicReset"]
else:
Saving.settings["secondsToMicReset"] = 180
createMicrophone()
func createMicrophone():
@ -119,7 +111,8 @@ func _process(delta):
else:
reparentMode = false
Global.chain.enable(reparentMode)
#Global.chain.enable(reparentMode)
return
if main.editMode:
if reparentMode:
@ -277,10 +270,10 @@ func blinking():
blinkTick += 1
if blinkTick == 0:
blink = false
if rand.randf_range(-1.0,1.0) > 0.5:
if randf_range(-1.0,1.0) > 0.5:
blinkTick = (420 * blinkSpeed) + 1
if blinkTick > 420 * blinkSpeed:
if rand.randi() % int(blinkChance) == 0:
if randi() % int(blinkChance) == 0:
blink = true
blinkTick = -12

View file

@ -0,0 +1,77 @@
# Handles background inputs (inputs when unfocused)
extends Node
signal key_pressed(key: Key)
signal key_released(key: Key)
signal all_keys_released
#background input capture
signal emptiedCapture
signal pressedKey
var costumeKeys = ["1","2","3","4","5","6","7","8","9","0"]
var pressed_keys: Array[Key] = []
func should_fire_signal() -> bool:
return get_viewport().gui_get_focus_owner() == null or not DisplayServer.window_is_focused()
func _process(_delta):
# This is a Dictionary[Key, bool] but I can't return typed dicts nor cast them
var keys = BackgroundInputCapture.get_keys()
for key in keys:
if keys[key]:
pressed_keys.append(key)
if should_fire_signal():
key_pressed.emit(key)
else:
pressed_keys.erase(key)
if should_fire_signal():
key_released.emit(key)
#process_key_presses(keys)
#bgInputSprite(keys)
#
#func process_key_presses(keys_pressed: Dictionary[Key, bool]):
#if Global.main.fileSystemOpen:
#return
#
#var keyStrings = keys_pressed.map(
#func(i) -> String: return OS.get_keycode_string(i) if !OS.get_keycode_string(i).strip_edges().is_empty() else "Keycode" + str(i)
#)
#
#if keyStrings.size() <= 0:
#emit_signal("emptiedCapture")
#return
#
#if settingsMenu.awaitingCostumeInput >= 0:
#
#if keyStrings[0] == "Keycode1":
#if !settingsMenu.hasMouse:
#emit_signal("pressedKey")
#return
#
#var currentButton = costumeKeys[settingsMenu.awaitingCostumeInput]
#costumeKeys[settingsMenu.awaitingCostumeInput] = keyStrings[0]
#Saving.settings["costumeKeys"] = costumeKeys
#Global.pushUpdate("Changed costume " + str(settingsMenu.awaitingCostumeInput+1) + " hotkey from \"" + currentButton + "\" to \"" + keyStrings[0] + "\"")
#emit_signal("pressedKey")
#
#for key in keyStrings:
#var i = costumeKeys.find(key)
#if i >= 0:
#changeCostume(i+1)
#
#
## Handles background input for sprites
#func bgInputSprite(keys_pressed: Dictionary[Key, bool]):
#if fileSystemOpen:
#return
#
#if keys_pressed.size() <= 0:
#emit_signal("all_keys_released")
#return
#
#spriteVisToggles.emit(
#keys_pressed.map(
#func(i) -> String: return OS.get_keycode_string(i) if !OS.get_keycode_string(i).strip_edges().is_empty() else "Keycode" + str(i)
#)
#)

View file

@ -0,0 +1 @@
uid://y12b1vin2hpt

22
scripts/avatar_data.gd Normal file
View file

@ -0,0 +1,22 @@
extends Resource
class_name AvatarData
@export var sprites: Array[SpriteData] = []
static func from_legacy_json(data: String) -> AvatarData:
var sprites: Array[SpriteData] = []
var json_data = JSON.parse_string(data)
if json_data is not Dictionary: return null
for sprite_data in json_data.values():
if sprite_data is not Dictionary: return null
var sprite = SpriteData.from_legacy_dict(sprite_data)
sprites.append(sprite)
var avatar = new()
for sprite in sprites:
if sprite.legacy_parent_id != null:
var parent_index = sprites.find_custom(func(x): return x.legacy_id == sprite.legacy_parent_id)
if parent_index != -1:
sprites[parent_index].children.append(sprite)
continue
avatar.sprites.append(sprite)
return avatar

View file

@ -0,0 +1 @@
uid://b73on8ic2acsv

18
scripts/settings.gd Normal file
View file

@ -0,0 +1,18 @@
extends Resource
class_name Settings
@export_global_file var lastAvatar: String = ""
@export_range(0, 1, 0.05) var volume: float = 0.185
@export_range(0, 1, 0.05) var sense = 0.25
@export var windowSize = Vector2i(1280, 720)
@export var useStreamDeck = false
@export var bounce = 250
@export var gravity = 1000
@export var maxFPS: int = 60
@export var secondsToMicReset: float = 180
@export var backgroundColor: Color = Color.TRANSPARENT
@export var filtering = false
@export var costumeKeys: Array[Key] = [KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0]
@export var blinkSpeed: float = 1.0
@export var blinkChance = 200
@export var bounceOnCostumeChange = false

1
scripts/settings.gd.uid Normal file
View file

@ -0,0 +1 @@
uid://dmeqvexvccsav

77
scripts/sprite_data.gd Normal file
View file

@ -0,0 +1,77 @@
extends Resource
class_name SpriteData
@export var anim_speed = 0
@export var clipped = false
@export var costume_layers: Array[bool] = [true, true, true, true, true, true, true, true, true, true]
@export var drag_speed = 0
@export var frames = 1
@export var ignore_bounce = false
#@export_global_file var path = ""
@export var image: Texture2D
@export var offset = Vector2(0, 0)
@export var pos = Vector2(0, 0)
@export var r_limit_max = 180
@export var r_limit_min = -180
@export var rot_drag = 0
@export var show_blink = 0
@export var show_talk = 0
@export var stretch_amount = 0.0
@export var x_amp: float = 0
@export var x_frq: float = 0
@export var y_amp: float = 0
@export var y_frq: float = 0
@export var zindex = 0
@export var children: Array[SpriteData] = []
var legacy_id
var legacy_parent_id
static func from_legacy_dict(data: Dictionary) -> SpriteData:
var sprite = new()
sprite.anim_speed = data.get("animSpeed", sprite.anim_speed)
sprite.clipped = data.get("clipped", sprite.clipped)
if "costumeLayers" in data:
var layers: Array[bool] = []
for l in str_to_var(data["costumeLayers"]):
layers.append(l == 1) # .map doesn't result in a typed array :/
sprite.costume_layers = layers
sprite.drag_speed = data.get("drag", sprite.drag_speed)
sprite.frames = data.get("frames", sprite.frames)
sprite.ignore_bounce = data.get("ignoreBounce", sprite.ignore_bounce)
if "path" in data:
sprite.image = Image.load_from_file(data["path"])
if sprite.image == null:
if "imageData" not in data: return null
var image = Image.new()
var error = image.load_png_from_buffer(Marshalls.base64_to_raw(data["imageData"]))
if error != OK:
return null
sprite.image = ImageTexture.create_from_image(image)
sprite.offset = legacy_get_from_string(data, "offset", sprite.offset)
sprite.pos = legacy_get_from_string(data, "pos", sprite.pos)
sprite.r_limit_max = data.get("rLimitMax", sprite.r_limit_max)
sprite.r_limit_min = data.get("rLimitMin", sprite.r_limit_min)
sprite.rot_drag = data.get("rotDrag", sprite.rot_drag)
sprite.show_blink = data.get("showBlink", sprite.show_blink)
sprite.show_talk = data.get("showTalk", sprite.show_talk)
sprite.stretch_amount = data.get("stretchAmount", sprite.stretch_amount)
sprite.x_amp = data.get("xAmp", sprite.x_amp)
sprite.x_frq = data.get("xFrq", sprite.x_frq)
sprite.y_amp = data.get("yAmp", sprite.y_amp)
sprite.y_frq = data.get("yFrq", sprite.y_frq)
sprite.zindex = data.get("zindex", sprite.zindex)
sprite.legacy_id = data.get("identification")
sprite.legacy_parent_id = data.get("parentId")
return sprite
static func legacy_get_from_string(data: Dictionary, index: String, default: Variant) -> Variant:
if index in data:
return str_to_var(data[index])
return default

View file

@ -0,0 +1 @@
uid://b07e67yn4uh6d

View file

@ -1,11 +0,0 @@
shader_type canvas_item;
uniform sampler2D noise_texture:repeat_enable;
uniform float distortion_strengh: hint_range(0, 0.1) = 1.0;
uniform float speed: hint_range(0.1, 10) = 1.0;
void fragment() {
vec4 noise_pixel = texture(noise_texture, UV + floor(TIME*speed)/3.0);
vec2 uv_offset = (noise_pixel.rg * 2.0 - 1.0) * distortion_strengh;
COLOR = texture(TEXTURE, UV + uv_offset);
}

View file

@ -1 +0,0 @@
uid://ddgp8n4l7veuh

View file

@ -1,38 +1,21 @@
extends Node2D
class_name SpriteObject
var type = "sprite"
@onready var sprite = $WobbleOrigin/DragOrigin/Sprite
@onready var grabArea = $WobbleOrigin/DragOrigin/Grab
@onready var dragOrigin = $WobbleOrigin/DragOrigin
@onready var dragger = $WobbleOrigin/Dragger
@onready var originSprite = $WobbleOrigin/DragOrigin/Sprite/Origin
@onready var wob = $WobbleOrigin
@onready var outlineScene = preload("res://ui_scenes/selectedSprite/outline.tscn")
#Passed Variables
var imageData = null
var tex = null
@export var path = ""
var loadedImageData = null
var id = 0
var parentId = null
var sprite_data: SpriteData
var parentSprite = null
var imageSize = Vector2.ZERO
#Node Reference
@onready var sprite = $WobbleOrigin/DragOrigin/Sprite
@onready var grabArea = $WobbleOrigin/DragOrigin/Grab
@onready var dragOrigin = $WobbleOrigin/DragOrigin
@onready var dragger = $WobbleOrigin/Dragger
@onready var originSprite = $WobbleOrigin/DragOrigin/Sprite/Origin
@onready var wob = $WobbleOrigin
@onready var outlineScene = preload("res://ui_scenes/selectedSprite/outline.tscn")
#Visuals
var mouseOffset = Vector2.ZERO
var grabDelay = 0
var size = Vector2(1,1)
var size = Vector2(1, 1)
var showOnTalk = 0
var showOnBlink = 0
@ -43,82 +26,27 @@ var z = 0
var heldTicks = 0
var dragSpeed = 0
#Origin
var origTick = 0
var offset = Vector2.ZERO
#Wobble
var xFrq = 0.0
var xAmp = 0.0
var yFrq = 0.0
var yAmp = 0.0
#Rotational Drag
var rdragStr = 0
var rLimitMax = 180
var rLimitMin = -180
#Layer
var costumeLayers = [1,1,1,1,1,1,1,1,1,1]
#Stretch
var stretchAmount = 0.0
#Ignore Bounce
var ignoreBounce = false
#Animation
var frames = 1
var animSpeed = 0
var remadePolygon = false
var clipped = false
var tick = 0
#Vis toggle
var toggle = "null"
var toggle: Key = KEY_NONE
func _ready():
InputHandler.key_pressed.connect(visToggle)
Global.main.spriteVisToggles.connect(visToggle)
imageSize = sprite_data.image.get_size()
var img = Image.new()
var err = img.load(path)
if err != OK:
#Runs if image import fails. Needs error dialog box at some point
if loadedImageData == null:
Global.epicFail(err)
print_debug("Failed to load image.")
queue_free()
return
else:
var data = Marshalls.base64_to_raw(loadedImageData)
var errr = img.load_png_from_buffer(data)
if errr != OK:
Global.epicFail(err)
print_debug("Failed to load image.")
queue_free()
return
var texture = ImageTexture.new()
texture = ImageTexture.create_from_image(img)
tex = texture
imageData = img
imageSize = img.get_size()
sprite.texture = tex
sprite.texture = sprite_data.image
var bitmap = BitMap.new()
bitmap.create_from_image_alpha(imageData)
bitmap.create_from_image_alpha(sprite_data.image.get_image())
var polygons = bitmap.opaque_to_polygons(Rect2(Vector2(0, 0), bitmap.get_size()),4.0) #bitmap.get_size()
var polygons = bitmap.opaque_to_polygons(Rect2(Vector2(), bitmap.get_size()), 4.0)
var b = false
for polygon in polygons:
@ -133,11 +61,10 @@ func _ready():
grabArea.add_child(outline)
size = imageData.get_size()
grabArea.position = size*-0.5
sprite.offset = offset
grabArea.position = (size*-0.5) + offset
grabArea.position = (size * -0.5) + offset
changeFrames()
setZIndex()
@ -207,7 +134,7 @@ func replaceSprite(pathNew):
sprite.offset = offset
grabArea.position = (size*-0.5) + offset
grabArea.position = (size * -0.5) + offset
if !b:
remakePolygon()
@ -215,7 +142,6 @@ func replaceSprite(pathNew):
func _process(delta):
tick += 1
if Global.heldSprite == self:
grabArea.visible = true
originSprite.visible = true
@ -232,21 +158,17 @@ func _process(delta):
var length = (glob.y - dragger.global_position.y)
rotationalDrag(length,delta)
stretch(length,delta)
if grabDelay > 0:
grabDelay -= 1
rotationalDrag(length, delta)
stretch(length, delta)
talkBlink()
animation()
func animation():
var speed = max(float(animSpeed),Engine.max_fps*6.0)
var speed = max(float(animSpeed), Engine.max_fps * 6.0)
if animSpeed > 0 and frames > 1:
if Global.animationTick % int((speed)/float(animSpeed)) == 0:
if Global.animationTick % int((speed) / float(animSpeed)) == 0:
if sprite.frame == frames - 1:
sprite.frame = 0
else:
@ -259,9 +181,9 @@ func setZIndex():
func talkBlink():
var faded = 0.2 * int(Global.main.editMode)
var value = (showOnTalk + (showOnBlink*3)) + (int(Global.speaking)*10) + (int(Global.blink)*20)
var yes = [0,10,20,30,1,21,12,32,3,13,4,15,26,36,27,38].has(int(value))
sprite.self_modulate.a = max(int(yes),faded)
var value = (showOnTalk + (showOnBlink * 3)) + (int(Global.speaking) * 10) + (int(Global.blink) * 20)
var yes = [0, 10, 20, 30, 1, 21, 12, 32, 3, 13, 4, 15, 26, 36, 27, 38].has(int(value))
sprite.self_modulate.a = max(int(yes), faded)
func delete():
queue_free()
@ -295,7 +217,7 @@ func moveSprite(dir):
multiplier = 1
position -= dir * multiplier
position = Vector2(int(position.x),int(position.y))
position = Vector2(int(position.x), int(position.y))
func moveOrigin(dir):
if dir != Vector2.ZERO:
@ -311,36 +233,36 @@ func moveOrigin(dir):
offset += dir * multiplier
position -= dir * multiplier
offset = Vector2(int(offset.x),int(offset.y))
offset = Vector2(int(offset.x), int(offset.y))
sprite.offset = offset
grabArea.position = (size*-0.5) + offset
grabArea.position = (size * -0.5) + offset
func drag(delta):
if dragSpeed == 0:
dragger.global_position = wob.global_position
else:
dragger.global_position = lerp(dragger.global_position,wob.global_position,1/dragSpeed)
dragger.global_position = lerp(dragger.global_position, wob.global_position, 1 / dragSpeed)
dragOrigin.global_position = dragger.global_position
func wobble():
wob.position.x = sin(tick*xFrq)*xAmp
wob.position.y = sin(tick*yFrq)*yAmp
wob.position.x = sin(tick * xFrq) * xAmp
wob.position.y = sin(tick * yFrq) * yAmp
func rotationalDrag(length,delta):
func rotationalDrag(length, delta):
var yvel = (length * rdragStr)
#Calculate Max angle
yvel = clamp(yvel,rLimitMin,rLimitMax)
yvel = clamp(yvel, rLimitMin, rLimitMax)
sprite.rotation = lerp_angle(sprite.rotation,deg_to_rad(yvel),0.25)
sprite.rotation = lerp_angle(sprite.rotation, deg_to_rad(yvel), 0.25)
func stretch(length,delta):
func stretch(length, delta):
var yvel = (length * stretchAmount * 0.01)
var target = Vector2(1.0-yvel,1.0+yvel)
var target = Vector2(1.0 - yvel, 1.0 + yvel)
sprite.scale = lerp(sprite.scale,target,0.5)
sprite.scale = lerp(sprite.scale, target, 0.5)
func changeCollision(enable):
grabArea.monitorable = enable
@ -357,18 +279,18 @@ func remakePolygon():
c.queue_free()
var collider = CollisionShape2D.new()
var shape = RectangleShape2D.new()
shape.size = Vector2(imageSize.y,imageSize.y)
shape.size = Vector2(imageSize.y, imageSize.y)
collider.shape = shape
collider.position = Vector2(imageSize.x,imageSize.y) * Vector2(0.5,0.5)
collider.position = Vector2(imageSize.x, imageSize.y) * Vector2(0.5, 0.5)
grabArea.add_child(collider)
var p = imageSize.y * 0.5
var outline = outlineScene.instantiate()
outline.add_point(Vector2(-p,-p))
outline.add_point(Vector2(p,-p))
outline.add_point(Vector2(p,p))
outline.add_point(Vector2(-p,p))
outline.add_point(Vector2(-p,-p))
outline.add_point(Vector2(-p, -p))
outline.add_point(Vector2(p, -p))
outline.add_point(Vector2(p, p))
outline.add_point(Vector2(-p, p))
outline.add_point(Vector2(-p, -p))
outline.position = collider.position
grabArea.add_child(outline)
@ -395,8 +317,8 @@ func getAllLinkedSprites():
linkedSprites.append(node)
return linkedSprites
func visToggle(keys):
if keys.has(toggle):
func visToggle(key: Key):
if key == toggle:
$WobbleOrigin/DragOrigin.visible = !$WobbleOrigin/DragOrigin.visible
func makeVis():

View file

@ -126,7 +126,7 @@ func _on_bounce_gravity_value_changed(value):
Global.pushUpdate("Bounce gravity value changed.")
func costumeButtonsPressed(label,id):
func costumeButtonsPressed(label: Label, id):
label.text = "AWAITING INPUT"
await Global.main.emptiedCapture
awaitingCostumeInput = id - 1

View file

@ -342,15 +342,14 @@ func _on_clip_linked_toggled(button_pressed):
func _on_delete_pressed():
Global.heldSprite.toggle = "null"
$VisToggle/setToggle/Label.text = "toggle: \"" + Global.heldSprite.toggle + "\""
Global.heldSprite.toggle = KEY_NONE
$VisToggle/setToggle/Label.text = "toggle: \"%s\"" % OS.get_keycode_string(Global.heldSprite.toggle)
Global.heldSprite.makeVis()
func _on_set_toggle_pressed():
$VisToggle/setToggle/Label.text = "toggle: AWAITING INPUT"
await Global.main.fatfuckingballs
await InputHandler.all_keys_released
var keys = await Global.main.spriteVisToggles
var key = keys[0]
var key = await InputHandler.key_pressed
Global.heldSprite.toggle = key
$VisToggle/setToggle/Label.text = "toggle: \"" + Global.heldSprite.toggle + "\""
$VisToggle/setToggle/Label.text = "toggle: \"%s\"" % OS.get_keycode_string(Global.heldSprite.toggle)