diff --git a/Defaults/default.tres b/Defaults/default.tres
index 438497a..74ba54e 100644
--- a/Defaults/default.tres
+++ b/Defaults/default.tres
@@ -1,4 +1,4 @@
-[gd_resource type="Theme" load_steps=4 format=3 uid="uid://5wxvr808qkyw"]
+[gd_resource type="Theme" load_steps=5 format=3 uid="uid://5wxvr808qkyw"]
 
 [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jyao1"]
 bg_color = Color(0, 0, 0, 0.196078)
@@ -6,6 +6,11 @@ border_width_top = 2
 border_color = Color(0, 0, 0, 1)
 border_blend = true
 
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_rx68y"]
+bg_color = Color(0, 0, 0, 0.196078)
+border_width_left = 2
+border_color = Color(0, 0, 0, 1)
+
 [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mceqj"]
 content_margin_left = 6.0
 content_margin_right = 6.0
@@ -14,13 +19,12 @@ bg_color = Color(0, 0, 0, 1)
 [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7tf7i"]
 bg_color = Color(0, 0, 0, 0.196078)
 border_width_left = 2
-border_width_top = 2
-border_width_bottom = 2
 border_color = Color(0, 0, 0, 1)
-border_blend = true
 
 [resource]
 HBoxContainer/constants/separation = 0
 ItemList/styles/panel = SubResource("StyleBoxFlat_jyao1")
+Label/styles/normal = SubResource("StyleBoxFlat_rx68y")
 MenuButton/styles/normal = SubResource("StyleBoxFlat_mceqj")
 RichTextLabel/styles/normal = SubResource("StyleBoxFlat_7tf7i")
+VSplitContainer/constants/separation = 0
diff --git a/Scenes/UI.tscn b/Scenes/UI.tscn
index 6745382..fe2cab6 100644
--- a/Scenes/UI.tscn
+++ b/Scenes/UI.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=24 format=3 uid="uid://cdwpy8hm6qseq"]
+[gd_scene load_steps=29 format=3 uid="uid://cdwpy8hm6qseq"]
 
 [ext_resource type="Script" path="res://Scripts/UI/UI.gd" id="1_yufu8"]
 [ext_resource type="Theme" uid="uid://5wxvr808qkyw" path="res://Defaults/default.tres" id="2_pfeim"]
@@ -8,7 +8,8 @@
 [ext_resource type="PackedScene" uid="uid://baepcmjcgsbk0" path="res://Objects/Compass.glb" id="6_exilt"]
 [ext_resource type="Script" path="res://Scripts/UI/Sidebar/EditorInfo.gd" id="7_jfdyk"]
 [ext_resource type="Script" path="res://Scripts/UI/Compass.gd" id="7_lgwbb"]
-[ext_resource type="Script" path="res://Scripts/UI/Toolbar/Palette.gd" id="10_yvdlw"]
+[ext_resource type="Script" path="res://Scripts/UI/Toolbar/Triles.gd" id="9_4swbr"]
+[ext_resource type="Script" path="res://Scripts/UI/Toolbar/NPCs.gd" id="10_2driq"]
 [ext_resource type="Script" path="res://Scripts/Importer/Importer.gd" id="11_b3xhm"]
 [ext_resource type="Script" path="res://Scripts/Exporter/Exporter.gd" id="12_4xdn3"]
 
@@ -36,6 +37,14 @@ keycode = 83
 [sub_resource type="Shortcut" id="Shortcut_c4g0v"]
 events = [SubResource("InputEventKey_txw7b")]
 
+[sub_resource type="InputEventKey" id="InputEventKey_pptsy"]
+device = -1
+ctrl_pressed = true
+keycode = 78
+
+[sub_resource type="Shortcut" id="Shortcut_o221s"]
+events = [SubResource("InputEventKey_pptsy")]
+
 [sub_resource type="InputEventKey" id="InputEventKey_slhck"]
 device = -1
 ctrl_pressed = true
@@ -60,6 +69,14 @@ keycode = 72
 [sub_resource type="Shortcut" id="Shortcut_efjk7"]
 events = [SubResource("InputEventKey_oq4ek")]
 
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mn0ei"]
+bg_color = Color(0, 0, 0, 0.196078)
+border_width_left = 2
+border_color = Color(0, 0, 0, 1)
+
+[sub_resource type="Theme" id="Theme_328gk"]
+Label/styles/normal = SubResource("StyleBoxFlat_mn0ei")
+
 [node name="UI" type="VBoxContainer"]
 anchors_preset = 15
 anchor_right = 1.0
@@ -68,6 +85,7 @@ grow_horizontal = 2
 grow_vertical = 2
 size_flags_horizontal = 3
 size_flags_vertical = 3
+theme_override_constants/separation = 0
 script = ExtResource("1_yufu8")
 
 [node name="Titlebar" type="HBoxContainer" parent="."]
@@ -80,22 +98,25 @@ shortcut = SubResource("Shortcut_aqtus")
 text = "File"
 flat = false
 switch_on_hover = true
-item_count = 5
+item_count = 6
 popup/item_0/text = "Load Level"
 popup/item_0/id = 0
 popup/item_1/text = "Save Level"
 popup/item_1/id = 1
 popup/item_1/disabled = true
-popup/item_2/text = "Options"
-popup/item_2/id = 2
-popup/item_3/text = ""
-popup/item_3/id = 3
-popup/item_3/separator = true
-popup/item_4/text = "Quit"
-popup/item_4/id = 4
+popup/item_2/text = "New Level"
+popup/item_2/id = 5
+popup/item_3/text = "Options"
+popup/item_3/id = 2
+popup/item_4/text = ""
+popup/item_4/id = 3
+popup/item_4/separator = true
+popup/item_5/text = "Quit"
+popup/item_5/id = 4
 script = ExtResource("3_mnd5b")
 loadShortcut = SubResource("Shortcut_8hi2n")
 saveShortcut = SubResource("Shortcut_c4g0v")
+newShortcut = SubResource("Shortcut_o221s")
 quitShortcut = SubResource("Shortcut_x4u3j")
 
 [node name="Load" type="FileDialog" parent="Titlebar/File"]
@@ -103,6 +124,7 @@ title = "Open a File"
 initial_position = 1
 size = Vector2i(454, 400)
 ok_button_text = "Open"
+dialog_hide_on_ok = true
 file_mode = 0
 access = 2
 filters = PackedStringArray("*.fezlvl.json ; FEZ Levels")
@@ -111,11 +133,22 @@ use_native_dialog = true
 [node name="Save" type="FileDialog" parent="Titlebar/File"]
 title = "Save FEZLVL as"
 initial_position = 2
+ok_button_text = "Save"
 dialog_hide_on_ok = true
 access = 2
 filters = PackedStringArray("*.fezlvl.json ; FEZ Levels")
 use_native_dialog = true
 
+[node name="New" type="FileDialog" parent="Titlebar/File"]
+title = "Open a File"
+initial_position = 2
+ok_button_text = "Open"
+dialog_hide_on_ok = true
+file_mode = 0
+access = 2
+filters = PackedStringArray("*.fezts.json ; FEZ Trileset")
+use_native_dialog = true
+
 [node name="Edit" type="MenuButton" parent="Titlebar"]
 layout_mode = 2
 text = "Edit"
@@ -128,18 +161,16 @@ shortcut = SubResource("Shortcut_5p5ho")
 text = "View"
 flat = false
 switch_on_hover = true
-item_count = 5
-popup/item_0/text = "Palette"
-popup/item_0/id = 0
-popup/item_1/text = "Hide layers..."
-popup/item_1/id = 1
-popup/item_2/text = ""
-popup/item_2/id = 10
-popup/item_2/separator = true
-popup/item_3/text = "Debug terminal"
-popup/item_3/id = 2
-popup/item_4/text = "Raw FEZLVL.JSON"
-popup/item_4/id = 3
+item_count = 4
+popup/item_0/text = "Hide layers..."
+popup/item_0/id = 1
+popup/item_1/text = ""
+popup/item_1/id = 10
+popup/item_1/separator = true
+popup/item_2/text = "Debug terminal"
+popup/item_2/id = 2
+popup/item_3/text = "Raw FEZLVL.JSON"
+popup/item_3/id = 3
 
 [node name="Help" type="MenuButton" parent="Titlebar"]
 layout_mode = 2
@@ -195,34 +226,44 @@ size_flags_horizontal = 3
 mouse_filter = 1
 color = Color(0, 0, 0, 1)
 
-[node name="Sidebar" type="HBoxContainer" parent="."]
+[node name="VSplitContainer" type="VSplitContainer" parent="."]
+clip_contents = true
+layout_mode = 2
+size_flags_vertical = 3
+theme = ExtResource("2_pfeim")
+
+[node name="Sidebar" type="HBoxContainer" parent="VSplitContainer"]
 layout_mode = 2
 size_flags_vertical = 3
 size_flags_stretch_ratio = 15.0
 
-[node name="Spacer" type="Container" parent="Sidebar"]
+[node name="Spacer" type="Control" parent="VSplitContainer/Sidebar"]
 layout_mode = 2
 size_flags_horizontal = 3
 size_flags_stretch_ratio = 5.3
+mouse_filter = 1
 
-[node name="SidebarVertical" type="VBoxContainer" parent="Sidebar"]
+[node name="SidebarVertical" type="VBoxContainer" parent="VSplitContainer/Sidebar"]
 layout_mode = 2
 size_flags_horizontal = 3
 size_flags_vertical = 3
+theme_override_constants/separation = 0
 
-[node name="Position" type="Label" parent="Sidebar/SidebarVertical"]
+[node name="Position" type="Label" parent="VSplitContainer/Sidebar/SidebarVertical"]
 layout_mode = 2
 mouse_filter = 1
+theme = SubResource("Theme_328gk")
 text = "[0, 0, 0]"
 horizontal_alignment = 1
 
-[node name="Object" type="Label" parent="Sidebar/SidebarVertical"]
+[node name="Object" type="Label" parent="VSplitContainer/Sidebar/SidebarVertical"]
 layout_mode = 2
 mouse_filter = 1
+theme = ExtResource("2_pfeim")
 text = "None"
 horizontal_alignment = 1
 
-[node name="EditorLog" type="RichTextLabel" parent="Sidebar/SidebarVertical"]
+[node name="EditorLog" type="RichTextLabel" parent="VSplitContainer/Sidebar/SidebarVertical"]
 layout_mode = 2
 size_flags_vertical = 3
 theme = ExtResource("2_pfeim")
@@ -232,51 +273,114 @@ scroll_following = true
 threaded = true
 script = ExtResource("7_jfdyk")
 
-[node name="CompassView" type="SubViewportContainer" parent="Sidebar/SidebarVertical"]
+[node name="CompassView" type="SubViewportContainer" parent="VSplitContainer/Sidebar/SidebarVertical"]
 visible = false
 layout_mode = 2
 size_flags_vertical = 3
 size_flags_stretch_ratio = 0.5
 stretch = true
 
-[node name="Compass" type="SubViewport" parent="Sidebar/SidebarVertical/CompassView"]
+[node name="Compass" type="SubViewport" parent="VSplitContainer/Sidebar/SidebarVertical/CompassView"]
 transparent_bg = true
 handle_input_locally = false
 size = Vector2i(2, 2)
 render_target_update_mode = 0
 
-[node name="Compass" parent="Sidebar/SidebarVertical/CompassView/Compass" instance=ExtResource("6_exilt")]
+[node name="Compass" parent="VSplitContainer/Sidebar/SidebarVertical/CompassView/Compass" instance=ExtResource("6_exilt")]
 transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0, 0, 0)
 visible = false
 script = ExtResource("7_lgwbb")
 
-[node name="CompPivot" type="Node3D" parent="Sidebar/SidebarVertical/CompassView/Compass"]
+[node name="CompPivot" type="Node3D" parent="VSplitContainer/Sidebar/SidebarVertical/CompassView/Compass"]
 transform = Transform3D(-1, 0, 8.74228e-08, 0, 1, 0, -8.74228e-08, 0, -1, 0, 0, 0)
 
-[node name="CompassCam" type="Camera3D" parent="Sidebar/SidebarVertical/CompassView/Compass/CompPivot"]
+[node name="CompassCam" type="Camera3D" parent="VSplitContainer/Sidebar/SidebarVertical/CompassView/Compass/CompPivot"]
 transform = Transform3D(0.707107, -0.380969, 0.595704, 0, 0.842453, 0.538771, -0.707107, -0.380969, 0.595704, 6.79999, 6.79999, 6.79999)
 cull_mask = 1
 projection = 1
 size = 10.0
 far = 20.0
 
-[node name="Toolbar" type="HBoxContainer" parent="."]
+[node name="Toolbar" type="HBoxContainer" parent="VSplitContainer"]
+clip_contents = true
+custom_minimum_size = Vector2(0, 1)
 layout_mode = 2
 size_flags_vertical = 3
+theme_override_constants/separation = 0
 
-[node name="TextureButton" type="TextureButton" parent="Toolbar"]
+[node name="ChoosePalette" type="OptionButton" parent="VSplitContainer/Toolbar"]
 layout_mode = 2
+alignment = 1
+item_count = 3
+selected = 0
+fit_to_longest_item = false
+popup/item_0/text = "Triles"
+popup/item_0/id = 0
+popup/item_0/disabled = true
+popup/item_1/text = "Art Objects"
+popup/item_1/id = 1
+popup/item_1/disabled = true
+popup/item_2/text = "NPCs"
+popup/item_2/id = 2
+popup/item_2/disabled = true
 
-[node name="Palette" type="ItemList" parent="Toolbar"]
+[node name="Palettes" type="Control" parent="VSplitContainer/Toolbar"]
 layout_mode = 2
 size_flags_horizontal = 3
+mouse_filter = 2
+
+[node name="Triles" type="ItemList" parent="VSplitContainer/Toolbar/Palettes"]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+mouse_force_pass_scroll_events = false
+theme = ExtResource("2_pfeim")
+allow_search = false
+max_columns = 0
+same_column_width = true
+icon_mode = 0
+icon_scale = 2.0
+script = ExtResource("9_4swbr")
+
+[node name="AOs" type="ItemList" parent="VSplitContainer/Toolbar/Palettes"]
+visible = false
+clip_contents = false
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+mouse_force_pass_scroll_events = false
+theme = ExtResource("2_pfeim")
+allow_search = false
+max_columns = 0
+same_column_width = true
+icon_mode = 0
+icon_scale = 2.0
+
+[node name="NPCs" type="ItemList" parent="VSplitContainer/Toolbar/Palettes"]
+visible = false
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
 mouse_force_pass_scroll_events = false
 theme = ExtResource("2_pfeim")
 allow_search = false
 max_columns = 0
 same_column_width = true
+icon_mode = 0
 icon_scale = 2.0
-script = ExtResource("10_yvdlw")
+script = ExtResource("10_2driq")
 
 [node name="SFX" type="AudioStreamPlayer" parent="."]
 
@@ -296,9 +400,11 @@ script = ExtResource("12_4xdn3")
 [connection signal="confirmed" from="Titlebar/File/Load" to="." method="_on_load_dialog_confirmed"]
 [connection signal="file_selected" from="Titlebar/File/Load" to="Loader" method="_on_load_dialog_file_selected"]
 [connection signal="file_selected" from="Titlebar/File/Save" to="Exporter" method="_on_save_file_selected"]
+[connection signal="file_selected" from="Titlebar/File/New" to="Titlebar/File" method="_on_new_file_selected"]
 [connection signal="close_requested" from="Titlebar/Help/About" to="Titlebar/Help" method="_on_about_close_requested"]
+[connection signal="item_selected" from="VSplitContainer/Toolbar/ChoosePalette" to="VSplitContainer/Toolbar/Palettes/Triles" method="_on_choose_palette_item_selected"]
 [connection signal="levelJSON" from="Loader" to="Titlebar/File" method="_on_loader_level_json"]
 [connection signal="levelJSON" from="Loader" to="Titlebar/View" method="_on_loader_level_json"]
-[connection signal="levelJSON" from="Loader" to="Sidebar/SidebarVertical/EditorLog" method="_on_loader_level_json"]
-[connection signal="loadedTS" from="Loader" to="Toolbar/Palette" method="_on_loader_loaded_ts"]
+[connection signal="levelJSON" from="Loader" to="VSplitContainer/Sidebar/SidebarVertical/EditorLog" method="_on_loader_level_json"]
+[connection signal="loadedTS" from="Loader" to="VSplitContainer/Toolbar/Palettes/Triles" method="_on_loader_loaded_ts"]
 [connection signal="newCurPor" from="Loader" to="." method="_on_loader_new_cur_por"]
diff --git a/Scripts/Cursor.gd b/Scripts/Cursor.gd
index 710a771..c360028 100644
--- a/Scripts/Cursor.gd
+++ b/Scripts/Cursor.gd
@@ -16,6 +16,10 @@ func tweenToPos(obj: Object, property: NodePath, direction: Variant, action, spe
 	allowMove = false
 	
 	var tween = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CIRC)
+	
+	if typeof(direction) == TYPE_VECTOR3: # Round position down.
+		direction = round(direction)
+		
 	tween.tween_property(obj, property, direction, speed)
 	emit_signal("hasMoved", action)
 	
@@ -40,6 +44,7 @@ func _process(_delta):
 	
 func _unhandled_input(_event):
 	if allowMove: # Movement control. Why does this have to be a bunch of if statements?
+		# Yes, this is reversed, but that's because of the position of the camera.
 		var forward = transform.basis.z; var right = -transform.basis.x
 		var _moveTo = Vector3.ZERO # Prevent cursor from going below (0, 0, 0)
 
diff --git a/Scripts/Exporter/Exporter.gd b/Scripts/Exporter/Exporter.gd
index b1229ba..5ca4e1b 100644
--- a/Scripts/Exporter/Exporter.gd
+++ b/Scripts/Exporter/Exporter.gd
@@ -67,7 +67,7 @@ func _saveFEZLVL(path, filename):
 				"StartingPoint":
 					var id = obj.get_meta("Id")
 					var face = obj.get_meta("Face")
-					var spDict = { "Id": id, "Face": face}
+					var spDict = { "Id": [id[0], id[1], id[2] - 1], "Face": face}
 					
 					template["StartingPosition"] = spDict
 					pass
diff --git a/Scripts/Importer/Importer.gd b/Scripts/Importer/Importer.gd
index 62ad868..66f83ae 100644
--- a/Scripts/Importer/Importer.gd
+++ b/Scripts/Importer/Importer.gd
@@ -30,13 +30,17 @@ func _ready():
 	pass
 
 func _on_load_dialog_file_selected(path):
-	for n in get_child_count(): # Clear out all objects.
-		get_child(n).queue_free()
+	killChildren()
 	
 	_mutex.lock(); _path = path; _mutex.unlock(); # Send file path to thread.
 	_sema.post() # Tell thread to start processing.
 	pass
 
+func killChildren(): # Please do not judge my function names.
+	for n in get_child_count(): # Clear out all objects.
+		get_child(n).queue_free()
+	pass
+
 func _loadFEZLVL():
 	while true:
 		_sema.wait() # Wait for signal from main thread to start processing.
@@ -57,7 +61,7 @@ func _loadFEZLVL():
 		if err == OK:
 			var lvlData = readLvl.data 
 			# Load trileset.
-			trileset = await _loadObj(Settings.TSDir + lvlData["TrileSetName"].to_lower() + ".fezts.json", 2)
+			trileset = await loadObj(Settings.TSDir + lvlData["TrileSetName"].to_lower() + ".fezts.json", 2)
 			
 			# Place fezlvl triles into scene.
 			var trilePlacements = lvlData["Triles"] # Extract emplacements, phi, and trile ID.
@@ -87,7 +91,7 @@ func _loadFEZLVL():
 		else: 
 			print("Error reading .fezlvl.")
 
-func _loadObj(filepath: String, type: int = 4):
+func loadObj(filepath: String, type: int = 4):
 	var cleanPath = filepath.get_basename()
 	match type:
 		2: # Load trileset as ArrayMesh, and trile names as Dictionary.
@@ -183,7 +187,7 @@ func placeAO(dir, ao):
 	var rot = ao["Rotation"]
 	var scale = ao["Scale"]
 	
-	var obj = await _loadObj(dir + objName + ".fezao.json")
+	var obj = await loadObj(dir + objName + ".fezao.json")
 	
 	obj.quaternion = Quaternion(rot[0], rot[1], rot[2], rot[3])
 	obj.scale = Vector3(scale[0], scale[1], scale[2])
@@ -210,6 +214,15 @@ func placeStart(dir, posArray):
 	gomez.texture_filter = BaseMaterial3D.TEXTURE_FILTER_NEAREST
 	gomez.scale = Vector3(5, 5, 5)
 	
+	var statBod = StaticBody3D.new() # Set up collisions for Cursor
+	var colBod = CollisionShape3D.new()
+	var colShape = SphereShape3D.new()
+	
+	colShape.radius = 0.05
+	colBod.shape = colShape
+	statBod.add_child(colBod)
+	gomez.add_child(statBod)
+	
 	# Figuring out where to place him
 	var posStr = posArray["Id"]
 	var face = posArray["Face"]
@@ -217,19 +230,21 @@ func placeStart(dir, posArray):
 	
 	match face: # Test with levels to find out where we should place Gomez!
 		"Front": adjust = Vector3.FORWARD
-		"Back":  adjust = Vector3.DOWN
+		"Back":  adjust = Vector3.BACK
 		"Left":  adjust = Vector3.LEFT
 		"Right": adjust = Vector3.RIGHT
 		"Top":   adjust = Vector3.UP
 		"Down":  adjust = Vector3.DOWN
 		
-	var pos = Vector3(posStr[0], posStr[1], posStr[2]) - adjust
+	var pos = Vector3(posStr[0], posStr[1], posStr[2]) + adjust
 	
 	gomez.position = pos
 	gomez.layers = 8
 	gomez.set_meta("Type", "StartingPoint")
 	gomez.set_meta("Id", posStr)
 	gomez.set_meta("Face", face)
+	gomez.set_meta("Name", "Gomez")
+	gomez.play("gif")
 	call_deferred("add_child", gomez)
 	return pos
 
diff --git a/Scripts/Settings.gd b/Scripts/Settings.gd
index 2a287d6..8556128 100644
--- a/Scripts/Settings.gd
+++ b/Scripts/Settings.gd
@@ -12,7 +12,7 @@ var NPCDir
 var TSDir
 
 func _ready(): # Load saved data, if available.
-	var err = config.load("user://HARDHAT.cfg")
+	var err = config.load("user://Beret.cfg")
 	if err != OK: # If not, have the user set up save data.
 		var s = preload("res://Scenes/NoDirs.tscn")
 		get_tree().change_scene_to_packed(s)
diff --git a/Scripts/UI/Titlebar/menuFile.gd b/Scripts/UI/Titlebar/menuFile.gd
index 2ef2656..c8cce7d 100644
--- a/Scripts/UI/Titlebar/menuFile.gd
+++ b/Scripts/UI/Titlebar/menuFile.gd
@@ -2,16 +2,24 @@ extends MenuButton
 
 @onready var _fdLoad = $Load
 @onready var _svFile = $Save
+@onready var _nwFile = $New
+
+@onready var _ldr = $"../../Loader"
 
 @export var loadShortcut: Shortcut
 @export var saveShortcut: Shortcut
+@export var newShortcut: Shortcut
 @export var quitShortcut: Shortcut
 
 func _ready():
 	self.get_popup().id_pressed.connect(_on_file_menu_pressed)
 	get_popup().set_item_shortcut(0, loadShortcut, true)
 	get_popup().set_item_shortcut(1, saveShortcut, true)
-	get_popup().set_item_shortcut(4, quitShortcut, true)
+	get_popup().set_item_shortcut(5, quitShortcut, true)
+	get_popup().set_item_shortcut(2, newShortcut, true)
+	
+	_fdLoad.root_subfolder = Settings.LVLDir
+	_nwFile.root_subfolder = Settings.TSDir
 
 func _on_file_menu_pressed(id: int):
 	match id:
@@ -23,9 +31,21 @@ func _on_file_menu_pressed(id: int):
 			print("To do!")
 		4:
 			get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST)
