Skip to content

Commit

Permalink
Working level auto-sizer?
Browse files Browse the repository at this point in the history
The automatic determination for the FEZLVL "Size" parameter was bugging out, causing some triles and AOs to disappear. I think I fixed it...
Also updated the links in the About pane, and started working on a FreeCam mode.
  • Loading branch information
edintomato2 committed Jan 15, 2024
1 parent 76e078c commit 843b583
Show file tree
Hide file tree
Showing 12 changed files with 258 additions and 41 deletions.
1 change: 0 additions & 1 deletion Scenes/Cursor.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,4 @@ speed_scale = 1.25
transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -200, 0, 0)
cull_mask = 1048574
projection = 1
current = true
size = 20.0
8 changes: 6 additions & 2 deletions Scenes/MainScene.tscn
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
[gd_scene load_steps=5 format=3 uid="uid://q6hiwea1m8ok"]
[gd_scene load_steps=6 format=3 uid="uid://q6hiwea1m8ok"]

[ext_resource type="PackedScene" uid="uid://djsig0kkd1ved" path="res://Scenes/Cursor.tscn" id="1_qhvts"]
[ext_resource type="PackedScene" uid="uid://cdwpy8hm6qseq" path="res://Scenes/UI.tscn" id="2_7lqbu"]
[ext_resource type="Environment" uid="uid://ctohsq6knqpup" path="res://Materials/DefaultEnv.tres" id="3_tf75n"]
[ext_resource type="PackedScene" uid="uid://dtgqsmedef7w7" path="res://Scenes/Stopper.tscn" id="4_1q8sn"]
[ext_resource type="Script" path="res://addons/simple-free-look-camera-4-cf0bc21bfd15940b18ec42e3c6cae1ad385284c4/camera.gd" id="5_ad71m"]

[node name="Main" type="Node"]

[node name="UI" parent="." instance=ExtResource("2_7lqbu")]

[node name="Cursor" parent="." instance=ExtResource("1_qhvts")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1)

