diff --git a/assets/shaders/outline3d.gdshader b/assets/shaders/outline3d.gdshader new file mode 100644 index 0000000..14aaf5b --- /dev/null +++ b/assets/shaders/outline3d.gdshader @@ -0,0 +1,21 @@ +shader_type spatial; +render_mode cull_front, unshaded; + +// Controls the width of the outline +uniform float outline_thickness : hint_range(0.0, 0.5) = 0.03; + +// Controls the color of the outline +uniform vec4 outline_color : source_color = vec4(0.0, 0.0, 0.0, 1.0); + +void vertex() { + // The core of the inverted hull method: + // We push the vertices outward along their normal vectors. + // Since front faces are culled, this creates the outline border. + VERTEX += NORMAL * outline_thickness; +} + +void fragment() { + // Apply the solid outline color + ALBEDO = outline_color.rgb; + ALPHA = outline_color.a; +} \ No newline at end of file diff --git a/assets/shaders/outline3d.gdshader.uid b/assets/shaders/outline3d.gdshader.uid new file mode 100644 index 0000000..7498dfd --- /dev/null +++ b/assets/shaders/outline3d.gdshader.uid @@ -0,0 +1 @@ +uid://cc6tnqkwd8iy6 diff --git a/scenes/lobby.gd b/scenes/lobby.gd index c2e00d6..b689620 100644 --- a/scenes/lobby.gd +++ b/scenes/lobby.gd @@ -145,6 +145,10 @@ func _ready(): refresh_btn.pressed.connect(_on_refresh_pressed) join_btn.pressed.connect(_on_join_pressed) back_btn.pressed.connect(_on_back_pressed) + + if room_list: + room_list.item_selected.connect(_on_room_selected) + room_list.item_activated.connect(_on_room_activated) if room_list_profile_btn: room_list_profile_btn.pressed.connect(_on_profile_btn_pressed) @@ -361,6 +365,24 @@ func _on_refresh_pressed() -> void: room_list.clear() LobbyManager.refresh_room_list() +func _on_room_selected(index: int) -> void: + """Automatically fill the match_id input when a room is clicked so it's not lost on focus change.""" + if index < LobbyManager.available_rooms.size(): + var room = LobbyManager.available_rooms[index] + if LobbyManager.is_lan_mode: + var ip = room.get("ip", "") + if not ip.is_empty(): + match_id_input.text = ip + else: + var mid = room.get("match_id", "") + if not mid.is_empty(): + match_id_input.text = mid + +func _on_room_activated(index: int) -> void: + """Handle double-clicking a room to join immediately.""" + _on_room_selected(index) + _on_join_pressed() + func _on_join_pressed() -> void: var match_id = match_id_input.text.strip_edges() diff --git a/scenes/player.gd b/scenes/player.gd index 56fe728..fa504d4 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -438,6 +438,26 @@ func set_character(character_name: String) -> void: anim_player.root_node = anim_player.get_path_to(active_character) # Start with idle animation play_idle_animation() + + # Apply outline shader to the active character + if active_character: + _apply_outline_recursive(active_character) + +func _apply_outline_recursive(node: Node): + if node is MeshInstance3D and node.mesh: + for i in range(node.mesh.get_surface_count()): + var mat = node.get_active_material(i) + if mat: + # Only apply if it doesn't already have a next pass + if not mat.next_pass: + var unique_mat = mat.duplicate() + var outline_mat = ShaderMaterial.new() + outline_mat.shader = load("res://assets/shaders/outline3d.gdshader") + unique_mat.next_pass = outline_mat + node.set_surface_override_material(i, unique_mat) + + for child in node.get_children(): + _apply_outline_recursive(child) @rpc("any_peer", "call_local", "reliable") func sync_character(character_name: String) -> void: