Added OBSProc information, and VTuberProc information, for later when testing if these programs are running, and maybe later implementing killing of these programs.
266 lines
10 KiB
GDScript
266 lines
10 KiB
GDScript
extends GDSubMenuButton
|
||
class_name GDFloatingMenu
|
||
|
||
const COL_ON := Color.LIGHT_GREEN
|
||
const COL_OFF := Color.LIGHT_SALMON
|
||
|
||
const SETTINGS_PANEL = preload("res://UI/settings_panel.tscn")
|
||
const SCRIPT_EDITOR = preload("res://UI/Controls/script_editor.tscn")
|
||
|
||
#region Alerts (Testing)
|
||
const FOLLOW_ALERT = preload("res://UI/Alerts/follow_alert.tscn")
|
||
const CHEER_ALERT = preload("res://UI/Alerts/cheer_alert.tscn")
|
||
const RAID_ALERT = preload("res://UI/Alerts/raid_alert.tscn")
|
||
const SUBSCRIBER_ALERT = preload("res://UI/Alerts/subscriber_alert.tscn")
|
||
var _impl_alerts: Array = [
|
||
FOLLOW_ALERT,
|
||
CHEER_ALERT,
|
||
RAID_ALERT,
|
||
SUBSCRIBER_ALERT,
|
||
]
|
||
|
||
const RANDOM_NAMES := [
|
||
"Voylin",
|
||
"meneldal",
|
||
"Pengo",
|
||
"Adam",
|
||
"Yagich",
|
||
"Falinere",
|
||
"Eroaxee",
|
||
"wolbee",
|
||
"JeSuisEmma",
|
||
"Temptic404",
|
||
"RobitussinMD",
|
||
"spimort",
|
||
"FuzzyDemonBunny",
|
||
"OdatNurd",
|
||
]
|
||
|
||
const RANDOM_MESSAGES := [
|
||
"Android was an easy fix, accidentally applied vpx to everything in Scons, Windows need an AUR package, and the arm builds are complaining about not finding vpx (probably no static build available). So not too difficult to fix luckily. But for arm I might need to build vpx myself for those builds, and whilst I'm at it I can implement support for Android as I need to clone and build it anyway for the arm builds ... Well ... that will be for later as I'll probably get stuck on this for the entire day without finishing what I started working on before XD",
|
||
"awesome, im going to run the project update tool with 4.6 and PR that so that we don't have 4.6 upgraded files in future PRs",
|
||
"I can do any time during the day or night, I can even wake up in the middle of the night if I need to",
|
||
"done 🙂 ready when you are",
|
||
"you probably been busy lately, but just curious how progress was coming along on the new launcher?",
|
||
"A version or two ago they moved the strip properties from the sequencer timeline (in blue) to the generic \"properties\" panel (in red) thats used everywhere else.",
|
||
"thanks, I realised my models were all subdivided triangle riddled messes!",
|
||
"I still don't know how to make a good short - but I can't get over the background music I was able to generate for this one. It just cracks me up. ",
|
||
"i think my favourite thing about streaming game dev is just how much of us are just sitting there guessing???",
|
||
"148 TEAM MEMBERS AND NOBODY TO WATCH ON A SUNDAY EVENING flips table",
|
||
"i'd like to formally apologize to @iRad for how i treated him in my really weird dream last night. we entered a game jam together and i spent the entire time talking to friends. he really carried me.",
|
||
"Sometimes that’s all it takes, just one person believing you’ll succeed. Or sometimes a whole bunch of people, who mysteriously growl low if you try and leave the chair. And in no way shape or form require you to send eye blinking messages for outside help, nor throw digital snacks in one direction while sneaking out the other. ",
|
||
"That's the reason I come into the communities, to be supportive, positive, try to help when possible... because game dev is already hard enough. Sometimes all you need is just that one little boost on a rough day to keep you going and just offset the grind enough to let you feel okay again. That and giving friendly pushes to devs to get that steam page done, or that demo knocked out, or just to push forward progress.",
|
||
"Born to late to explore Earth, born to early to explore the universe",
|
||
]
|
||
#endregion
|
||
|
||
# Indicators
|
||
@onready var indicators: Control = %indicators
|
||
@onready var ind_stream: TextureRect = %ind_stream
|
||
@onready var ind_mic: TextureRect = %ind_mic
|
||
@onready var ind_pixelate: TextureRect = %ind_pixelate
|
||
@onready var ind_browser: TextureRect = %ind_browser
|
||
# Buttons
|
||
@onready var btn_obs: GDSubMenuButton = %btn_obs
|
||
@onready var btn_run_obs: GDSubMenuButton = %btn_run_obs
|
||
@onready var btn_step_away: GDSubMenuButton = %btn_step_away
|
||
@onready var btn_tuber: GDSubMenuButton = %btn_tuber
|
||
@onready var btn_camera: GDSubMenuButton = %btn_camera
|
||
@onready var btn_chat: GDSubMenuButton = %btn_chat
|
||
@onready var btn_script_editor: GDSubMenuButton = %btn_script_editor
|
||
@onready var btn_user_list: GDSubMenuButton = %btn_user_list
|
||
@onready var btn_settings: GDSubMenuButton = %btn_settings
|
||
@onready var btn_end: GDSubMenuButton = %btn_end
|
||
|
||
var is_anchored := true
|
||
var anchored_position: Vector2
|
||
|
||
var _set_win: Window
|
||
var _edit_win: Window
|
||
var _obs_proc: ProcessTree.ProcessInfo = null
|
||
var _vtuber_proc: ProcessTree.ProcessInfo = null
|
||
var _vtuber_sid: int
|
||
var _camera_sid: int
|
||
|
||
func _ready() -> void:
|
||
ObsManager.obs_ready.connect(_handle_obs_connect)
|
||
|
||
func _handle_obs_connect() -> void:
|
||
_vtuber_sid = await ObsManager.get_scene_item_id("~Avatar", "~VTuber")
|
||
_camera_sid = await ObsManager.get_scene_item_id("~Avatar", "~WebCam")
|
||
|
||
func start(_main_menu_button: GDSubMenuButton = null) -> void:
|
||
anchored_position = position
|
||
var _parent: Control = get_parent()
|
||
_parent.resized.connect(func(): calculate_anchored_pos(); is_anchored = false)
|
||
generate_panels_buttons()
|
||
super(self)
|
||
start_indicators()
|
||
_connect_signals()
|
||
|
||
func start_indicators() -> void:
|
||
var tot = indicators.get_child_count()
|
||
for i in tot:
|
||
var ind: TextureRect = indicators.get_child(i)
|
||
ind.show()
|
||
ind.position = (size/2 - ind.size/2)
|
||
ind.position += Vector2.from_angle(TAU*i/tot + PI/2) * (size.x/2 - ind.size.x/2)
|
||
|
||
func generate_panels_buttons() -> void:
|
||
# TODO: Generate Panels?
|
||
pass
|
||
|
||
func _process(d: float) -> void:
|
||
super(d)
|
||
if not is_anchored and not is_dragged:
|
||
position = position.lerp(anchored_position, d*10)
|
||
if position.distance_squared_to(anchored_position) < 1:
|
||
position = anchored_position
|
||
is_anchored = true
|
||
|
||
func _on_gui_input(event: InputEvent) -> void:
|
||
super(event)
|
||
if event is InputEventMouseButton:
|
||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||
if not event.is_pressed():
|
||
is_anchored = false
|
||
calculate_anchored_pos()
|
||
if event is InputEventMouseMotion and is_mouse_click_down:
|
||
if is_open:
|
||
expand_menu(false)
|
||
|
||
func calculate_anchored_pos() -> void:
|
||
var m_pos := global_position + size/2.0
|
||
var w_size := get_window().size / get_tree().root.content_scale_factor
|
||
|
||
if min(m_pos.x, abs(w_size.x - m_pos.x)) < min(m_pos.y, abs(w_size.y - m_pos.y)):
|
||
closest_edge = Edge.LEFT if m_pos.x < abs(w_size.x - m_pos.x) else Edge.RIGHT
|
||
else:
|
||
closest_edge = Edge.UP if m_pos.y < abs(w_size.y - m_pos.y) else Edge.BOT
|
||
|
||
match closest_edge:
|
||
Edge.UP:
|
||
anchored_position = Vector2(position.x, 0)
|
||
parent_dir = Vector2.DOWN
|
||
Edge.RIGHT:
|
||
anchored_position = Vector2(w_size.x - size.x, position.y)
|
||
parent_dir = Vector2.LEFT
|
||
Edge.BOT:
|
||
anchored_position = Vector2(position.x, w_size.y - size.y)
|
||
parent_dir = Vector2.UP
|
||
Edge.LEFT:
|
||
anchored_position = Vector2(0, position.y)
|
||
parent_dir = Vector2.RIGHT
|
||
|
||
anchored_position = anchored_position.clamp(Vector2(), Vector2(w_size)-size)
|
||
|
||
#region Hnadle Button Functions
|
||
func _connect_signals() -> void:
|
||
btn_end.properly_pressed.connect(func(): get_tree().quit())
|
||
btn_settings.properly_pressed.connect(_handle_settings)
|
||
btn_script_editor.properly_pressed.connect(_handle_script_editor)
|
||
btn_run_obs.properly_pressed.connect(_handle_run_obs)
|
||
btn_step_away.properly_pressed.connect(_handle_step_away)
|
||
btn_tuber.properly_pressed.connect(_handle_run_vtuber)
|
||
btn_camera.properly_pressed.connect(_handle_camera)
|
||
|
||
|
||
func _handle_settings() -> void:
|
||
if _set_win: return
|
||
var win := Window.new()
|
||
win.borderless = false
|
||
win.always_on_top = false
|
||
win.mode = Window.MODE_WINDOWED
|
||
var pnl := SETTINGS_PANEL.instantiate()
|
||
#Globals.disable_mouse_passthrough()
|
||
win.add_child(pnl)
|
||
win.size = Vector2i(1000,800)
|
||
win.close_requested.connect(func(): win.queue_free(); _set_win = null)
|
||
win.name = "SettingsWindow"
|
||
win.title = "Settings"
|
||
get_tree().root.add_child(win)
|
||
win.show()
|
||
_set_win = win
|
||
|
||
func _handle_script_editor() -> void:
|
||
if _edit_win: return
|
||
var win := Window.new()
|
||
win.borderless = false
|
||
win.always_on_top = false
|
||
win.mode = Window.MODE_WINDOWED
|
||
var pnl := SCRIPT_EDITOR.instantiate()
|
||
win.name = "ScriptEditorWindow"
|
||
win.title = "Script Editor"
|
||
win.add_child(pnl)
|
||
win.size = Vector2i(800,600)
|
||
win.close_requested.connect(func(): win.queue_free(); _edit_win = null)
|
||
get_tree().root.add_child(win)
|
||
win.show()
|
||
_edit_win = win
|
||
|
||
func _handle_run_obs() -> void:
|
||
if _obs_proc and _obs_proc.is_running():
|
||
print("OBS is running.")
|
||
return
|
||
elif _obs_proc and not _obs_proc.is_running():
|
||
_obs_proc = null
|
||
|
||
var tree := ProcessTree.new()
|
||
if tree.has_process_name(Globals.settings.obs_name):
|
||
_obs_proc = tree.get_process_by_name(Globals.settings.obs_name)
|
||
print("OBS is running.")
|
||
return
|
||
else:
|
||
OS.create_process(Globals.settings.obs_path, [])
|
||
|
||
|
||
func _handle_step_away() -> void:
|
||
var alert = _impl_alerts.pick_random().instantiate()
|
||
if alert is FollowAlert:
|
||
alert.setup(RANDOM_NAMES.pick_random())
|
||
elif alert is CheerAlert:
|
||
alert.setup(RANDOM_NAMES.pick_random(), randi_range(10,1000), RANDOM_MESSAGES.pick_random())
|
||
elif alert is RaidAlert:
|
||
alert.setup(RANDOM_NAMES.pick_random(), randi_range(5,500))
|
||
elif alert is SubscriberAlert:
|
||
var prime: bool = randf() < 0.25
|
||
var months: int = randi_range(0,64) if randf() < 0.25 else 1
|
||
var tier: bool = randi_range(1,3)
|
||
var msg: String = RANDOM_MESSAGES.pick_random() if randf() < 0.45 else ""
|
||
alert.setup(RANDOM_NAMES.pick_random(), months, prime, tier, msg)
|
||
EventManager.add_alert(alert)
|
||
|
||
func _handle_run_vtuber() -> void:
|
||
if _vtuber_proc and _vtuber_proc.is_running():
|
||
print("VTuber is running.")
|
||
return
|
||
elif _vtuber_proc and not _vtuber_proc.is_running():
|
||
_vtuber_proc = null
|
||
|
||
|
||
var tree := ProcessTree.new()
|
||
if tree.has_process_name(Globals.settings.vtuber_name):
|
||
_vtuber_proc = tree.get_process_by_name(Globals.settings.vtuber_name)
|
||
print("VTuber is running.")
|
||
return
|
||
else:
|
||
OS.create_process(Globals.settings.vtuber_path, [Globals.settings.vtuber_model_path])
|
||
|
||
func _handle_camera() -> void:
|
||
if not ObsManager.is_open(): return
|
||
var vtuber_vis := await ObsManager.get_item_enabled("~Avatar", _vtuber_sid)
|
||
ObsManager.set_item_enabled("~Avatar",_vtuber_sid, !vtuber_vis)
|
||
ObsManager.set_item_enabled("~Avatar",_camera_sid, vtuber_vis)
|
||
var aid := await ObsManager.get_scene_item_id("Talking", "~Avatar")
|
||
var transform := await ObsManager.get_item_transform("Talking", aid)
|
||
transform.bounds_width = 1.0
|
||
transform.bounds_height = 1.0
|
||
if vtuber_vis:
|
||
transform.position_x = 70
|
||
transform.position_y = 320
|
||
else:
|
||
transform.position_x = 39
|
||
transform.position_y = 492
|
||
print("Moving ~Avatar to: %s" % [{"x": transform.position_x, "y": transform.position_y}])
|
||
ObsManager.set_item_transform("Talking", aid, transform)
|
||
#endregion
|