[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = ExtResource("3_tf75n")

[node name="Stopper" parent="." instance=ExtResource("4_1q8sn")]
visible = false

[node name="DebugCam" type="Camera3D" parent="."]
cull_mask = 1048574
script = ExtResource("5_ad71m")

[connection signal="cursorPos" from="UI" to="Cursor" method="_on_ui_cursor_pos"]
[connection signal="hasMoved" from="Cursor" to="UI" method="_on_cursor_has_moved"]
27 changes: 17 additions & 10 deletions Scenes/UI.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,23 @@ shortcut = SubResource("Shortcut_5p5ho")
text = "View"
flat = false
switch_on_hover = true
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
item_count = 6
popup/item_0/text = "Ortho Cam"
popup/item_0/checkable = 1
popup/item_0/checked = true
popup/item_0/id = 5
popup/item_1/text = "Free Cam"
popup/item_1/checkable = 1
popup/item_1/id = 4
popup/item_2/text = "Hide layers..."
popup/item_2/id = 1
popup/item_3/text = ""
popup/item_3/id = 10
popup/item_3/separator = true
popup/item_4/text = "Debug terminal"
popup/item_4/id = 2
popup/item_5/text = "Raw FEZLVL.JSON"
popup/item_5/id = 3

[node name="Help" type="MenuButton" parent="Titlebar"]
layout_mode = 2
Expand Down
61 changes: 46 additions & 15 deletions Scripts/Exporter/Exporter.gd
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ extends Node
# overwrite with our data.

@onready var _loader = $"../Loader"

var lvlSize = [0, 0, 0]
@onready var _ui = $".."

# Standard definitions. This will get ugly!
var _aoActor = { "Inactive": false, "ContainedTrile": "None", "AttachedGroup": null, "SpinView": "None", "SpinEvery": 0, "SpinOffset": 0, "OffCenter": false, "RotationCenter": [0, 0, 0], "VibrationPattern": [], "CodePattern": [], "Segment": { "Destination": [0, 0, 0], "Duration": 1, "WaitTimeOnStart": 0, "WaitTimeOnFinish": 0, "Acceleration": 0, "Deceleration": 0, "JitterFactor": 0, "Orientation": [0, 0, 0, 1], "CustomData": null }, "NextNode": null, "DestinationLevel": "", "TreasureMapName": "", "InvisibleSides": [], "TimeswitchWindBackSpeed": 0}
Expand Down Expand Up @@ -67,7 +66,7 @@ func _saveFEZLVL(path, filename):
"StartingPoint":
var id = obj.get_meta("Id")
var face = obj.get_meta("Face")
var spDict = { "Id": [id[0], id[1], id[2] - 1], "Face": face}
var spDict = { "Id": [id[0], id[1], id[2]], "Face": face}

template["StartingPosition"] = spDict
pass
Expand All @@ -76,25 +75,57 @@ func _saveFEZLVL(path, filename):
template["TrileSetName"] = _loader.trileset[3].to_upper()

# Find the level's size automatically by finding the most out-there object.
var maxX = _findLargest(template["Triles"], 0)
var maxY = _findLargest(template["Triles"], 1)
var maxZ = _findLargest(template["Triles"], 2)
template["Size"] = [maxX, maxY, maxZ]
## Take into account negative level sizes by applying an offset.
var offset: Array = _findSmallest(template["Triles"])

print("Done writing file. Phew!")
## Apply offset to all trile positions and emplacements
for idx in template["Triles"].size():
template["Triles"][idx]["Emplacement"] = _offset(template["Triles"][idx]["Emplacement"], offset)
template["Triles"][idx]["Position"] = _offset(template["Triles"][idx]["Position"], offset)
pass

## Apply offset to Gomez
var startPos = template.get("StartingPosition")
startPos["Id"] = _startOffset(startPos["Id"], offset)

## Find the level size from here
var lvlSize = _findLargest(template["Triles"])
template["Size"] = lvlSize

var writeLVL := JSON.stringify(template, " ", false, false)

var file = FileAccess.open(path + "/" + filename + ".fezlvl.json", FileAccess.WRITE)
file.store_string(writeLVL)
file.close()
print("Done writing file. Phew!")
_ui.playSound("saved")
pass
pass

func _findLargest(triles, idx: int):
var comparer: int = 1
for trile in triles:
if trile["Position"][idx] > comparer:
comparer = trile["Position"][idx]
pass
return comparer + 1 # Just in case we need some extra space!
func _findLargest(triles):
var comparer := [1, 1, 1]
for idx in range(0,3): # For X, Y, and Z
for trile in triles:
if trile["Emplacement"][idx] > comparer[idx]:
comparer[idx] = trile["Emplacement"][idx]
pass
return comparer.map(func(n): return n + 1) # Just in case we need extra space!

func _findSmallest(triles):
var comparer := [0, 0, 0]
for idx in range(0,3): # For X, Y, and Z
for trile in triles:
if trile["Emplacement"][idx] < comparer[idx]:
comparer[idx] = trile["Emplacement"][idx]
pass
return comparer

func _offset(array: Array, offset: Array):
for idx in range(0,3): # For X, Y, and Z
array[idx] += (abs(offset[idx]))
return array

func _startOffset(startPos, offset: Array):
for pos in range(0,3):
startPos[pos] += (abs(offset[pos]))
return startPos
14 changes: 3 additions & 11 deletions Scripts/Importer/Importer.gd
Original file line number Diff line number Diff line change
Expand Up @@ -220,23 +220,15 @@ func placeStart(dir, posArray):

colShape.radius = 0.05
colBod.shape = colShape
statBod.add_child(colBod)

statBod.call_deferred("add_child", colBod)
gomez.add_child(statBod)

# Figuring out where to place him
var posStr = posArray["Id"]
var face = posArray["Face"]
var adjust: Vector3

match face: # Test with levels to find out where we should place Gomez!
"Front": adjust = Vector3.FORWARD
"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])

gomez.position = pos
gomez.layers = 8
Expand Down
2 changes: 2 additions & 0 deletions Scripts/UI/Titlebar/menuFile.gd
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ extends MenuButton
@onready var _nwFile = $New

@onready var _ldr = $"../../Loader"
@onready var _ui = $"../.."

@export var loadShortcut: Shortcut
@export var saveShortcut: Shortcut
Expand Down Expand Up @@ -46,6 +47,7 @@ func _on_new_file_selected(path: String):
get_popup().set_item_disabled(1, false)
_ldr.killChildren() # Clear out all objects
var trileset = await _ldr.loadObj(cleanPath, 2)
_ui.playSound("loaded")
_ldr.trileset = trileset # Let the importer know we have loaded a new TS
_ldr.loadedTS.emit(trileset)
pass
4 changes: 2 additions & 2 deletions Scripts/UI/Titlebar/menuHelp.gd
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ func _on_help_menu_pressed(id: int):
sfx.stream = soundOK; sfx.play()
match id:
0:
OS.shell_open("https://github.com/FEZModding/FEZRepacker/wiki")
OS.shell_open("https://fezmodding.github.io/wiki/")
1:
OS.shell_open("https://github.com/edintomato2/HARDHAT")
OS.shell_open("https://github.com/edintomato2/Beret")
3:
winAbout.visible = true

Expand Down
7 changes: 7 additions & 0 deletions Scripts/UI/UI.gd
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var onObj = null

@onready var _infoLabel: Label = $"VSplitContainer/Sidebar/SidebarVertical/Position"
@onready var _objLabel: Label = $"VSplitContainer/Sidebar/SidebarVertical/Object"
@onready var _logLabel: RichTextLabel = $"VSplitContainer/Sidebar/SidebarVertical/EditorLog"

@onready var _palettes: Control = $"VSplitContainer/Toolbar/Palettes"

Expand Down Expand Up @@ -52,6 +53,9 @@ func _physics_process(_delta):


func _on_cursor_has_moved(keyPress): # Sounds for movement.
playSound(keyPress)

func playSound(keyPress):
match keyPress:
"move_up", "move_right", "move_up_layer":
_sfx.stream = soundUp; _sfx.play()
Expand All @@ -65,6 +69,9 @@ func _on_cursor_has_moved(keyPress): # Sounds for movement.
_sfx.stream = soundCancel; _sfx.play()
"loaded":
_sfx.stream = soundOK; _sfx.play()
"saved":
_logLabel.append_text("Level saved!")
_sfx.stream = soundOK; _sfx.play()

func _on_loader_new_cur_por(newPos):
emit_signal("cursorPos", newPos)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Copyright 2020 Adam Viola

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Simple Free-Look Camera
A simple 3D 100-line free-look camera for Godot 4.0 that mimics the functionality of the editor's camera for in-game use.

Ported from [Adamviola's Godot 3.2 version](https://github.com/adamviola/simple-free-look-camera).

## Usage
Use **W** and **S** to move forward and backward.

Use **A** and **D** to move left and right.

Use **Q** and **E** to move up and down.

Roll the **scroll wheel** to increase and decrease movement speed.

Press **shift** to move faster, and hold **alt** to move slower.

Hold down the **right mouse button** to rotate the camera.
There's a slider in the editor to control mouse sensitivity.

## Installation
Attach `camera.gd` to your Camera3D node. That's it!

## License
[MIT](https://opensource.org/licenses/MIT).

Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
class_name FreeLookCamera extends Camera3D

# Modifier keys' speed multiplier
const SHIFT_MULTIPLIER = 2.5
const ALT_MULTIPLIER = 1.0 / SHIFT_MULTIPLIER

@export_range(0.0, 1.0) var sensitivity = 0.25

# Mouse state
var _mouse_position = Vector2(0.0, 0.0)
var _total_pitch = 0.0

# Movement state
var _direction = Vector3(0.0, 0.0, 0.0)
var _velocity = Vector3(0.0, 0.0, 0.0)
var _acceleration = 30
var _deceleration = -10
var _vel_multiplier = 4

# Keyboard state
var _w = false
var _s = false
var _a = false
var _d = false
var _q = false
var _e = false
var _shift = false
var _alt = false

func _input(event):
# Receives mouse motion
if event is InputEventMouseMotion:
_mouse_position = event.relative

# Receives mouse button input
if event is InputEventMouseButton:
match event.button_index:
MOUSE_BUTTON_RIGHT: # Only allows rotation if right click down
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED if event.pressed else Input.MOUSE_MODE_VISIBLE)
MOUSE_BUTTON_WHEEL_UP: # Increases max velocity
_vel_multiplier = clamp(_vel_multiplier * 1.1, 0.2, 20)
MOUSE_BUTTON_WHEEL_DOWN: # Decereases max velocity
_vel_multiplier = clamp(_vel_multiplier / 1.1, 0.2, 20)

# Receives key input
if event is InputEventKey:
match event.keycode:
KEY_W:
_w = event.pressed
KEY_S:
_s = event.pressed
KEY_A:
_a = event.pressed
KEY_D:
_d = event.pressed
KEY_Q:
_q = event.pressed
KEY_E:
_e = event.pressed

# Updates mouselook and movement every frame
func _process(delta):
_update_mouselook()
_update_movement(delta)

# Updates camera movement
func _update_movement(delta):
# Computes desired direction from key states
_direction = Vector3((_d as float) - (_a as float),
(_e as float) - (_q as float),
(_s as float) - (_w as float))

# Computes the change in velocity due to desired direction and "drag"
# The "drag" is a constant acceleration on the camera to bring it's velocity to 0
var offset = _direction.normalized() * _acceleration * _vel_multiplier * delta \
+ _velocity.normalized() * _deceleration * _vel_multiplier * delta

# Compute modifiers' speed multiplier
var speed_multi = 1
if _shift: speed_multi *= SHIFT_MULTIPLIER
if _alt: speed_multi *= ALT_MULTIPLIER

# Checks if we should bother translating the camera
if _direction == Vector3.ZERO and offset.length_squared() > _velocity.length_squared():
# Sets the velocity to 0 to prevent jittering due to imperfect deceleration
_velocity = Vector3.ZERO
else:
# Clamps speed to stay within maximum value (_vel_multiplier)
_velocity.x = clamp(_velocity.x + offset.x, -_vel_multiplier, _vel_multiplier)
_velocity.y = clamp(_velocity.y + offset.y, -_vel_multiplier, _vel_multiplier)
_velocity.z = clamp(_velocity.z + offset.z, -_vel_multiplier, _vel_multiplier)

translate(_velocity * delta * speed_multi)

# Updates mouse look
func _update_mouselook():
# Only rotates mouse if the mouse is captured
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
_mouse_position *= sensitivity
var yaw = _mouse_position.x
var pitch = _mouse_position.y
_mouse_position = Vector2(0, 0)

# Prevents looking up/down too far
pitch = clamp(pitch, -90 - _total_pitch, 90 - _total_pitch)
_total_pitch += pitch

rotate_y(deg_to_rad(-yaw))
rotate_object_local(Vector3(1,0,0), deg_to_rad(-pitch))
Loading

0 comments on commit 843b583

Please sign in to comment.