CraftStation Tutorial 3: UI
This tutorial continues from CraftStation Tutorial 2: Nodes and will guide you through adding a complete crafting UI to the furnace and workbench scenes you already created. You’ll enhance the existing scenes with visual interfaces that provide real-time feedback and user controls.
Prerequisites
Before starting this tutorial, make sure you have:
Completed CraftStation Tutorial 1: Resources and CraftStation Tutorial 2: Nodes
The FurnaceTest scene with FurnaceStation, InputInventory, and OutputInventory
The WorkbenchTest scene with WorkbenchStation, InputInventory, and OutputInventory
Both scenes working with their respective scripts
Building Upon Tutorial 2
We’ll be enhancing the scenes you already created in Tutorial 2:
FurnaceTest scene with its furnace station type and iron smelting
Instead of creating new scenes, we’ll add UI elements to the existing FurnaceTest scene to create a complete crafting experience.
Adding UI to the Furnace Scene
Step 1: Open the FurnaceTest Scene
Open your FurnaceTest scene from Tutorial 2
Current Structure (from Tutorial 2):
FurnaceTest (Node) ├── FurnaceStation (CraftStation) ├── InputInventory (Inventory) └── OutputInventory (Inventory)
Step 2: Add UI Structure to Furnace Scene
Add these UI nodes to your FurnaceTest scene:
Add UI Layer
CanvasLayer (name: “UI”)
MarginContainer (child of UI)
VBoxContainer (child of MarginContainer)
Add UI Elements
Under the VBoxContainer, add:
Label (name: “TitleLabel”) - text: “Furnace Station”
HBoxContainer (name: “StatusContainer”)
Label (name: “InputLabel”) - shows input inventory status
Label (name: “OutputLabel”) - shows output inventory status
Label (name: “RecipesLabel”) - text: “Available Smelting Recipes:”
VBoxContainer (name: “RecipesList”) - for recipe buttons
HBoxContainer (name: “ControlsContainer”)
Button (name: “AddMaterialsButton”) - text: “Add Materials”
Button (name: “SmeltAllButton”) - text: “Smelt All”
Label (name: “ProgressLabel”) - shows crafting progress
ProgressBar (name: “ProgressBar”)

Step 3: Update the Furnace Script
Replace the existing script on your FurnaceTest node with this enhanced version that includes UI functionality:
extends Node
# Existing nodes from Tutorial 2
@onready var craft_station = $FurnaceStation
@onready var input_inventory = $InputInventory
@onready var output_inventory = $OutputInventory
# New UI nodes
@onready var input_label = $UI/MarginContainer/VBoxContainer/StatusContainer/InputLabel
@onready var output_label = $UI/MarginContainer/VBoxContainer/StatusContainer/OutputLabel
@onready var recipes_list = $UI/MarginContainer/VBoxContainer/RecipesList
@onready var add_materials_button = $UI/MarginContainer/VBoxContainer/ControlsContainer/AddMaterialsButton
@onready var smelt_all_button = $UI/MarginContainer/VBoxContainer/ControlsContainer/SmeltAllButton
@onready var progress_label = $UI/MarginContainer/VBoxContainer/ProgressLabel
@onready var progress_bar = $UI/MarginContainer/VBoxContainer/ProgressBar
var recipe_buttons = []
func _ready():
# Original setup from Tutorial 2
_setup_initial_materials()
_setup_station()
# New UI setup
_setup_ui()
_connect_ui_signals()
_update_ui()
func _setup_initial_materials():
# Add iron ore and coal (from Tutorial 2)
input_inventory.add("iron_ore", 10)
input_inventory.add("coal", 5)
func _setup_station():
# Connect station signals
craft_station.on_crafted.connect(_on_craft_completed)
craft_station.crafting_added.connect(_on_crafting_started)
# Print station info (from Tutorial 2)
print("=== FURNACE STATION UI ===")
print("Station Type: ", craft_station.type.name if craft_station.type else "None")
print("Available recipes: ", craft_station.valid_recipes.size())
func _setup_ui():
# Configure progress bar
progress_bar.value = 0
progress_bar.visible = false
# Create recipe buttons based on valid furnace recipes
_create_recipe_buttons()
func _connect_ui_signals():
# Connect button signals
add_materials_button.pressed.connect(_add_more_materials)
smelt_all_button.pressed.connect(_smelt_all_possible)
# Connect inventory signals for UI updates
input_inventory.contents_changed.connect(_update_ui)
output_inventory.contents_changed.connect(_update_ui)
func _create_recipe_buttons():
# Clear existing buttons
for button in recipe_buttons:
button.queue_free()
recipe_buttons.clear()
# Create button for each furnace recipe
for i in craft_station.valid_recipes.size():
var recipe_index = craft_station.valid_recipes[i]
var recipe = craft_station.database.recipes[recipe_index]
var button = Button.new()
var product_name = recipe.products[0].item_id if recipe.products.size() > 0 else "Unknown"
button.text = "Smelt " + product_name
button.pressed.connect(_craft_recipe.bind(i))
recipes_list.add_child(button)
recipe_buttons.append(button)
func _add_more_materials():
# Add more smelting materials
input_inventory.add("iron_ore", 5)
input_inventory.add("coal", 3)
print("Added more iron ore and coal")
func _smelt_all_possible():
# Try to start smelting if possible
if craft_station.valid_recipes.size() > 0:
print("Starting furnace smelting...")
craft_station.craft(0)
func _craft_recipe(recipe_list_index: int):
if recipe_list_index < craft_station.valid_recipes.size():
print("Starting specific recipe: ", recipe_list_index)
craft_station.craft(recipe_list_index)
func _update_ui():
# Update inventory status
var input_count = _count_inventory_items(input_inventory)
var output_count = _count_inventory_items(output_inventory)
input_label.text = "Input Materials: " + str(input_count) + " items"
output_label.text = "Output Products: " + str(output_count) + " items"
# Update recipe button availability
for i in recipe_buttons.size():
var button = recipe_buttons[i]
if i < craft_station.valid_recipes.size():
var recipe_index = craft_station.valid_recipes[i]
var recipe = craft_station.database.recipes[recipe_index]
var can_craft = craft_station.can_craft(recipe)
button.disabled = not can_craft
button.modulate = Color.WHITE if can_craft else Color.GRAY
# Update smelt all button
smelt_all_button.disabled = not _has_craftable_recipes()
# Update progress
_update_progress()
func _count_inventory_items(inventory: Inventory) -> int:
var count = 0
for stack in inventory.stacks:
if stack:
count += stack.amount
return count
func _has_craftable_recipes() -> bool:
for recipe_index in craft_station.valid_recipes:
var recipe = craft_station.database.recipes[recipe_index]
if craft_station.can_craft(recipe):
return true
return false
func _update_progress():
if craft_station.craftings.size() > 0:
var crafting = craft_station.craftings[0]
var recipe_index = crafting.get_recipe_index()
var recipe = craft_station.database.recipes[recipe_index]
var progress = crafting.get_time() / recipe.time_to_craft
progress = clamp(progress, 0.0, 1.0)
progress_bar.value = progress * 100
progress_bar.visible = true
var product_name = recipe.products[0].item_id if recipe.products.size() > 0 else "Unknown"
progress_label.text = "Smelting " + product_name + "... " + str(int(progress * 100)) + "%"
else:
progress_bar.visible = false
progress_label.text = "Furnace ready"
# Enhanced signal handlers
func _on_crafting_started(crafting_index: int):
print("Smelting started: ", crafting_index)
_update_ui()
func _on_craft_completed(recipe_index: int):
print("Smelting completed!")
# Show output (enhanced from Tutorial 2)
for i in output_inventory.stacks.size():
var stack = output_inventory.stacks[i]
if stack:
print("Produced: ", stack.amount, "x ", stack.item_id)
_update_ui()
# Continue updating progress during smelting
func _process(_delta):
if craft_station.craftings.size() > 0:
_update_progress()
# Keep the space key functionality from Tutorial 2
func _input(event):
if event.is_action_pressed("ui_accept"):
_smelt_all_possible()
Step 4: Test the Furnace UI
Run the FurnaceTest scene
You should see: - “Furnace Station” title - Input/Output inventory counts - “Smelt Iron Ingot” button (enabled if materials available) - “Add Materials” and “Smelt All” buttons - Progress bar and status
Test the functionality: - Click “Add Materials” to add more iron ore and coal - Click “Smelt Iron Ingot” to start smelting - Watch the progress bar fill up - See the input materials decrease and output products appear
Comparing Station Behaviors
Now that both scenes have UI, you can clearly see:
Furnace Station: - Only shows furnace-specific recipes (iron smelting) - Uses iron ore and coal as inputs - Produces metal products
This demonstrates how station types successfully filter recipes and create specialized crafting workflows.
Troubleshooting
UI Not Appearing
If the UI doesn’t show up:
Check that CanvasLayer was added correctly
Verify UI node names match the script references
Ensure the MarginContainer and VBoxContainer hierarchy is correct
Progress Not Updating
If the progress bar doesn’t show:
Check that _process() is calling _update_progress()
Verify crafting signals are connected properly
Ensure the progress bar node reference is correct
Different Behavior Between Stations
This is expected! The furnace and workbench should behave differently:
Furnace: Only iron smelting recipes, uses ore/coal
If they show the same recipes, check the station type assignments.
Enhancements
Now that you have working UIs for both station types, you can enhance them further:
Visual Improvements: - Add item icons to show materials and products visually - Include inventory slot displays - Add animations for crafting progress
Functional Enhancements: - Implement crafting queues for multiple items - Add drag-and-drop item management - Include recipe cost displays
Station-Specific Features: - Add fuel management for the furnace - Include temperature or power indicators - Create different visual themes for each station type
Conclusion
You have successfully created comprehensive UIs for both crafting stations from Tutorial 2!
Enhanced the existing furnace scene with a specialized smelting interface
Maintained the station type filtering from Tutorial 2
Added real-time progress tracking and material management
Created reusable UI patterns that can be applied to other station types
The tutorials now form a complete progression:
Tutorial 1: Resources (items, recipes, station types)
Tutorial 2: Nodes (scene setup, scripting, testing)
Tutorial 3: UI (visual interfaces, user interaction)
See also
CraftStation Tutorial 1: Resources - Review resource creation
CraftStation Tutorial 2: Nodes - Review node setup and scripting