+		5:
+			_nwFile.visible = true
 
 
 func _on_loader_level_json(_lvlJSON, _trileNum, _aoNum, _npcNum):
 	# Once a level is loaded, let the user save.
 	get_popup().set_item_disabled(1, false)
-	pass # Replace with function body.
+	pass
+
+func _on_new_file_selected(path: String):
+	var cleanPath = path.get_basename() + ".json"
+	# Have the user choose a trileset, and let the user save.
+	get_popup().set_item_disabled(1, false)
+	_ldr.killChildren() # Clear out all objects
+	var trileset = await _ldr.loadObj(cleanPath, 2)
+	_ldr.trileset = trileset # Let the importer know we have loaded a new TS
+	_ldr.loadedTS.emit(trileset)
+	pass
diff --git a/Scripts/UI/Toolbar/NPCs.gd b/Scripts/UI/Toolbar/NPCs.gd
new file mode 100644
index 0000000..a210eb6
--- /dev/null
+++ b/Scripts/UI/Toolbar/NPCs.gd
@@ -0,0 +1,11 @@
+extends ItemList
+
+# Called when the node enters the scene tree for the first time.
+func _ready():
+	# For now, we'll only let the user place Gomez as the starting point.
+	var gif = GifManager.sprite_frames_from_file(Settings.NPCDir + "gomez/idlewink.gif")
+	var tex = gif.get_frame_texture("gif", 0)
+	
+	var idx = add_icon_item(tex, true)
+	set_item_metadata(idx, "StartingPoint") # Set type of NPC as metadata.
+	set_item_tooltip(idx, "Gomez (StartingPoint)") # Set name as tooltip.
diff --git a/Scripts/UI/Toolbar/Palette.gd b/Scripts/UI/Toolbar/Palette.gd
deleted file mode 100644
index 1638c5a..0000000
--- a/Scripts/UI/Toolbar/Palette.gd
+++ /dev/null
@@ -1,30 +0,0 @@
-extends ItemList
-
-const TRILE_SIZE = 18 # Width and height of trile textures, in pixels.
-
-func _on_loader_loaded_ts(trileset):
-	clear() # Empty out list, in case it's full from another level.
-	
-	var tex: Texture2D = trileset[1].albedo_texture # Get texture
-	var info: Dictionary = trileset[2] # Extract atlas offset and trile name from here!
-	
-	var w = tex.get_width()
-	var h = tex.get_height()
-	
-	# Trixel Engine defines the positions of textures as an "Atlas Offset" multiplied by image
-	# width and height. We'll implement the same thing here to find both the trile texture and its
-	# representative name.
-	
-	for trile in info:
-		var offsetX = floor(info[trile]["AtlasOffset"][0] * w)
-		var offsetY = floor(info[trile]["AtlasOffset"][1] * h)
-		var atl = AtlasTexture.new()
-		
-		atl.atlas = tex
-		atl.region = Rect2(offsetX, offsetY, TRILE_SIZE, TRILE_SIZE)
-		atl.filter_clip = true
-		
-		var idx = add_item(info[trile]["Name"], atl, true)
-		set_item_metadata(idx, trile) # Set trile ID as metadata.
-		pass
-	pass
diff --git a/Scripts/UI/Toolbar/Triles.gd b/Scripts/UI/Toolbar/Triles.gd
new file mode 100644
index 0000000..1844342
--- /dev/null
+++ b/Scripts/UI/Toolbar/Triles.gd
@@ -0,0 +1,50 @@
+extends ItemList
+
+const TRILE_SIZE = 18 # Width and height of trile textures, in pixels.
+@onready var _Colors: OptionButton = $"../../ChoosePalette" # "Colors", because this is a palette!
+
+var curTS = null
+
+func _on_loader_loaded_ts(trileset):
+	curTS = trileset
+	# Enable all "colors"; default to "Triles".
+	for i in _Colors.item_count:
+		_Colors.set_item_disabled(i, false)
+	reloadTS(trileset)
+
+func _on_choose_palette_item_selected(index): # Hide palettes except for the one we chose.
+	var showPalette = index
+	var numChild = get_parent().get_child_count()
+	for palette in range(0, numChild):
+		if palette == showPalette:
+			get_parent().get_child(palette).visible = true
+		else:
+			get_parent().get_child(palette).visible = false
+
+func reloadTS(trileset): # (Re)load trileset.
+	clear() # Empty out list, in case it's full.
+	
+	var tex: Texture2D = trileset[1].albedo_texture # Get texture
+	var info: Dictionary = trileset[2] # Extract atlas offset and trile name from here!
+	
+	var w = tex.get_width()
+	var h = tex.get_height()
+	
+	# Trixel Engine defines the positions of textures as an "Atlas Offset" multiplied by image
+	# width and height. We'll implement the same thing here to find both the trile texture and its
+	# representative name.
+	
+	for trile in info:
+		var offsetX = floor(info[trile]["AtlasOffset"][0] * w)
+		var offsetY = floor(info[trile]["AtlasOffset"][1] * h)
+		var atl = AtlasTexture.new()
+		
+		atl.atlas = tex
+		atl.region = Rect2(offsetX, offsetY, TRILE_SIZE, TRILE_SIZE) # Get the texture at position x and y
+		atl.filter_clip = true # Don't let the textures bleed into each other!
+		
+		var idx = add_icon_item(atl, true)
+		set_item_metadata(idx, trile) # Set trile ID as metadata.
+		set_item_tooltip(idx, info[trile]["Name"]) # Set trile name as tooltip.
+		pass
+	pass
diff --git a/Scripts/UI/UI.gd b/Scripts/UI/UI.gd
index 11c1700..8c39aff 100644
--- a/Scripts/UI/UI.gd
+++ b/Scripts/UI/UI.gd
@@ -10,26 +10,21 @@ var soundRight = preload("res://Sounds/rotateright.wav")
 var posFormat = "[%d, %d, %d]" # Position formatting.
 var movement = false
 
-var tID: String = "" # Trile ID.
-var onTrile = null
+var onObj = null
 
-@onready var _infoLabel: Label = $"Sidebar/SidebarVertical/Position"
-@onready var _objLabel: Label  = $"Sidebar/SidebarVertical/Object"
+@onready var _infoLabel: Label = $"VSplitContainer/Sidebar/SidebarVertical/Position"
+@onready var _objLabel: Label  = $"VSplitContainer/Sidebar/SidebarVertical/Object"
+
+@onready var _palettes: Control = $"VSplitContainer/Toolbar/Palettes"
 
-@onready var _palette: ItemList = $"Toolbar/Palette"
 @onready var _loader: Node3D = $"Loader"
 @onready var _cursor: Node3D = $"../Cursor"
+@onready var _curArea: Area3D = $"../Cursor/Area3D"
 
 @onready var _sfx: AudioStreamPlayer = $"SFX"
 
 signal cursorPos(newPos: Vector3) # A relay from Loader.
 
-func _ready():
-	var curArea = $"../Cursor/Area3D"
-	curArea.body_entered.connect(_on_body_entered)
-	_palette.item_selected.connect(_on_object_clicked)
-	pass
-
 func _notification(what):
 	if what == NOTIFICATION_WM_CLOSE_REQUEST: # Handle closing the window.
 		_sfx.stream = soundCancel; _sfx.play()
@@ -38,9 +33,23 @@ func _notification(what):
 		get_tree().quit()
 
 func _process(_delta):
-	var pos = _cursor.get_child(1).global_position
+	var pos = _cursor.global_position # Update Position label
 	var posStr = posFormat % [pos.x, pos.y, pos.z]
 	_infoLabel.set_text(posStr)
+	
+func _physics_process(_delta):
+	# Update Object label
+	if _curArea.has_overlapping_bodies():
+		var bodies = _curArea.get_overlapping_bodies()
+		if !(bodies.size() == 0): # Prevent trying to get a nil value
+			onObj = bodies[0].get_parent() # Maybe we should list all objects? AOs could inhabit the same space...
+		
+			var objName = onObj.get_meta("Name")
+			_objLabel.set_text(str(objName))
+	else:
+		onObj = null
+		_objLabel.set_text("None")
+		
 
 func _on_cursor_has_moved(keyPress): # Sounds for movement.
 	match keyPress:
@@ -61,29 +70,60 @@ func _on_loader_new_cur_por(newPos):
 	emit_signal("cursorPos", newPos)
 	pass
 
-# Check collisions (with triles, AOs)
-func _on_body_entered(body):
-	onTrile = body.get_parent()
-	var objName = onTrile.get_meta("Name")
-	if body != null:
-		_objLabel.set_text(str(objName))
-	else:
-		_objLabel.set_text("None")
-	pass
-	
-# Get trile ID/name of selected object
-func _on_object_clicked(idx):
-	tID = _palette.get_item_metadata(idx)
-	print(tID)
-	pass
-
 # Allow placing/removing of objects
 func _unhandled_input(event): 
-	if event.is_action_pressed("place_object", true) and !tID.is_empty():
-		var info: Dictionary = {"Id" : tID, "Position" : _cursor.global_position, "Phi" : 0}
-		_loader.placeTrile(_loader.trileset, info)
-		pass
+	# First, let's see what the active (visible) palette is
+	var active: ItemList = getActivePalette(_palettes)
+	var selected = active.get_selected_items()
+	var objID = null
+	var objType = active.get_name() # The name of the palette will decide what we're placing.
+	
+	if !(selected.size() == 0): # If something is selected,
+		objID = active.get_item_metadata(selected[0])
+		
+		if event.is_action_pressed("place_object", true):
+			match objType:
+				"Triles":
+					if !objID.is_empty() and (onObj == null): # and if nothing's there
+						await plObj(objID, "Trile")
+					elif !objID.is_empty() and !(onObj == null): # or if a trile is already occupying that spot
+						await rmObj(onObj) # Delete it, and change it to the new trile.
+						await plObj(objID, "Trile")
+				"AOs":
+					pass
+				"NPCs":
+					await plObj(objID, "NPC")
+					pass
+					
+			_curArea.monitoring = false; _curArea.monitoring = true # Force the area to update
+			
+	if event.is_action_pressed("remove_object", true) and !(onObj == null): # Remove valid objects
+		await rmObj(onObj)
 		
-	if event.is_action_pressed("remove_object", true) and !(onTrile == null):
-		onTrile.queue_free()
-		pass
+func rmObj(obj):
+	obj.queue_free()
+	onObj = null
+	return OK
+	
+func plObj(obj, type: String):
+	match type:
+		"Trile":
+			# We should probably factor in camera rotation as the Phi value.
+			var info: Dictionary = {"Id" : obj, "Position" : _cursor.global_position, "Phi" : 0}
+			_loader.placeTrile(_loader.trileset, info)
+		"AO":
+			pass
+		"NPC":
+			if obj == "StartingPoint":
+				# It looks like the Trixel engine only has sepcific positions for Gomez to spawn at.
+				var info: Dictionary = {"Id": _cursor.global_position, "Face": "Back"}
+				_loader.placeStart(Settings.NPCDir, info)
+	return OK
+
+func getActivePalette(parent: Node):
+	var children = parent.get_child_count()
+	for idx in children:
+		var child = parent.get_child(idx)
+		if child.visible == true:
+			return child
+	return 1
diff --git a/export_presets.cfg b/export_presets.cfg
index 1e79336..2c30b68 100644
--- a/export_presets.cfg
+++ b/export_presets.cfg
@@ -60,43 +60,3 @@ Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorActi
 ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
 Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
 Remove-Item -Recurse -Force '{temp_dir}'"
-
-[preset.1]
-
-name="Linux/X11"
-platform="Linux/X11"
-runnable=true
-dedicated_server=false
-custom_features=""
-export_filter="all_resources"
-include_filter=""
-exclude_filter="test/*"
-export_path="../BeretExports/Beret_Linux.x86_64"
-encryption_include_filters=""
-encryption_exclude_filters=""
-encrypt_pck=false
-encrypt_directory=false
-
-[preset.1.options]
-
-custom_template/debug=""
-custom_template/release=""
-debug/export_console_wrapper=1
-binary_format/embed_pck=true
-texture_format/bptc=true
-texture_format/s3tc=true
-texture_format/etc=false
-texture_format/etc2=false
-binary_format/architecture="x86_64"
-ssh_remote_deploy/enabled=false
-ssh_remote_deploy/host="user@host_ip"
-ssh_remote_deploy/port="22"
-ssh_remote_deploy/extra_args_ssh=""
-ssh_remote_deploy/extra_args_scp=""
-ssh_remote_deploy/run_script="#!/usr/bin/env bash
-export DISPLAY=:0
-unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
-\"{temp_dir}/{exe_name}\" {cmd_args}"
-ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
-kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
-rm -rf \"{temp_dir}\""