online multiplayer chess game (note server currently down)
customization of the game
bendn 2022-06-26
parent 3cefcd9 · commit 887de94
-rw-r--r--PGN/PGN.gd5
-rw-r--r--networking/PacketHandler.gd23
-rw-r--r--project.godot15
-rw-r--r--ui/Status.gd2
-rw-r--r--ui/menus/StartMenu.tscn2
-rw-r--r--ui/menus/account/Account.gd2
-rw-r--r--ui/menus/account/Account.tscn4
-rw-r--r--ui/menus/account/InfoLabel.gd11
-rw-r--r--ui/menus/lobby/Disclaimer.gd (renamed from ui/menus/Disclaimer.gd)0
-rw-r--r--ui/menus/lobby/GameConfig.gd36
-rw-r--r--ui/menus/lobby/GameConfig.tscn100
-rw-r--r--ui/menus/lobby/Lobby.gd (renamed from ui/menus/Lobby.gd)10
-rw-r--r--ui/menus/lobby/Lobby.tscn (renamed from ui/menus/Lobby.tscn)28
-rw-r--r--ui/menus/lobby/PGNEntry.gd19
-rw-r--r--ui/menus/sidebarright/SidebarRight.tscn6
-rw-r--r--ui/menus/sidebarright/sandisplay/SanDisplay.tscn12
-rw-r--r--ui/slider_button/SliderButton.gd36
-rw-r--r--ui/slider_button/SliderButton.tscn30
-rw-r--r--ui/slider_button/slider.tres32
-rw-r--r--ui/slider_button/slider_background.styleboxbin0 -> 410 bytes
-rw-r--r--ui/theme/main.themebin1915 -> 1509 bytes
21 files changed, 337 insertions, 36 deletions
diff --git a/PGN/PGN.gd b/PGN/PGN.gd
index d6ba721..8a8eaf6 100644
--- a/PGN/PGN.gd
+++ b/PGN/PGN.gd
@@ -2,7 +2,7 @@ extends Node
class_name PGN
-func parse(pgn: String, tags := true) -> Dictionary:
+func parse(pgn: String, tags := true):
# put tags into a dictionary,
# and the moves into a array
@@ -33,8 +33,7 @@ func parse(pgn: String, tags := true) -> Dictionary:
headers[cap[1]] = cap[2]
else:
# invalid headers
- push_error("invalid headers")
- return {}
+ return null
else:
break
var movetext := PoolStringArray()
diff --git a/networking/PacketHandler.gd b/networking/PacketHandler.gd
index ea69b50..18a4360 100644
--- a/networking/PacketHandler.gd
+++ b/networking/PacketHandler.gd
@@ -129,13 +129,19 @@ func _connection_error() -> void:
func join_result(accepted) -> void:
if handle_result(accepted, "Joined!"):
- yield(get_tree(), "idle_frame")
- if Globals.team == Globals.BLACK:
- Globals.grid.flip_board()
+ flip_if_black()
+
+
+func flip_if_black():
+ yield(get_tree(), "idle_frame")
+ if Globals.team == Globals.BLACK:
+ Globals.grid.flip_board()
func host_result(accepted) -> void:
- set_hosting(handle_result(accepted, "Hosted!"))
+ if handle_result(accepted, "Hosted!"):
+ set_hosting(true)
+ flip_if_black()
func handle_result(accepted, resultstring: String) -> bool:
@@ -149,6 +155,7 @@ func handle_result(accepted, resultstring: String) -> bool:
func go_back(error: String, isok: bool) -> void:
+ stopgame(game_code)
Globals.reset_vars()
if has_node("/root/Game"):
$"/root/Game".queue_free()
@@ -186,8 +193,12 @@ func join_game(game: String = game_code) -> void:
send_gamecode_packet(SaveLoad.get_public_info(), HEADERS.joinrequest, game)
-func host_game(game: String = game_code) -> void:
- send_gamecode_packet(SaveLoad.get_public_info(), HEADERS.hostrequest, game)
+func host_game(game: String = game_code, white := true, moves_array: PoolStringArray = []) -> void:
+ send_gamecode_packet(
+ Utils.append_dict(SaveLoad.get_public_info(), {team = white, moves = moves_array}),
+ HEADERS.hostrequest,
+ game
+ )
func spectate(game: String = game_code) -> void:
diff --git a/project.godot b/project.godot
index 5ac0b22..aeb90af 100644
--- a/project.godot
+++ b/project.godot
@@ -104,6 +104,11 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://ui/colorpicker/HueSlider.gd"
}, {
+"base": "Label",
+"class": "InfoLabel",
+"language": "GDScript",
+"path": "res://ui/menus/account/InfoLabel.gd"
+}, {
"base": "KeyUtils",
"class": "Key",
"language": "GDScript",
@@ -127,7 +132,7 @@ _global_script_classes=[ {
"base": "Control",
"class": "Lobby",
"language": "GDScript",
-"path": "res://ui/menus/Lobby.gd"
+"path": "res://ui/menus/lobby/Lobby.gd"
}, {
"base": "PanelContainer",
"class": "MessageList",
@@ -199,6 +204,11 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://saveload.gd"
}, {
+"base": "Control",
+"class": "SliderButton",
+"language": "GDScript",
+"path": "res://ui/slider_button/SliderButton.gd"
+}, {
"base": "KeyUtils",
"class": "SpecialKey",
"language": "GDScript",
@@ -249,6 +259,7 @@ _global_script_class_icons={
"GridMenu": "",
"GridMenuButton": "",
"HueSlider": "",
+"InfoLabel": "",
"Key": "",
"KeyUtils": "",
"King": "res://assets/pieces/california/wK.png",
@@ -268,6 +279,7 @@ _global_script_class_icons={
"Rook": "res://assets/pieces/california/wR.png",
"SanParser": "",
"SaveLoader": "",
+"SliderButton": "",
"SpecialKey": "",
"StatusLabel": "",
"TextEditor": "",
@@ -323,6 +335,7 @@ enabled=PoolStringArray( )
[gui]
theme/custom="res://ui/theme/main.theme"
+theme/custom_font="res://ui/ubuntu-bold.tres"
[importer_defaults]
diff --git a/ui/Status.gd b/ui/Status.gd
index 03f8db1..99c6697 100644
--- a/ui/Status.gd
+++ b/ui/Status.gd
@@ -3,9 +3,7 @@ class_name StatusLabel
func set_text(newtext: String, time := 7) -> void:
- show()
text = newtext
if time != 0:
yield(get_tree().create_timer(time), "timeout")
text = ""
- hide()
diff --git a/ui/menus/StartMenu.tscn b/ui/menus/StartMenu.tscn
index f720f72..0c14f81 100644
--- a/ui/menus/StartMenu.tscn
+++ b/ui/menus/StartMenu.tscn
@@ -4,7 +4,7 @@
[ext_resource path="res://ui/menus/settings/Settings.tscn" type="PackedScene" id=2]
[ext_resource path="res://assets/ui/ubuntu/ubuntu-bold.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://ui/theme/main.theme" type="Theme" id=4]
-[ext_resource path="res://ui/menus/Lobby.tscn" type="PackedScene" id=5]
+[ext_resource path="res://ui/menus/lobby/Lobby.tscn" type="PackedScene" id=5]
[ext_resource path="res://test.gd" type="Script" id=6]
[ext_resource path="res://ui/menus/StartMenu.gd" type="Script" id=7]
[ext_resource path="res://PGN/test_pgns.tscn" type="PackedScene" id=8]
diff --git a/ui/menus/account/Account.gd b/ui/menus/account/Account.gd
index 29ce00e..c1bc49e 100644
--- a/ui/menus/account/Account.gd
+++ b/ui/menus/account/Account.gd
@@ -3,7 +3,7 @@ extends Control
onready var flags: PoolStringArray = ["rainbow"]
onready var flagchoice: GridMenuButton = $choose/signup/flag
onready var data: Dictionary = SaveLoad.get_data("id")
-onready var status: StatusLabel = $H/InfoLabel # not a StatusLabel
+onready var status: InfoLabel = $H/InfoLabel # not a StatusLabel
onready var loading = $LoadingAnimation
onready var tabs := {
diff --git a/ui/menus/account/Account.tscn b/ui/menus/account/Account.tscn
index a51d609..c5e1c32 100644
--- a/ui/menus/account/Account.tscn
+++ b/ui/menus/account/Account.tscn
@@ -2,7 +2,7 @@
[ext_resource path="res://ui/gridmenu/GridMenuButton.tscn" type="PackedScene" id=1]
[ext_resource path="res://assets/ui/whitespace.png" type="Texture" id=2]
-[ext_resource path="res://ui/Status.gd" type="Script" id=4]
+[ext_resource path="res://ui/menus/account/InfoLabel.gd" type="Script" id=3]
[ext_resource path="res://ui/menus/account/usernamepass.tscn" type="PackedScene" id=5]
[ext_resource path="res://ui/theme/main.theme" type="Theme" id=6]
[ext_resource path="res://ui/animations/thehalo.tres" type="Material" id=7]
@@ -22,7 +22,7 @@ visible = false
margin_right = 1422.0
margin_bottom = 46.0
size_flags_horizontal = 3
-script = ExtResource( 4 )
+script = ExtResource( 3 )
[node name="LogOut" type="Button" parent="H"]
visible = false
diff --git a/ui/menus/account/InfoLabel.gd b/ui/menus/account/InfoLabel.gd
new file mode 100644
index 0000000..660040c
--- /dev/null
+++ b/ui/menus/account/InfoLabel.gd
@@ -0,0 +1,11 @@
+extends Label
+class_name InfoLabel
+
+
+func set_text(new_text: String, time := 5) -> void:
+ show()
+ text = new_text
+ if time != 0:
+ yield(get_tree().create_timer(time), "timeout")
+ text = ""
+ hide()
diff --git a/ui/menus/Disclaimer.gd b/ui/menus/lobby/Disclaimer.gd
index 385d4e0..385d4e0 100644
--- a/ui/menus/Disclaimer.gd
+++ b/ui/menus/lobby/Disclaimer.gd
diff --git a/ui/menus/lobby/GameConfig.gd b/ui/menus/lobby/GameConfig.gd
new file mode 100644
index 0000000..da0cd67
--- /dev/null
+++ b/ui/menus/lobby/GameConfig.gd
@@ -0,0 +1,36 @@
+extends TabContainer
+
+var moves := PoolStringArray()
+var white := true setget set_white
+var lobby: Lobby
+
+
+func _ready():
+ find_node("SliderButton").connect("toggled", self, "set_white")
+
+
+func set_white(new_white: bool) -> void:
+ white = new_white
+
+
+func _on_Continue_pressed():
+ PacketHandler.host_game(PacketHandler.game_code, white, moves)
+ reset()
+
+
+func open(_lobby: Lobby):
+ show()
+ lobby = _lobby
+
+
+func _on_Stop_pressed():
+ reset()
+
+
+func reset():
+ lobby.set_buttons(true)
+ hide()
+
+
+func _on_pgn_selected(_moves: PoolStringArray):
+ moves = _moves
diff --git a/ui/menus/lobby/GameConfig.tscn b/ui/menus/lobby/GameConfig.tscn
new file mode 100644
index 0000000..1956929
--- /dev/null
+++ b/ui/menus/lobby/GameConfig.tscn
@@ -0,0 +1,100 @@
+[gd_scene load_steps=7 format=2]
+
+[ext_resource path="res://ui/theme/main.theme" type="Theme" id=1]
+[ext_resource path="res://ui/slider_button/SliderButton.tscn" type="PackedScene" id=2]
+[ext_resource path="res://assets/pieces/cburnett/wK.png" type="Texture" id=3]
+[ext_resource path="res://assets/pieces/cburnett/bK.png" type="Texture" id=4]
+[ext_resource path="res://ui/menus/lobby/GameConfig.gd" type="Script" id=5]
+[ext_resource path="res://ui/menus/lobby/PGNEntry.gd" type="Script" id=6]
+
+[node name="GameConfig" type="TabContainer"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+theme = ExtResource( 1 )
+script = ExtResource( 5 )
+
+[node name="General" type="VBoxContainer" parent="."]
+visible = false
+anchor_right = 1.0
+anchor_bottom = 1.0
+margin_left = 30.0
+margin_top = 86.0
+margin_right = -30.0
+margin_bottom = -30.0
+
+[node name="H" type="HBoxContainer" parent="General"]
+margin_right = 1362.0
+margin_bottom = 100.0
+custom_constants/separation = 0
+alignment = 1
+
+[node name="Black" type="TextureRect" parent="General/H"]
+margin_left = 481.0
+margin_right = 581.0
+margin_bottom = 100.0
+rect_min_size = Vector2( 100, 100 )
+texture = ExtResource( 4 )
+expand = true
+stretch_mode = 6
+
+[node name="SliderButton" parent="General/H" instance=ExtResource( 2 )]
+anchor_left = 0.0
+anchor_top = 0.0
+anchor_right = 0.0
+anchor_bottom = 0.0
+margin_left = 581.0
+margin_top = 25.0
+margin_right = 781.0
+margin_bottom = 75.0
+rect_min_size = Vector2( 200, 50 )
+size_flags_vertical = 4
+on_color = Color( 1, 1, 1, 1 )
+off_color = Color( 0, 0, 0, 1 )
+
+[node name="White" type="TextureRect" parent="General/H"]
+margin_left = 781.0
+margin_right = 881.0
+margin_bottom = 100.0
+rect_min_size = Vector2( 100, 100 )
+texture = ExtResource( 3 )
+expand = true
+stretch_mode = 6
+
+[node name="H2" type="HBoxContainer" parent="General"]
+margin_top = 115.0
+margin_right = 1362.0
+margin_bottom = 217.0
+alignment = 1
+
+[node name="Stop" type="Button" parent="General/H2"]
+margin_left = 450.0
+margin_right = 621.0
+margin_bottom = 102.0
+size_flags_horizontal = 4
+text = "exit"
+
+[node name="Continue" type="Button" parent="General/H2"]
+margin_left = 636.0
+margin_right = 911.0
+margin_bottom = 102.0
+size_flags_horizontal = 4
+text = "continue "
+
+[node name="Advanced" type="VBoxContainer" parent="."]
+anchor_right = 1.0
+anchor_bottom = 1.0
+margin_left = 30.0
+margin_top = 86.0
+margin_right = -30.0
+margin_bottom = -30.0
+
+[node name="Pgn" type="LineEdit" parent="Advanced"]
+margin_right = 1362.0
+margin_bottom = 102.0
+placeholder_text = "1. e4"
+script = ExtResource( 6 )
+
+[connection signal="pressed" from="General/H2/Stop" to="." method="_on_Stop_pressed"]
+[connection signal="pressed" from="General/H2/Continue" to="." method="_on_Continue_pressed"]
+[connection signal="pgn_selected" from="Advanced/Pgn" to="." method="_on_pgn_selected"]
+[connection signal="text_entered" from="Advanced/Pgn" to="Advanced/Pgn" method="_text_entered"]
diff --git a/ui/menus/Lobby.gd b/ui/menus/lobby/Lobby.gd
index 1250bc5..3f6088c 100644
--- a/ui/menus/Lobby.gd
+++ b/ui/menus/lobby/Lobby.gd
@@ -57,21 +57,25 @@ func _on_join_pressed() -> void:
func _on_HostButton_pressed() -> void:
if validate_text():
set_buttons(false)
- PacketHandler.host_game()
+ $Center/VBox/GameConfig.open(self)
else:
set_status("Invalid address", false)
func validate_text(text := address.get_text()) -> String:
var pos := address.caret_position
- text = text.strip_edges()
- text = text.replace(" ", "_")
+ text = clean_text(text)
address.text = text
address.caret_position = pos
PacketHandler.game_code = text
return text
+func clean_text(text: String) -> String:
+ text = text.strip_edges()
+ return text.replace(" ", "_")
+
+
func _on_Address_text_entered(new_text: String) -> void:
validate_text(new_text)
diff --git a/ui/menus/Lobby.tscn b/ui/menus/lobby/Lobby.tscn
index d798bb2..a9beb3d 100644
--- a/ui/menus/Lobby.tscn
+++ b/ui/menus/lobby/Lobby.tscn
@@ -1,9 +1,10 @@
-[gd_scene load_steps=5 format=2]
+[gd_scene load_steps=6 format=2]
[ext_resource path="res://ui/theme/main.theme" type="Theme" id=1]
-[ext_resource path="res://ui/menus/Lobby.gd" type="Script" id=2]
-[ext_resource path="res://ui/menus/Disclaimer.gd" type="Script" id=3]
+[ext_resource path="res://ui/menus/lobby/Lobby.gd" type="Script" id=2]
+[ext_resource path="res://ui/menus/lobby/Disclaimer.gd" type="Script" id=3]
[ext_resource path="res://ui/ubuntu-bold-small.tres" type="DynamicFont" id=4]
+[ext_resource path="res://ui/menus/lobby/GameConfig.tscn" type="PackedScene" id=5]
[node name="Lobby" type="CenterContainer"]
anchor_right = 1.0
@@ -21,10 +22,16 @@ margin_bottom = 509.0
margin_right = 600.0
margin_bottom = 219.0
+[node name="GameConfig" parent="Center/VBox" instance=ExtResource( 5 )]
+visible = false
+anchor_right = 0.0
+anchor_bottom = 0.0
+margin_right = 727.0
+margin_bottom = 450.0
+
[node name="stophost" type="Button" parent="Center/VBox"]
visible = false
-margin_left = 152.0
-margin_right = 448.0
+margin_right = 296.0
margin_bottom = 102.0
focus_mode = 0
size_flags_horizontal = 4
@@ -34,7 +41,7 @@ text = "stop hosting"
margin_right = 600.0
margin_bottom = 102.0
rect_min_size = Vector2( 600, 0 )
-hint_tooltip = "place game code here"
+hint_tooltip = "people will be able to join this gamecode"
focus_mode = 1
text = "game_code"
align = 1
@@ -59,7 +66,7 @@ text = "spectate"
[node name="JoinButton" type="Button" parent="Center/VBox/buttons"]
margin_left = 238.0
-margin_right = 411.0
+margin_right = 406.0
margin_bottom = 102.0
rect_min_size = Vector2( 150, 0 )
hint_tooltip = "join the game"
@@ -69,14 +76,14 @@ disabled = true
text = "join"
[node name="HostButton" type="Button" parent="Center/VBox/buttons"]
-margin_left = 426.0
+margin_left = 421.0
margin_right = 600.0
margin_bottom = 102.0
-hint_tooltip = "host the game"
+hint_tooltip = "create a game"
focus_mode = 0
size_flags_horizontal = 7
disabled = true
-text = "host"
+text = "create"
[node name="StatusOK" type="Label" parent="Center/VBox"]
visible = false
@@ -116,7 +123,6 @@ margin_right = -46.0
color = Color( 0.588235, 0.560784, 0.309804, 1 )
[connection signal="pressed" from="Center/VBox/stophost" to="." method="_on_stophost_pressed"]
-[connection signal="text_entered" from="Center/VBox/Address" to="." method="_on_Address_text_entered"]
[connection signal="pressed" from="Center/VBox/buttons/SpectateButton" to="." method="_on_spectate_pressed"]
[connection signal="pressed" from="Center/VBox/buttons/JoinButton" to="." method="_on_join_pressed"]
[connection signal="pressed" from="Center/VBox/buttons/HostButton" to="." method="_on_HostButton_pressed"]
diff --git a/ui/menus/lobby/PGNEntry.gd b/ui/menus/lobby/PGNEntry.gd
new file mode 100644
index 0000000..5f76aa2
--- /dev/null
+++ b/ui/menus/lobby/PGNEntry.gd
@@ -0,0 +1,19 @@
+extends LineEdit
+
+signal pgn_selected(m_array)
+
+
+func _text_entered(new_text: String):
+ var status = validate_pgn(new_text)
+ if status:
+ emit_signal("pgn_selected", status)
+ else:
+ text = "invalid pgn"
+
+
+func validate_pgn(p: String):
+ var parsed = Pgn.parse(p)
+ if parsed == null:
+ return false
+ else:
+ return parsed.moves # TODO: simulate the pgn and such nonsense
diff --git a/ui/menus/sidebarright/SidebarRight.tscn b/ui/menus/sidebarright/SidebarRight.tscn
index ad25a5c..37e35ea 100644
--- a/ui/menus/sidebarright/SidebarRight.tscn
+++ b/ui/menus/sidebarright/SidebarRight.tscn
@@ -99,7 +99,7 @@ focus_mode = 0
mouse_default_cursor_shape = 2
size_flags_horizontal = 3
custom_fonts/font = ExtResource( 9 )
-text = ""
+text = "ﮨ"
script = ExtResource( 19 )
[node name="DrawButton" type="Button" parent="V/buttonbarholder/buttonbar"]
@@ -124,7 +124,7 @@ hint_tooltip = "resign"
focus_mode = 0
mouse_default_cursor_shape = 2
size_flags_horizontal = 3
-text = ""
+text = ""
script = ExtResource( 2 )
confirm_text = "Resign?"
@@ -137,7 +137,7 @@ hint_tooltip = "request a undo"
focus_mode = 0
mouse_default_cursor_shape = 2
size_flags_horizontal = 3
-text = "社"
+text = ""
script = ExtResource( 18 )
confirm_text = "Your opponent requests a undo"
status = NodePath("../../../Status")
diff --git a/ui/menus/sidebarright/sandisplay/SanDisplay.tscn b/ui/menus/sidebarright/sandisplay/SanDisplay.tscn
index 80b9b1c..1a28bdf 100644
--- a/ui/menus/sidebarright/sandisplay/SanDisplay.tscn
+++ b/ui/menus/sidebarright/sandisplay/SanDisplay.tscn
@@ -1,20 +1,26 @@
-[gd_scene load_steps=3 format=2]
+[gd_scene load_steps=4 format=2]
+[ext_resource path="res://ui/theme/main.theme" type="Theme" id=1]
[ext_resource path="res://ui/menus/sidebarright/sandisplay/SanDisplay.gd" type="Script" id=8]
[ext_resource path="res://ui/menus/sidebarright/sandisplay/Base.tscn" type="PackedScene" id=10]
[node name="SanDisplay" type="PanelContainer"]
anchor_right = 1.0
anchor_bottom = 1.0
-mouse_filter = 2
+hint_tooltip = "click to copy pgn"
+theme = ExtResource( 1 )
script = ExtResource( 8 )
Base = ExtResource( 10 )
[node name="Scroller" type="ScrollContainer" parent="."]
margin_right = 1422.0
margin_bottom = 800.0
-hint_tooltip = "click to copy pgn"
+mouse_filter = 2
scroll_horizontal_enabled = false
+__meta__ = {
+"_edit_group_": true,
+"_edit_lock_": true
+}
[node name="sanholder" type="VBoxContainer" parent="Scroller"]
margin_right = 1422.0
diff --git a/ui/slider_button/SliderButton.gd b/ui/slider_button/SliderButton.gd
new file mode 100644
index 0000000..f043a60
--- /dev/null
+++ b/ui/slider_button/SliderButton.gd
@@ -0,0 +1,36 @@
+extends Control
+class_name SliderButton
+
+signal toggled(enabled)
+
+export(bool) var enabled = true setget set_enabled # true is to the right
+export(Color) var on_color := Color.green
+export(Color) var off_color := Color.red
+var pos: float = 1 # 0-1
+
+
+func set_enabled(new_enabled: bool) -> void:
+ enabled = new_enabled
+ emit_signal("toggled", enabled)
+ set_process(true)
+
+
+func _gui_input(event):
+ if event is InputEventMouseButton and event.pressed:
+ set_enabled(!enabled)
+
+
+func _draw():
+ var x: float = lerp(rect_size.y / 2, rect_size.x - rect_size.y / 2, pos)
+ var c: Color = lerp(off_color, on_color, pos)
+ draw_circle(Vector2(x, rect_size.y / 2), (rect_size.y / 2) + .3, c)
+
+
+func _process(_delta):
+ update()
+ if enabled and pos <= 1:
+ pos = lerp(pos, 1, 0.1)
+ elif !enabled and pos >= 0:
+ pos = lerp(pos, 0, 0.1)
+ if is_equal_approx(pos, 1) or is_equal_approx(pos, 0):
+ set_process(false)
diff --git a/ui/slider_button/SliderButton.tscn b/ui/slider_button/SliderButton.tscn
new file mode 100644
index 0000000..06f44e0
--- /dev/null
+++ b/ui/slider_button/SliderButton.tscn
@@ -0,0 +1,30 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://ui/slider_button/slider.tres" type="Theme" id=1]
+[ext_resource path="res://ui/slider_button/SliderButton.gd" type="Script" id=2]
+[ext_resource path="res://ui/slider_button/slider_background.stylebox" type="StyleBox" id=3]
+
+[node name="SliderButton" type="Control"]
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+margin_left = -135.0
+margin_top = -8.0
+margin_right = -35.0
+margin_bottom = 42.0
+rect_min_size = Vector2( 100, 50 )
+theme = ExtResource( 1 )
+script = ExtResource( 2 )
+on_color = Color( 0.55, 1, 0.55, 1 )
+off_color = Color( 1, 0.55, 0.55, 1 )
+
+[node name="Panel" type="Panel" parent="."]
+show_behind_parent = true
+anchor_right = 1.0
+anchor_bottom = 1.0
+mouse_filter = 2
+custom_styles/panel = ExtResource( 3 )
+__meta__ = {
+"_edit_lock_": true
+}
diff --git a/ui/slider_button/slider.tres b/ui/slider_button/slider.tres
new file mode 100644
index 0000000..5db8557
--- /dev/null
+++ b/ui/slider_button/slider.tres
@@ -0,0 +1,32 @@
+[gd_resource type="Theme" load_steps=4 format=2]
+
+[ext_resource path="res://assets/ui/whitespace.png" type="Texture" id=1]
+
+[sub_resource type="StyleBoxFlat" id=23]
+bg_color = Color( 0.588235, 0.360784, 0.360784, 1 )
+corner_radius_top_left = 10
+corner_radius_top_right = 10
+corner_radius_bottom_right = 10
+corner_radius_bottom_left = 10
+expand_margin_left = 10.0
+expand_margin_right = 10.0
+expand_margin_top = 10.0
+expand_margin_bottom = 10.0
+
+[sub_resource type="StyleBoxFlat" id=22]
+bg_color = Color( 0.14902, 0.14902, 0.14902, 1 )
+corner_radius_top_left = 10
+corner_radius_top_right = 10
+corner_radius_bottom_right = 10
+corner_radius_bottom_left = 10
+corner_detail = 10
+expand_margin_left = 10.0
+expand_margin_right = 10.0
+expand_margin_top = 10.0
+expand_margin_bottom = 10.0
+
+[resource]
+HSlider/icons/grabber = ExtResource( 1 )
+HSlider/styles/grabber_area = SubResource( 23 )
+HSlider/styles/grabber_area_highlight = SubResource( 23 )
+HSlider/styles/slider = SubResource( 22 )
diff --git a/ui/slider_button/slider_background.stylebox b/ui/slider_button/slider_background.stylebox
new file mode 100644
index 0000000..90d9dba
--- /dev/null
+++ b/ui/slider_button/slider_background.stylebox
Binary files differ
diff --git a/ui/theme/main.theme b/ui/theme/main.theme
index 6c5984f..bc17bdd 100644
--- a/ui/theme/main.theme
+++ b/ui/theme/main.theme
Binary files differ