Compare commits

..

1 Commits

Author SHA1 Message Date
Nilton Constantino
bfd4e450e1
some adjustments on stage editor 2026-06-15 17:48:18 +01:00
59 changed files with 2907 additions and 19811 deletions

View File

@ -1,18 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f70bf8524ee54f76ba35bd5c28995d83, type: 3}
m_Name: Prefab Table
m_EditorClassIdentifier: Assembly-CSharp-Editor::Editor.GardensStageEditor.PrefabTable
groundSlabPrefab: {fileID: 4088177062756800262, guid: 761db1bde191e401fa6ec87acd053bbf, type: 3}
groundRampFrontPrefab: {fileID: 116909126457648545, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
groundRampLeftPrefab: {fileID: 1762350532007512996, guid: 378324f09bdf84db99e602efb4b23fa3, type: 3}
groundRampRightPrefab: {fileID: 778490509801794073, guid: d5e0f7c6e96fe4425a061863751bc639, type: 3}

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: ef963f234702846efa75432cf0bb519f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -5,34 +5,18 @@ using UnityEngine;
namespace __Prototype.Scripts namespace __Prototype.Scripts
{ {
public class TestGroundMorion : GroundProfileMotionBehaviour public class TestGroundMorion : GroundProfileMotion
{ {
[GroupConfigurations, SerializeField] private Vector3 localDirection = Vector3.right; [GroupConfigurations, SerializeField] private Vector3 localDirection = Vector3.right;
[GroupConfigurations, SerializeField] private float speed = 2f; [GroupConfigurations, SerializeField] private float speed = 2f;
[GroupConfigurations, SerializeField] private float maxDistance = 4f; [GroupConfigurations, SerializeField] private float maxDistance = 4f;
[GroupConfigurations, SerializeField] private bool pingPong = true; [GroupConfigurations, SerializeField] private bool pingPong = true;
[GroupConfigurations, SerializeField] private bool moveOnStart; [GroupConfigurations, SerializeField] private bool moveOnStart;
public Vector3 Velocity public override Vector3 Velocity { get; protected set; }
{ public override Vector3 DeltaPosition { get; protected set; }
get => GroundProfileMotion.Velocity; public override bool IsMoving { get; protected set; }
private set => GroundProfileMotion.Velocity = value; public override bool IsStatic { get; protected set; } = false;
}
public Vector3 DeltaPosition
{
get => GroundProfileMotion.DeltaPosition;
private set => GroundProfileMotion.DeltaPosition = value;
}
public bool IsMoving
{
get => GroundProfileMotion.IsMoving;
private set => GroundProfileMotion.IsMoving = value;
}
public bool IsStatic
{
get => GroundProfileMotion.IsStatic;
private set => GroundProfileMotion.IsStatic = value;
}
private Vector3 _startPosition; private Vector3 _startPosition;
private Vector3 _lastPosition; private Vector3 _lastPosition;
@ -85,7 +69,7 @@ namespace __Prototype.Scripts
} }
else else
{ {
next = _startPosition + worldDirection * (Mathf.Sign(distanceFromStart) * maxDistance); next = _startPosition + worldDirection * Mathf.Sign(distanceFromStart) * maxDistance;
Stop(); Stop();
} }
} }

View File

@ -0,0 +1,22 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 778f9d79eb2c410482efdc25b248dd46, type: 3}
m_Name: StageDefinition
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Prototyping.StageDefinition
stageId: stagedefinition
cellSize: 1
floorHeight: 6
activeFloorIndex: 0
floors:
- floorId: F0
cells: []
objects: []

File diff suppressed because it is too large Load Diff

View File

@ -1,63 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &1867437227332939269
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 2829319849928503959, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_Mesh
value:
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071068
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalRotation.y
value: -0.7071068
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: -90
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9140983697215042600, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_Name
value: Ground_Ramp_Left_Prototype
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 378324f09bdf84db99e602efb4b23fa3
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -8,14 +8,6 @@ PrefabInstance:
serializedVersion: 3 serializedVersion: 3
m_TransformParent: {fileID: 0} m_TransformParent: {fileID: 0}
m_Modifications: m_Modifications:
- target: {fileID: 101776470001583037, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: movementProfiles.Array.size
value: 1
objectReference: {fileID: 0}
- target: {fileID: 101776470001583037, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: 'movementProfiles.Array.data[0]'
value:
objectReference: {fileID: 5801231790879681971}
- target: {fileID: 221717111884494654, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3} - target: {fileID: 221717111884494654, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_Mesh propertyPath: m_Mesh
value: value:
@ -98,7 +90,7 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6524376507900539265, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3} - target: {fileID: 6524376507900539265, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_Name propertyPath: m_Name
value: Ground_Ramp_Front_Prototype value: Ground_Ramp_Prototype
objectReference: {fileID: 0} objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
@ -107,9 +99,6 @@ PrefabInstance:
- targetCorrespondingSourceObject: {fileID: 6524376507900539265, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3} - targetCorrespondingSourceObject: {fileID: 6524376507900539265, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
insertIndex: -1 insertIndex: -1
addedObject: {fileID: 116909126457648545} addedObject: {fileID: 116909126457648545}
- targetCorrespondingSourceObject: {fileID: 6524376507900539265, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
insertIndex: -1
addedObject: {fileID: 5801231790879681971}
m_SourcePrefab: {fileID: 100100000, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3} m_SourcePrefab: {fileID: 100100000, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
--- !u!114 &2719093777726527478 stripped --- !u!114 &2719093777726527478 stripped
MonoBehaviour: MonoBehaviour:
@ -145,23 +134,3 @@ MonoBehaviour:
sizeZ: 1 sizeZ: 1
x: 1 x: 1
z: 1 z: 1
--- !u!114 &5801231790879681971
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9140983697215042600}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bdd4ad30e2d149b58a2f84fa9a5b5fbc, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Core.Grounding.GroundProfileMovementBehaviour
id: 9d7dfeaecb7e4204ba7dd29dede5075d
groundProfileMovement:
speedMultiplier: 1
accelerationMultiplier: 1
decelerationMultiplier: 1
uphillSpeedMultiplier: 0.75
downhillSpeedMultiplier: 1
sidewaysSpeedMultiplier: 0.9

View File

@ -1,63 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &815882455729688504
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 2829319849928503959, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_Mesh
value:
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071068
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalRotation.y
value: 0.7071068
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 90
objectReference: {fileID: 0}
- target: {fileID: 4113289733881740216, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9140983697215042600, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}
propertyPath: m_Name
value: Ground_Ramp_Right_Prototype
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 321f39f98806c4db7a3deff6d508bde1, type: 3}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: d5e0f7c6e96fe4425a061863751bc639
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,171 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &3530962555909840662
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 101776470001583037, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: movementProfiles.Array.size
value: 1
objectReference: {fileID: 0}
- target: {fileID: 101776470001583037, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: 'movementProfiles.Array.data[0]'
value:
objectReference: {fileID: 1964621128587179894}
- target: {fileID: 221717111884494654, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_Mesh
value:
objectReference: {fileID: 0}
- target: {fileID: 2109134711161568785, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2109134711161568785, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2109134711161568785, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2109134711161568785, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2109134711161568785, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2109134711161568785, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2109134711161568785, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2109134711161568785, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2109134711161568785, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2109134711161568785, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3352223124200162652, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3352223124200162652, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalPosition.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3352223124200162652, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4990331727855981778, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalRotation.w
value: 0.9238795
objectReference: {fileID: 0}
- target: {fileID: 4990331727855981778, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalRotation.x
value: -0.38268346
objectReference: {fileID: 0}
- target: {fileID: 4990331727855981778, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4990331727855981778, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6392326082573612157, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_Size.y
value: 0.05
objectReference: {fileID: 0}
- target: {fileID: 6392326082573612157, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_Size.z
value: 1.4142
objectReference: {fileID: 0}
- target: {fileID: 6392326082573612157, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_Center.y
value: -0.025
objectReference: {fileID: 0}
- target: {fileID: 6524376507900539265, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
propertyPath: m_Name
value: Ground_Stair_Front_Prototype
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 6524376507900539265, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
insertIndex: -1
addedObject: {fileID: 2575929596551944822}
- targetCorrespondingSourceObject: {fileID: 6524376507900539265, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
insertIndex: -1
addedObject: {fileID: 1964621128587179894}
m_SourcePrefab: {fileID: 100100000, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
--- !u!114 &3525235759526726985 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 138583005792719455, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
m_PrefabInstance: {fileID: 3530962555909840662}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f20bd3bb11c64d00a0429af5fe4bd33f, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Prototyping.PrototypeModel
--- !u!1 &7749360569717010071 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 6524376507900539265, guid: 84ef2ec4df393420d973aa876a8778b6, type: 3}
m_PrefabInstance: {fileID: 3530962555909840662}
m_PrefabAsset: {fileID: 0}
--- !u!114 &2575929596551944822
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7749360569717010071}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3a3b1270c87c4456bdc61721ca19132f, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Prototyping.GroundStairModelPrototype
displayDebug: 1
prototypeModel: {fileID: 3525235759526726985}
sizeX: 1
sizeZ: 1
x: 1
z: 1
--- !u!114 &1964621128587179894
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7749360569717010071}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bdd4ad30e2d149b58a2f84fa9a5b5fbc, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Core.Grounding.GroundProfileMovementBehaviour
id: afbca706aa91413387e401bb77925f70
groundProfileMovement:
speedMultiplier: 1
accelerationMultiplier: 1
decelerationMultiplier: 1
uphillSpeedMultiplier: 0.5
downhillSpeedMultiplier: 1
sidewaysSpeedMultiplier: 0.9

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: da66eef8ff1ce4c3eaf46c09ad26e70b
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,63 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &3382806052188099058
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071068
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalRotation.y
value: -0.7071068
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: -90
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3608453355090094120, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_Mesh
value:
objectReference: {fileID: 0}
- target: {fileID: 7749360569717010071, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_Name
value: Ground_Stair_Left_Prototype
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: c11973af2c21642658a917c1253a53f4
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,63 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &8988140421347768202
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071068
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalRotation.y
value: 0.7071068
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 90
objectReference: {fileID: 0}
- target: {fileID: 3190054200416215303, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3608453355090094120, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_Mesh
value:
objectReference: {fileID: 0}
- target: {fileID: 7749360569717010071, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}
propertyPath: m_Name
value: Ground_Stair_Right_Prototype
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: da66eef8ff1ce4c3eaf46c09ad26e70b, type: 3}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 3e0d56cfe99b4417a8f7c924adc9581e
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -10,31 +10,23 @@ PrefabInstance:
m_Modifications: m_Modifications:
- target: {fileID: 369205274101430871, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3} - target: {fileID: 369205274101430871, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3}
propertyPath: m_LocalPosition.y propertyPath: m_LocalPosition.y
value: 1.5 value: 0.5
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3020532133659471693, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3} - target: {fileID: 3020532133659471693, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3}
propertyPath: m_Size.x propertyPath: m_Size.x
value: 3 value: 2
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3020532133659471693, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3} - target: {fileID: 3020532133659471693, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3}
propertyPath: m_Size.y propertyPath: m_Size.y
value: 3 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3020532133659471693, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3} - target: {fileID: 3020532133659471693, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3}
propertyPath: m_Size.z propertyPath: m_Size.z
value: 3.5 value: 2
objectReference: {fileID: 0}
- target: {fileID: 3020532133659471693, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3}
propertyPath: m_Center.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3020532133659471693, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3}
propertyPath: m_Center.z
value: 0.25
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 5094209182163755379, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3} - target: {fileID: 5094209182163755379, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3}
propertyPath: m_Enabled propertyPath: m_Enabled
value: 1 value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6166895172714925370, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3} - target: {fileID: 6166895172714925370, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3}
propertyPath: m_Mesh propertyPath: m_Mesh
@ -82,7 +74,7 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8449749668273782584, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3} - target: {fileID: 8449749668273782584, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3}
propertyPath: m_Name propertyPath: m_Name
value: Obstacle_Wall_Prototype value: Obstacle_Cube_Prototype
objectReference: {fileID: 0} objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
@ -109,18 +101,16 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: ccf30362a82f4d67958b61569d4cf1b4, type: 3} m_Script: {fileID: 11500000, guid: ccf30362a82f4d67958b61569d4cf1b4, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Prototyping.ContactCubeModelPrototype m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Prototyping.ContactCubeModelPrototype
displayDebug: 1 displayDebug: 0
prototypeModel: {fileID: 8402728050198132523} prototypeModel: {fileID: 8402728050198132523}
sizeX: 1 sizeX: 1
sizeY: 3 sizeY: 1
sizeZ: 1 sizeZ: 1
offset_x: {x: 1, y: 1} offset: 1
offset_y: {x: 1.5, y: 1}
x: 1 x: 1
y: 3 y: 1
z: 1 z: 1
contact_offset_x: {x: 1, y: 1} contact_offset: 1
contact_offset_y: {x: 1.5, y: 1}
--- !u!114 &8402728050198132523 stripped --- !u!114 &8402728050198132523 stripped
MonoBehaviour: MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 3563105585321411375, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3} m_CorrespondingSourceObject: {fileID: 3563105585321411375, guid: 64620cfd283d648b5b4d9c9a4fac7751, type: 3}

File diff suppressed because one or more lines are too long

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: e6846a45a2ff48599d8e2a83e5a5d0e3
timeCreated: 1781601092

View File

@ -1,75 +0,0 @@
using System;
using Intrepid.Diagnostics;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Editor.GardensStageEditor.Baker
{
namespace Editor.GardensStageEditor
{
public static class StageBaker
{
private const string GeneratedRootName = "Generated";
public static GameObject Bake(StageDefinition stage, PrefabTable prefabTable)
{
if (stage.IsNull())
{
DLogger.LogWarn("Cannot bake: no StageDefinition selected.");
return null;
}
stage.EnsureDefaults();
var scene = SceneManager.GetActiveScene();
var generatedRoot = EnsureGeneratedRoot(scene);
Undo.RegisterCreatedObjectUndo(generatedRoot, "Create Generated Root");
var stageRoot = EnsureStageRoot(stage, generatedRoot);
StageBuilder.BuildStage(new StageBuilderRequest
{
Stage = stage,
Root = stageRoot,
PrefabTable = prefabTable
});
Undo.RegisterCreatedObjectUndo(stageRoot, "Create Stage Root");
EditorSceneManager.MarkSceneDirty(scene);
Selection.activeGameObject = stageRoot;
DLogger.LogDebug($"Bake started for stage '{stage.Id}'. State root is ready.");
return stageRoot;
}
private static GameObject EnsureStageRoot(StageDefinition stage, GameObject generatedRoot)
{
foreach (Transform goTransform in generatedRoot.transform)
{
if (goTransform.gameObject.name == stage.Id)
{
goTransform.gameObject.name = $"{goTransform.gameObject.name}_bkp";
goTransform.gameObject.SetActive(false);
}
}
var go = new GameObject(stage.Id);
go.transform.SetParent(generatedRoot.transform);
return go;
}
private static GameObject EnsureGeneratedRoot(Scene scene)
{
foreach (var gameObject in scene.GetRootGameObjects())
{
if (gameObject.name == GeneratedRootName)
{
return gameObject;
}
}
return new GameObject(GeneratedRootName);
}
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 3e84387a0ce04c489edeca68df66e1c4
timeCreated: 1781549085

View File

@ -1,135 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Intrepid.Diagnostics;
using Intrepid.Gameplay.Prototyping;
using UnityEditor;
using UnityEngine;
namespace Editor.GardensStageEditor.Baker
{
public struct StageBuilderRequest
{
public StageDefinition Stage { get; set; }
public GameObject Root { get; set; }
public PrefabTable PrefabTable { get; set; }
}
public static class StageBuilder
{
public static void BuildStage(StageBuilderRequest request)
{
foreach (var stageFloorDefinition in request.Stage.floors)
{
var cellsGS = new HashSet<Vector2Int>();
var cellsGRF = new HashSet<Vector2Int>();
var cellsGRR = new HashSet<Vector2Int>();
var cellsGRL = new HashSet<Vector2Int>();
foreach (var logicalCell in stageFloorDefinition.Cells)
{
switch (logicalCell.structural)
{
case StructuralCellKind.Empty:
break;
case StructuralCellKind.Ground_Slab:
cellsGS.Add(new Vector2Int(logicalCell.x, logicalCell.y));
break;
case StructuralCellKind.Ground_Ramp_Front:
cellsGRF.Add(new Vector2Int(logicalCell.x, logicalCell.y));
break;
case StructuralCellKind.Ground_Ramp_Left:
cellsGRL.Add(new Vector2Int(logicalCell.x, logicalCell.y));
break;
case StructuralCellKind.Ground_Ramp_Right:
cellsGRR.Add(new Vector2Int(logicalCell.x, logicalCell.y));
break;
case StructuralCellKind.Wall:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
var floorRootTransform = new GameObject(stageFloorDefinition.floorId)
{
transform =
{
parent = request.Root.transform,
position = new Vector3(0, stageFloorDefinition.FloorHeight, 0)
}
}.transform;
InstantiateGround(
request.PrefabTable.GroundSlabPrefab,
floorRootTransform,
cellsGS,
StraightAddressSize
);
InstantiateGround(
request.PrefabTable.GroundRampFrontPrefab,
floorRootTransform,
cellsGRF,
StraightAddressSize
);
InstantiateGround(
request.PrefabTable.GroundRampLeftPrefab,
floorRootTransform,
cellsGRL,
InverseAddressSize
);
InstantiateGround(
request.PrefabTable.GroundRampRightPrefab,
floorRootTransform,
cellsGRR,
InverseAddressSize
);
}
}
private static Vector2Int StraightAddressSize(RectInt rect)
{
return new Vector2Int(rect.width, rect.height);
}
private static Vector2Int InverseAddressSize(RectInt rect)
{
return new Vector2Int(rect.height, rect.width);
}
private static void InstantiateGround<G>(
G prefab, Transform parent,
HashSet<Vector2Int> set,
Func<RectInt, Vector2Int> addressSize
) where G: GroundModelPrototype
{
var releaseName = new string(typeof(G).Name.Where(char.IsUpper).ToArray());
if (prefab.IsNull())
{
DLogger.LogError($"Prefab is not configured in PrefabTable: {releaseName}");
return;
}
foreach (var rect in StageBuilderHelpers.BuildRectanglesFromCellsBest(set))
{
if (PrefabUtility.InstantiatePrefab(prefab, parent) is not G g)
{
DLogger.LogError($"Failed to instantiate prefab: {prefab.name}");
continue;
}
StageBuilderHelpers.ResetTransform(g.transform);
g.name = $"{releaseName} ({rect.x}, {rect.y}) {rect.width}x{rect.height}";
g.transform.localPosition = new Vector3(
rect.x + (rect.width - 1) * 0.5f,
0,
-(rect.y + (rect.height - 1) * 0.5f)
);
g.SetSize(addressSize(rect));
}
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 571d9dd73a024147b211247e52b60a2a
timeCreated: 1781593722

View File

@ -1,153 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
namespace Editor.GardensStageEditor.Baker
{
public static class StageBuilderHelpers
{
public static void ResetTransform(Transform transform)
{
// transform.rotation = Quaternion.identity;
transform.localScale = Vector3.one;
}
public static List<RectInt> BuildRectanglesFromCellsBest(HashSet<Vector2Int> cells)
{
var result = new List<RectInt>();
var remaining = new HashSet<Vector2Int>(cells);
while (remaining.Count > 0)
{
var rect = FindLargestRectGlobal(remaining);
result.Add(rect);
RemoveRectCells(rect, remaining);
}
return result;
}
public static List<RectInt> BuildRectanglesFromCells(HashSet<Vector2Int> cells)
{
var result = new List<RectInt>();
var remaining = new HashSet<Vector2Int>(cells);
while (remaining.Count > 0)
{
var start = FindTopLeftMostCell(remaining);
var rect = FindBestRectFromStart(start, remaining);
result.Add(rect);
RemoveRectCells(rect, remaining);
}
return result;
}
private static RectInt FindLargestRectGlobal(HashSet<Vector2Int> remaining)
{
var best = new RectInt();
var bestArea = 0;
foreach (var cell in remaining)
{
var rect = FindBestRectFromStart(cell, remaining);
var area = rect.width * rect.height;
if (area > bestArea)
{
best = rect;
bestArea = area;
}
}
return best;
}
private static RectInt FindBestRectFromStart(Vector2Int start, HashSet<Vector2Int> remaining)
{
var bestWidth = 1;
var bestHeight = 1;
var bestArea = 1;
var currentMinWidth = int.MaxValue;
var height = 0;
while (true)
{
var rowWidth = FindRowWidth(start.x, start.y + height, remaining);
if (rowWidth == 0)
{
break;
}
currentMinWidth = Mathf.Min(currentMinWidth, rowWidth);
height++;
var area = currentMinWidth * height;
if (area > bestArea)
{
bestArea = area;
bestWidth = currentMinWidth;
bestHeight = height;
}
}
return new RectInt(start.x, start.y, bestWidth, bestHeight);
}
private static int FindRowWidth(int x, int y, HashSet<Vector2Int> remaining)
{
var width = 0;
while (remaining.Contains(new Vector2Int(x + width, y)))
{
width++;
}
return width;
}
private static Vector2Int FindTopLeftMostCell(HashSet<Vector2Int> cells)
{
var found = false;
var best = Vector2Int.zero;
foreach (var cell in cells)
{
if (!found)
{
best = cell;
found = true;
continue;
}
if (cell.y < best.y)
{
best = cell;
continue;
}
if (cell.y == best.y && cell.x < best.x)
{
best = cell;
}
}
return best;
}
private static void RemoveRectCells(RectInt rect, HashSet<Vector2Int> remaining)
{
for (var y = rect.yMin; y < rect.yMax; y++)
{
for (var x = rect.xMin; x < rect.xMax; x++)
{
remaining.Remove(new Vector2Int(x, y));
}
}
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: b3cf864dedfb4a929e087eba87cfd7f5
timeCreated: 1781598891

View File

@ -1,20 +0,0 @@
using Intrepid.Gameplay.Prototyping;
using Intrepid.Utilities;
using UnityEngine;
namespace Editor.GardensStageEditor
{
[CreateAssetMenu(fileName = "New Prefab Table", menuName = "GON/Editor/Prefab Table")]
public class PrefabTable : ScriptableObject
{
[GroupInjections, SerializeField] private GroundSlabModelPrototype groundSlabPrefab;
[GroupInjections, SerializeField] private GroundRampModelPrototype groundRampFrontPrefab;
[GroupInjections, SerializeField] private GroundRampModelPrototype groundRampLeftPrefab;
[GroupInjections, SerializeField] private GroundRampModelPrototype groundRampRightPrefab;
public GroundSlabModelPrototype GroundSlabPrefab => groundSlabPrefab;
public GroundRampModelPrototype GroundRampFrontPrefab => groundRampFrontPrefab;
public GroundRampModelPrototype GroundRampLeftPrefab => groundRampLeftPrefab;
public GroundRampModelPrototype GroundRampRightPrefab => groundRampRightPrefab;
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: f70bf8524ee54f76ba35bd5c28995d83
timeCreated: 1781596138

View File

@ -0,0 +1,109 @@
# Gardens Stage Editor Starter Kit
Starter kit para um editor lógico de stages do **Gardens of Nil** dentro da Unity.
Este pacote contém somente:
- modelo de dados (`StageDefinition`, floors, células estruturais e objetos lógicos);
- janela de editor com UI Toolkit;
- grid 1x1 com pan/zoom;
- paleta por layer;
- criação/seleção/remoção de elementos lógicos;
- inspector simples;
- validação básica.
Não contém bake/rebake de scene, geração de colliders ou integração com Tiled.
## Instalação
Descompacte a pasta `GardensStageEditor` dentro de:
```txt
Assets/Editor/
```
O resultado deve ficar parecido com:
```txt
Assets/Editor/GardensStageEditor/
Data/
Editor/
README.md
```
Depois espere a Unity recompilar.
## Abrir o editor
Na Unity:
```txt
Gardens > Stage Editor
```
Na janela:
1. Clique em `New` para criar um `StageDefinition.asset`.
2. Escolha a layer na paleta inferior.
3. Use `Paint`, `Select`, `Erase` ou `Pan`.
4. Pinte o mapa lógico no canvas central.
5. Edite o elemento selecionado no inspector à direita.
6. Use `Validate` para checagens básicas.
## Controles
```txt
LMB: pintar / selecionar
RMB ou MMB: pan
Mouse wheel: zoom
```
## Modelo mental
O editor trabalha em um plano lógico 2D:
```txt
Editor X/Y
```
Mais tarde, o baker pode mapear isso para o mundo Unity:
```txt
Editor X -> Unity X
Editor Y -> Unity Z
Floor index -> Unity Y offset
```
## Layers iniciais
```txt
Structural: Ground, Wall, Hole, Erase Structural
Design: Falling Floor, Door, Interactable, Portal
Camera: Camera Zone
Markers: Player Spawn, Elevator, Marker
```
## Filosofia
A scene não é fonte da verdade.
```txt
StageDefinition.asset = source of truth
Generated scene/prefab = output futuro do baker
```
Este pacote só cuida do primeiro lado: autoria visual e dados lógicos.
## Próximos passos sugeridos
1. Transformar `StagePaletteEntry` em assets configuráveis, se necessário.
2. Adicionar hotkeys e melhor seleção/move/resize visual.
3. Adicionar overlays de erro no canvas.
4. Implementar o baker separado consumindo `StageDefinition`.
5. Depois, se fizer sentido, criar import/export Tiled apenas para o mapa lógico.
## Requisitos recomendados
Unity 2022.3 LTS ou superior. Unity 6 também deve funcionar.
O canvas usa UI Toolkit custom drawing (`Painter2D`). Em versões muito antigas da Unity, pode ser necessário trocar o canvas por IMGUI ou SceneView Handles.

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 494fb84451f94e218111409283a7f795
timeCreated: 1781500522

View File

@ -0,0 +1,71 @@
# Stage Model Notes
## StageDefinition
Fonte da verdade do stage lógico.
Contém:
- `stageId`
- `cellSize`
- `floorHeight`
- `floors`
- `objects`
## StageFloorDefinition
Um andar lógico do stage.
Contém:
- `floorId`
- `width`
- `height`
- células estruturais preenchidas
Células vazias não são serializadas explicitamente. Apenas células com `Ground`, `Wall` ou `Hole` são guardadas.
## Structural cells
A layer estrutural é cell-based.
```txt
Empty
Ground
Wall
Hole
```
## StageObjectDefinition
Objetos lógicos são object-based.
Exemplos:
- traps
- doors
- interactables
- portals
- camera zones
- spawn points
- elevators
- markers
Cada objeto tem:
- `id`
- `layer`
- `kind`
- `typeId`
- `prefabId`
- `floorId`
- `x`, `y`, `width`, `height`
- flags como `cutsGround` e `blocksMovement`
## Regra sugerida para bake futuro
```txt
GroundCollision = Structural.Ground - Structural.Hole - Objects(cutsGround)
```
Depois o baker pode compactar células em BoxColliders maiores.

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ffb9c2df7a0f4b3ca08544979287cf20
timeCreated: 1781500522

View File

@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Intrepid.Utilities;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine; using UnityEngine;
namespace Editor.GardensStageEditor namespace Editor.GardensStageEditor
@ -17,35 +15,27 @@ namespace Editor.GardensStageEditor
public enum StructuralCellKind public enum StructuralCellKind
{ {
Empty = 0, Empty = 0,
Ground_Slab = 10, Ground = 1,
Ground_Ramp_Front = 11, Wall = 2
Ground_Ramp_Left = 12,
Ground_Ramp_Right = 13,
Wall = 20,
} }
public enum StageObjectKind public enum StageObjectKind
{ {
Trap_FallingFloor = 0, Trap = 0,
Door = 1,
DoorHorizontal = 10, Interactable = 2,
DoorVertical = 11, Portal = 3,
CameraZone = 4,
// Interactable = 2, Spawn = 5,
// Portal = 3, Elevator = 6,
Marker = 7,
CameraBoundary = 40, Custom = 100
Spawn = 50,
// Elevator = 6,
// Marker = 7,
// Custom = 100
} }
[CreateAssetMenu(menuName = "GON/Editor/Stage Definition", fileName = "StageDefinition")] [CreateAssetMenu(menuName = "GON/Editor/Stage Definition", fileName = "StageDefinition")]
public sealed class StageDefinition : SOIdentification public sealed class StageDefinition : ScriptableObject
{ {
public string stageId = "stage_new";
public float cellSize = 1f; public float cellSize = 1f;
public float floorHeight = 6f; public float floorHeight = 6f;
public int activeFloorIndex; public int activeFloorIndex;
@ -104,7 +94,7 @@ namespace Editor.GardensStageEditor
public bool ContainsFloor(string floorId) public bool ContainsFloor(string floorId)
{ {
return GetFloor(floorId) is not null; return GetFloor(floorId) != null;
} }
public string CreateUniqueObjectId(StageObjectKind kind) public string CreateUniqueObjectId(StageObjectKind kind)
@ -140,8 +130,7 @@ namespace Editor.GardensStageEditor
public sealed class StageFloorDefinition public sealed class StageFloorDefinition
{ {
public string floorId = "F0"; public string floorId = "F0";
public float FloorHeight;
[SerializeField] [SerializeField]
private List<LogicalCell> cells = new(); private List<LogicalCell> cells = new();
@ -162,7 +151,7 @@ namespace Editor.GardensStageEditor
public StructuralCellKind GetCell(int x, int y) public StructuralCellKind GetCell(int x, int y)
{ {
var index = FindCellIndex(x, y); int index = FindCellIndex(x, y);
if (index < 0) if (index < 0)
{ {
return StructuralCellKind.Empty; return StructuralCellKind.Empty;
@ -184,7 +173,7 @@ namespace Editor.GardensStageEditor
return; return;
} }
var cell = new LogicalCell LogicalCell cell = new LogicalCell
{ {
x = x, x = x,
y = y, y = y,
@ -280,11 +269,6 @@ namespace Editor.GardensStageEditor
public bool blocksMovement; public bool blocksMovement;
public string notes; public string notes;
public bool IsResizable => IsKindResizable(kind);
public Vector2Int DefaultSize => GetDefaultSize(kind);
public Vector2Int MinSize => GetMinSize(kind);
public Vector2Int MaxSize => GetMaxSize(kind);
public RectInt Bounds => new(x, y, Mathf.Max(1, width), Mathf.Max(1, height)); public RectInt Bounds => new(x, y, Mathf.Max(1, width), Mathf.Max(1, height));
public bool ContainsCell(int cellX, int cellY) public bool ContainsCell(int cellX, int cellY)
@ -292,62 +276,5 @@ namespace Editor.GardensStageEditor
var bounds = Bounds; var bounds = Bounds;
return cellX >= bounds.xMin && cellX < bounds.xMax && cellY >= bounds.yMin && cellY < bounds.yMax; return cellX >= bounds.xMin && cellX < bounds.xMax && cellY >= bounds.yMin && cellY < bounds.yMax;
} }
public void NormalizeSize()
{
if (!IsResizable)
{
var fixedSize = DefaultSize;
width = Mathf.Max(1, fixedSize.x);
height = Mathf.Max(1, fixedSize.y);
return;
}
var min = MinSize;
var max = MaxSize;
width = Mathf.Clamp(Mathf.Max(1, width), Mathf.Max(1, min.x), Mathf.Max(1, max.x));
height = Mathf.Clamp(Mathf.Max(1, height), Mathf.Max(1, min.y), Mathf.Max(1, max.y));
}
public static bool IsKindResizable(StageObjectKind kind)
{
return kind switch
{
StageObjectKind.Trap_FallingFloor => true,
StageObjectKind.CameraBoundary => true,
_ => false
};
}
public static Vector2Int GetDefaultSize(StageObjectKind kind)
{
return kind switch
{
StageObjectKind.Trap_FallingFloor => 2 * Vector2Int.one,
StageObjectKind.DoorVertical => new Vector2Int(1, 2),
StageObjectKind.DoorHorizontal => new Vector2Int(2, 1),
StageObjectKind.CameraBoundary => new Vector2Int(8, 5),
_ => Vector2Int.one
};
}
public static Vector2Int GetMinSize(StageObjectKind kind)
{
return kind switch
{
StageObjectKind.CameraBoundary => new Vector2Int(1, 1),
_ => GetDefaultSize(kind)
};
}
public static Vector2Int GetMaxSize(StageObjectKind kind)
{
return kind switch
{
StageObjectKind.Trap_FallingFloor => new Vector2Int(64, 64),
StageObjectKind.CameraBoundary => new Vector2Int(64, 64),
_ => GetDefaultSize(kind)
};
}
} }
} }

View File

@ -1,4 +1,3 @@
using Intrepid.Diagnostics;
using UnityEngine; using UnityEngine;
namespace Editor.GardensStageEditor namespace Editor.GardensStageEditor
@ -13,26 +12,12 @@ namespace Editor.GardensStageEditor
public static readonly Color PreviewStroke = new(1f, 1f, 1f, 0.9f); public static readonly Color PreviewStroke = new(1f, 1f, 1f, 0.9f);
public static readonly Color SelectionStroke = new(1f, 0.85f, 0.25f, 1f); public static readonly Color SelectionStroke = new(1f, 0.85f, 0.25f, 1f);
public static Color FromHtml(string html)
{
if (!html.StartsWith("#")) html = $"#{html}";
if (ColorUtility.TryParseHtmlString(html, out var color))
{
return color;
}
DLogger.LogDebug("color not supported");
return Color.magenta;
}
public static Color Structural(StructuralCellKind kind) public static Color Structural(StructuralCellKind kind)
{ {
return kind switch return kind switch
{ {
StructuralCellKind.Ground_Slab => FromHtml("55E0FF"), StructuralCellKind.Ground => new Color(0.28f, 0.52f, 0.35f, 0.8f),
StructuralCellKind.Ground_Ramp_Front => FromHtml("55E0FF"), StructuralCellKind.Wall => new Color(0.38f, 0.38f, 0.42f, 0.9f),
StructuralCellKind.Ground_Ramp_Left => FromHtml("55E0FF"),
StructuralCellKind.Ground_Ramp_Right => FromHtml("55E0FF"),
StructuralCellKind.Wall => FromHtml("668B93"),
_ => new Color(0f, 0f, 0f, 0f) _ => new Color(0f, 0f, 0f, 0f)
}; };
} }

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using Intrepid.Gameplay.Prototyping;
using Editor.GardensStageEditor.Baker.Editor.GardensStageEditor;
using UnityEditor; using UnityEditor;
using UnityEditor.UIElements; using UnityEditor.UIElements;
using UnityEngine; using UnityEngine;
@ -11,7 +9,6 @@ namespace Editor.GardensStageEditor
{ {
public sealed class StageEditorWindow : EditorWindow public sealed class StageEditorWindow : EditorWindow
{ {
private PrefabTable prefabTable;
private StageDefinition stage; private StageDefinition stage;
private StageEditorState state; private StageEditorState state;
private List<StagePaletteEntry> palette; private List<StagePaletteEntry> palette;
@ -20,7 +17,6 @@ namespace Editor.GardensStageEditor
private StageMapCanvas canvas; private StageMapCanvas canvas;
private StageInspectorPanel inspector; private StageInspectorPanel inspector;
private StagePalettePanel palettePanel; private StagePalettePanel palettePanel;
private Label mouseCellLabel;
[MenuItem("Tools/Gardens Of Nil/Stage Editor")] [MenuItem("Tools/Gardens Of Nil/Stage Editor")]
public static void Open() public static void Open()
@ -95,7 +91,7 @@ namespace Editor.GardensStageEditor
RebuildTopBar(); RebuildTopBar();
} }
public void MutateStage(string undoName, Action mutation) public void MutateStage(string undoName, System.Action mutation)
{ {
if (stage is null || mutation is null) if (stage is null || mutation is null)
{ {
@ -122,21 +118,6 @@ namespace Editor.GardensStageEditor
} }
topBar.Clear(); topBar.Clear();
var prefabTableField = new ObjectField("Prefab Table")
{
objectType = typeof(PrefabTable),
value = prefabTable,
style =
{
minWidth = 200
}
};
prefabTableField.RegisterValueChangedCallback(evt =>
{
SetPrefabTable(evt.newValue as PrefabTable);
});
topBar.Add(prefabTableField);
var stageField = new ObjectField("Stage") var stageField = new ObjectField("Stage")
{ {
@ -144,7 +125,7 @@ namespace Editor.GardensStageEditor
value = stage, value = stage,
style = style =
{ {
minWidth = 200 minWidth = 300
} }
}; };
stageField.RegisterValueChangedCallback(evt => stageField.RegisterValueChangedCallback(evt =>
@ -210,7 +191,7 @@ namespace Editor.GardensStageEditor
} }
}; };
topBar.Add(validate); topBar.Add(validate);
var save = new Button(delegate var save = new Button(delegate
{ {
EditorUtility.SetDirty(stage); EditorUtility.SetDirty(stage);
@ -225,31 +206,18 @@ namespace Editor.GardensStageEditor
} }
}; };
topBar.Add(save); topBar.Add(save);
var bake = new Button(BakeStage)
{
text = "Bake",
style =
{
marginLeft = 4
}
};
topBar.Add(bake);
} }
topBar.Add(AddSpacer());
mouseCellLabel = new Label("Mouse: —") var spacer = new VisualElement
{ {
style = style =
{ {
opacity = 0.85f, flexGrow = 1f
marginRight = 16f
} }
}; };
topBar.Add(mouseCellLabel); topBar.Add(spacer);
var hint = new Label("Infinite grid · LMB select/place/paint/move · selected resizable objects have a resize handle · RMB/MMB pan · Wheel zoom") var hint = new Label("Infinite grid · LMB select/place/paint · RMB/MMB pan · Wheel zoom")
{ {
style = style =
{ {
@ -259,30 +227,6 @@ namespace Editor.GardensStageEditor
topBar.Add(hint); topBar.Add(hint);
} }
private static VisualElement AddSpacer()
{
return new VisualElement
{
style =
{
flexGrow = 1f
}
};
}
public void SetMouseCell(Vector2Int? cell)
{
if (mouseCellLabel is null)
{
return;
}
mouseCellLabel.text = cell.HasValue
? "Mouse: X " + cell.Value.x + " Y " + cell.Value.y
: "Mouse: —";
}
private void SetStage(StageDefinition newStage) private void SetStage(StageDefinition newStage)
{ {
stage = newStage; stage = newStage;
@ -293,19 +237,12 @@ namespace Editor.GardensStageEditor
RebuildTopBar(); RebuildTopBar();
} }
private void SetPrefabTable(PrefabTable newPrefabTable)
{
prefabTable = newPrefabTable;
RebuildTopBar();
}
private void CreateNewStageAsset() private void CreateNewStageAsset()
{ {
var path = EditorUtility.SaveFilePanelInProject( var path = EditorUtility.SaveFilePanelInProject(
"Create Stage Definition", "Create Stage Definition",
"new-stage.stage-definition", "StageDefinition",
"asset", "asset",
"Choose where to create the new StageDefinition asset." "Choose where to create the new StageDefinition asset."
); );
@ -316,7 +253,7 @@ namespace Editor.GardensStageEditor
} }
var asset = CreateInstance<StageDefinition>(); var asset = CreateInstance<StageDefinition>();
asset.Id = Path.GetFileNameWithoutExtension(path).ToLowerInvariant(); asset.stageId = System.IO.Path.GetFileNameWithoutExtension(path).ToLowerInvariant();
asset.EnsureDefaults(); asset.EnsureDefaults();
AssetDatabase.CreateAsset(asset, path); AssetDatabase.CreateAsset(asset, path);
@ -339,8 +276,7 @@ namespace Editor.GardensStageEditor
var index = stage.floors.Count; var index = stage.floors.Count;
var floor = new StageFloorDefinition var floor = new StageFloorDefinition
{ {
floorId = "F" + index, floorId = "F" + index
FloorHeight = stage.floors.Count == 0 ? 0.0f : stage.floors[^1].FloorHeight
}; };
stage.floors.Add(floor); stage.floors.Add(floor);
@ -355,32 +291,5 @@ namespace Editor.GardensStageEditor
Debug.Log(report); Debug.Log(report);
EditorUtility.DisplayDialog("Stage Validation", report, "OK"); EditorUtility.DisplayDialog("Stage Validation", report, "OK");
} }
private void BakeStage()
{
if (stage is null)
{
EditorUtility.DisplayDialog(
"Bake Stage",
"Select or create a StageDefinition before baking.",
"OK"
);
return;
}
if (prefabTable is null)
{
EditorUtility.DisplayDialog(
"Bake Stage",
"Select a PrefabTable before baking.",
"OK"
);
return;
}
StageBaker.Bake(stage, prefabTable);
}
} }
} }

View File

@ -77,7 +77,14 @@ namespace Editor.GardensStageEditor
} }
}; };
Add(section); Add(section);
var stageId = new TextField("Stage Id")
{
value = stage.stageId
};
stageId.RegisterValueChangedCallback(evt => owner.MutateStage("Change stage id", delegate { stage.stageId = evt.newValue; }));
Add(stageId);
var cellSize = new FloatField("Cell Size") var cellSize = new FloatField("Cell Size")
{ {
value = stage.cellSize value = stage.cellSize
@ -158,8 +165,13 @@ namespace Editor.GardensStageEditor
id.RegisterValueChangedCallback(evt => owner.MutateStage("Change object id", delegate { obj.id = evt.newValue; })); id.RegisterValueChangedCallback(evt => owner.MutateStage("Change object id", delegate { obj.id = evt.newValue; }));
Add(id); Add(id);
AddReadOnlyLine("Layer", obj.layer.ToString()); var layer = new EnumField("Layer", obj.layer);
AddReadOnlyLine("Kind", obj.kind.ToString()); layer.RegisterValueChangedCallback(evt => owner.MutateStage("Change object layer", delegate { obj.layer = (StageLogicalLayer)evt.newValue; }));
Add(layer);
var kind = new EnumField("Kind", obj.kind);
kind.RegisterValueChangedCallback(evt => owner.MutateStage("Change object kind", delegate { obj.kind = (StageObjectKind)evt.newValue; }));
Add(kind);
var typeId = new TextField("Type Id") var typeId = new TextField("Type Id")
{ {
@ -189,56 +201,19 @@ namespace Editor.GardensStageEditor
y.RegisterValueChangedCallback(evt => owner.MutateStage("Move object y", delegate { obj.y = evt.newValue; })); y.RegisterValueChangedCallback(evt => owner.MutateStage("Move object y", delegate { obj.y = evt.newValue; }));
Add(y); Add(y);
if (obj.IsResizable) var width = new IntegerField("Width")
{ {
var min = obj.MinSize; value = obj.width
var max = obj.MaxSize; };
Add(new Label("Resizable: yes · Min " + min.x + "x" + min.y + " · Max " + max.x + "x" + max.y) width.RegisterValueChangedCallback(evt => owner.MutateStage("Resize object width", delegate { obj.width = Mathf.Max(1, evt.newValue); }));
{ Add(width);
style =
{
opacity = 0.75f,
marginTop = 4,
marginBottom = 2
}
});
var width = new IntegerField("Width") var height = new IntegerField("Height")
{
value = obj.width
};
width.RegisterValueChangedCallback(evt => owner.MutateStage("Resize object width", delegate
{
obj.width = evt.newValue;
obj.NormalizeSize();
}));
Add(width);
var height = new IntegerField("Height")
{
value = obj.height
};
height.RegisterValueChangedCallback(evt => owner.MutateStage("Resize object height", delegate
{
obj.height = evt.newValue;
obj.NormalizeSize();
}));
Add(height);
}
else
{ {
var fixedSize = obj.DefaultSize; value = obj.height
Add(new Label("Size: " + fixedSize.x + "x" + fixedSize.y + " (fixed)") };
{ height.RegisterValueChangedCallback(evt => owner.MutateStage("Resize object height", delegate { obj.height = Mathf.Max(1, evt.newValue); }));
style = Add(height);
{
opacity = 0.75f,
marginTop = 4,
marginBottom = 2
}
});
Add(new HelpBox("This object kind has a fixed size. It can be moved, but it cannot be resized from the inspector or the grid.", HelpBoxMessageType.Info));
}
var cutsGround = new Toggle("Cuts Ground") var cutsGround = new Toggle("Cuts Ground")
{ {
@ -279,39 +254,5 @@ namespace Editor.GardensStageEditor
}; };
Add(delete); Add(delete);
} }
private void AddReadOnlyLine(string label, string value)
{
var row = new VisualElement
{
style =
{
flexDirection = FlexDirection.Row,
marginTop = 2,
marginBottom = 2
}
};
var left = new Label(label)
{
style =
{
width = 90,
opacity = 0.75f
}
};
row.Add(left);
var right = new Label(value)
{
style =
{
unityFontStyleAndWeight = FontStyle.Bold
}
};
row.Add(right);
Add(row);
}
} }
} }

View File

@ -1,4 +1,3 @@
using System;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements; using UnityEngine.UIElements;
@ -8,16 +7,6 @@ namespace Editor.GardensStageEditor
{ {
private const float MinCellPixels = 12f; private const float MinCellPixels = 12f;
private const float MaxCellPixels = 96f; private const float MaxCellPixels = 96f;
private const float ResizeHandlePixels = 12f;
private enum DragMode
{
None,
Pan,
Paint,
MoveObject,
ResizeObject
}
private readonly StageEditorWindow owner; private readonly StageEditorWindow owner;
private readonly StageEditorState state; private readonly StageEditorState state;
@ -26,18 +15,12 @@ namespace Editor.GardensStageEditor
private Vector2 pan = new(40f, 40f); private Vector2 pan = new(40f, 40f);
private float cellPixels = 32f; private float cellPixels = 32f;
private DragMode dragMode = DragMode.None; private bool isPanning;
private bool isPainting;
private Vector2 panStartMouse; private Vector2 panStartMouse;
private Vector2 panStartValue; private Vector2 panStartValue;
private Vector2Int dragStartCell; private Vector2Int dragStartCell;
private Vector2Int dragCurrentCell; private Vector2Int dragCurrentCell;
private Vector2Int? hoverCell;
private StageObjectDefinition draggedObject;
private int objectStartX;
private int objectStartY;
private int objectStartWidth;
private int objectStartHeight;
public StageMapCanvas(StageEditorWindow owner, StageEditorState state) public StageMapCanvas(StageEditorWindow owner, StageEditorState state)
{ {
@ -46,7 +29,6 @@ namespace Editor.GardensStageEditor
focusable = true; focusable = true;
style.flexGrow = 1f; style.flexGrow = 1f;
style.overflow = Overflow.Hidden;
style.backgroundColor = StageEditorColors.Background; style.backgroundColor = StageEditorColors.Background;
generateVisualContent += OnGenerateVisualContent; generateVisualContent += OnGenerateVisualContent;
@ -54,7 +36,6 @@ namespace Editor.GardensStageEditor
RegisterCallback<MouseDownEvent>(OnMouseDown); RegisterCallback<MouseDownEvent>(OnMouseDown);
RegisterCallback<MouseMoveEvent>(OnMouseMove); RegisterCallback<MouseMoveEvent>(OnMouseMove);
RegisterCallback<MouseUpEvent>(OnMouseUp); RegisterCallback<MouseUpEvent>(OnMouseUp);
RegisterCallback<MouseLeaveEvent>(OnMouseLeave);
RegisterCallback<WheelEvent>(OnWheel); RegisterCallback<WheelEvent>(OnWheel);
} }
@ -77,8 +58,6 @@ namespace Editor.GardensStageEditor
return; return;
} }
UpdateHoverCell(evt.localMousePosition);
var mouse = evt.localMousePosition; var mouse = evt.localMousePosition;
var before = ScreenToGridFloat(mouse); var before = ScreenToGridFloat(mouse);
@ -95,7 +74,6 @@ namespace Editor.GardensStageEditor
private void OnMouseDown(MouseDownEvent evt) private void OnMouseDown(MouseDownEvent evt)
{ {
Focus(); Focus();
UpdateHoverCell(evt.localMousePosition);
if (stage is null) if (stage is null)
{ {
@ -105,7 +83,10 @@ namespace Editor.GardensStageEditor
// Pan is no longer a palette tool. It is always available through RMB/MMB. // Pan is no longer a palette tool. It is always available through RMB/MMB.
if (evt.button == 2 || evt.button == 1) if (evt.button == 2 || evt.button == 1)
{ {
BeginPan(evt.localMousePosition); isPanning = true;
panStartMouse = evt.localMousePosition;
panStartValue = pan;
this.CaptureMouse();
evt.StopPropagation(); evt.StopPropagation();
return; return;
} }
@ -115,240 +96,91 @@ namespace Editor.GardensStageEditor
return; return;
} }
if (!TryScreenToCell(evt.localMousePosition, out var cell)) if (!TryScreenToCell(evt.localMousePosition, out Vector2Int cell))
{ {
return; return;
} }
// If a resizable selected object has its handle clicked, resize wins over move/select.
if (TryBeginResizeSelectedObject(evt.localMousePosition, cell))
{
evt.StopPropagation();
MarkDirtyRepaint();
return;
}
// LMB always tries to select an existing logical object first. // LMB always tries to select an existing logical object first.
// If the user drags after selecting/hitting it, the same interaction moves it. // This removes the need for a Select tool.
var hit = FindObjectAt(cell, false); var hit = FindObjectAt(cell, false);
if (hit != null) if (hit != null)
{ {
state.SelectObject(hit); state.SelectObject(hit);
BeginMoveObject(hit, cell);
evt.StopPropagation();
MarkDirtyRepaint(); MarkDirtyRepaint();
evt.StopPropagation();
return; return;
} }
state.SelectObject(null); state.SelectObject(null);
// Empty space uses the active palette item to paint/place. // Empty space uses the active palette item to paint/place.
BeginPaint(cell); dragStartCell = cell;
dragCurrentCell = cell;
isPainting = true;
this.CaptureMouse();
evt.StopPropagation(); evt.StopPropagation();
MarkDirtyRepaint(); MarkDirtyRepaint();
} }
private void OnMouseMove(MouseMoveEvent evt) private void OnMouseMove(MouseMoveEvent evt)
{ {
UpdateHoverCell(evt.localMousePosition); if (isPanning)
switch (dragMode)
{ {
case DragMode.Pan: pan = panStartValue + evt.localMousePosition - panStartMouse;
pan = panStartValue + evt.localMousePosition - panStartMouse; evt.StopPropagation();
evt.StopPropagation(); MarkDirtyRepaint();
return;
}
if (isPainting)
{
if (TryScreenToCell(evt.localMousePosition, out Vector2Int cell))
{
dragCurrentCell = cell;
MarkDirtyRepaint(); MarkDirtyRepaint();
return; }
case DragMode.Paint: evt.StopPropagation();
if (TryScreenToCell(evt.localMousePosition, out var paintCell))
{
dragCurrentCell = paintCell;
MarkDirtyRepaint();
}
evt.StopPropagation();
return;
case DragMode.MoveObject:
if (TryScreenToCell(evt.localMousePosition, out var moveCell))
{
ApplyMoveObject(moveCell);
}
evt.StopPropagation();
return;
case DragMode.ResizeObject:
if (TryScreenToCell(evt.localMousePosition, out var resizeCell))
{
ApplyResizeObject(resizeCell);
}
evt.StopPropagation();
return;
case DragMode.None:
break;
default:
throw new ArgumentOutOfRangeException();
} }
} }
private void OnMouseUp(MouseUpEvent evt) private void OnMouseUp(MouseUpEvent evt)
{ {
switch (dragMode) if (isPanning)
{ {
case DragMode.None: isPanning = false;
return; if (this.HasMouseCapture())
case DragMode.Paint when evt.button == 0:
{ {
var rect = GetDragRect(); this.ReleaseMouse();
ApplyPalette(rect);
break;
} }
case DragMode.Pan:
case DragMode.MoveObject: evt.StopPropagation();
case DragMode.ResizeObject: return;
break;
default:
throw new ArgumentOutOfRangeException();
} }
EndDrag(); if (!isPainting || evt.button != 0)
evt.StopPropagation();
MarkDirtyRepaint();
}
private void OnMouseLeave(MouseLeaveEvent evt)
{
if (!this.HasMouseCapture())
{
hoverCell = null;
owner.SetMouseCell(null);
MarkDirtyRepaint();
}
}
private void BeginPan(Vector2 mouse)
{
dragMode = DragMode.Pan;
panStartMouse = mouse;
panStartValue = pan;
this.CaptureMouse();
}
private void BeginPaint(Vector2Int cell)
{
dragMode = DragMode.Paint;
dragStartCell = cell;
dragCurrentCell = cell;
this.CaptureMouse();
}
private void BeginMoveObject(StageObjectDefinition obj, Vector2Int cell)
{
dragMode = DragMode.MoveObject;
draggedObject = obj;
dragStartCell = cell;
dragCurrentCell = cell;
objectStartX = obj.x;
objectStartY = obj.y;
objectStartWidth = obj.width;
objectStartHeight = obj.height;
this.CaptureMouse();
}
private bool TryBeginResizeSelectedObject(Vector2 mouse, Vector2Int cell)
{
var obj = state.selectedObject;
if (obj is null || !CanEditObjectOnActiveFloor(obj) || !obj.IsResizable)
{
return false;
}
if (!GetResizeHandleRect(obj).Contains(mouse))
{
return false;
}
dragMode = DragMode.ResizeObject;
draggedObject = obj;
dragStartCell = cell;
dragCurrentCell = cell;
objectStartX = obj.x;
objectStartY = obj.y;
objectStartWidth = obj.width;
objectStartHeight = obj.height;
this.CaptureMouse();
return true;
}
private void ApplyMoveObject(Vector2Int cell)
{
if (draggedObject is null || !CanEditObjectOnActiveFloor(draggedObject))
{ {
return; return;
} }
dragCurrentCell = cell; isPainting = false;
var dx = cell.x - dragStartCell.x;
var dy = cell.y - dragStartCell.y;
var newX = objectStartX + dx;
var newY = objectStartY + dy;
if (draggedObject.x == newX && draggedObject.y == newY)
{
return;
}
owner.MutateStage("Move object", delegate
{
draggedObject.x = newX;
draggedObject.y = newY;
});
}
private void ApplyResizeObject(Vector2Int cell)
{
if (draggedObject is null || !CanEditObjectOnActiveFloor(draggedObject) || !draggedObject.IsResizable)
{
return;
}
dragCurrentCell = cell;
var min = draggedObject.MinSize;
var max = draggedObject.MaxSize;
var newWidth = Mathf.Clamp(cell.x - objectStartX + 1, Mathf.Max(1, min.x), Mathf.Max(1, max.x));
var newHeight = Mathf.Clamp(cell.y - objectStartY + 1, Mathf.Max(1, min.y), Mathf.Max(1, max.y));
if (draggedObject.width == newWidth && draggedObject.height == newHeight)
{
return;
}
owner.MutateStage("Resize object", delegate
{
draggedObject.width = newWidth;
draggedObject.height = newHeight;
draggedObject.NormalizeSize();
});
}
private void EndDrag()
{
dragMode = DragMode.None;
draggedObject = null;
if (this.HasMouseCapture()) if (this.HasMouseCapture())
{ {
this.ReleaseMouse(); this.ReleaseMouse();
} }
var rect = GetDragRect();
ApplyPalette(rect);
evt.StopPropagation();
MarkDirtyRepaint();
} }
private void ApplyPalette(RectInt rect) private void ApplyPalette(RectInt rect)
{ {
var floor = stage?.ActiveFloor; StageFloorDefinition floor = stage?.ActiveFloor;
if (floor is null) if (floor is null)
{ {
return; return;
@ -362,12 +194,21 @@ namespace Editor.GardensStageEditor
if (entry.paintsStructural) if (entry.paintsStructural)
{ {
owner.MutateStage("Paint " + entry.displayName, owner.MutateStage("Paint " + entry.displayName, delegate
delegate { floor.FillRect(rect, entry.structuralKind); }); {
floor.FillRect(rect, entry.structuralKind);
});
return; return;
} }
var objectRect = GetPaletteObjectRect(entry, rect); var objectRect = rect;
if (rect is { width: 1, height: 1 })
{
objectRect = new RectInt(rect.x, rect.y, Mathf.Max(1, entry.defaultSize.x), Mathf.Max(1, entry.defaultSize.y));
}
objectRect.width = Mathf.Clamp(objectRect.width, Mathf.Max(1, entry.minSize.x), Mathf.Max(1, entry.maxSize.x));
objectRect.height = Mathf.Clamp(objectRect.height, Mathf.Max(1, entry.minSize.y), Mathf.Max(1, entry.maxSize.y));
owner.MutateStage("Place " + entry.displayName, delegate owner.MutateStage("Place " + entry.displayName, delegate
{ {
@ -387,40 +228,11 @@ namespace Editor.GardensStageEditor
blocksMovement = entry.blocksMovement blocksMovement = entry.blocksMovement
}; };
obj.NormalizeSize();
stage.objects.Add(obj); stage.objects.Add(obj);
state.SelectObject(obj); state.SelectObject(obj);
}); });
} }
private RectInt GetPaletteObjectRect(StagePaletteEntry entry, RectInt paintedRect)
{
var defaultSize = entry.defaultSize;
if (defaultSize.x <= 0 || defaultSize.y <= 0)
{
defaultSize = StageObjectDefinition.GetDefaultSize(entry.objectKind);
}
if (!StageObjectDefinition.IsKindResizable(entry.objectKind))
{
return new RectInt(paintedRect.x, paintedRect.y, Mathf.Max(1, defaultSize.x),
Mathf.Max(1, defaultSize.y));
}
var objectRect = paintedRect;
if (paintedRect is { width: 1, height: 1 })
{
objectRect = new RectInt(paintedRect.x, paintedRect.y, Mathf.Max(1, defaultSize.x),
Mathf.Max(1, defaultSize.y));
}
var min = StageObjectDefinition.GetMinSize(entry.objectKind);
var max = StageObjectDefinition.GetMaxSize(entry.objectKind);
objectRect.width = Mathf.Clamp(objectRect.width, Mathf.Max(1, min.x), Mathf.Max(1, max.x));
objectRect.height = Mathf.Clamp(objectRect.height, Mathf.Max(1, min.y), Mathf.Max(1, max.y));
return objectRect;
}
private StageObjectDefinition FindObjectAt(Vector2Int cell, bool activeLayerOnly) private StageObjectDefinition FindObjectAt(Vector2Int cell, bool activeLayerOnly)
{ {
if (stage is null) if (stage is null)
@ -451,31 +263,6 @@ namespace Editor.GardensStageEditor
return null; return null;
} }
private bool CanEditObjectOnActiveFloor(StageObjectDefinition obj)
{
return stage is not null && obj is not null && stage.ActiveFloor is not null &&
obj.floorId == stage.ActiveFloor.floorId;
}
private void UpdateHoverCell(Vector2 localMousePosition)
{
if (stage is null || !TryScreenToCell(localMousePosition, out var cell))
{
hoverCell = null;
owner.SetMouseCell(null);
return;
}
if (hoverCell.HasValue && hoverCell.Value == cell)
{
return;
}
hoverCell = cell;
owner.SetMouseCell(cell);
MarkDirtyRepaint();
}
private void OnGenerateVisualContent(MeshGenerationContext mgc) private void OnGenerateVisualContent(MeshGenerationContext mgc)
{ {
var p = mgc.painter2D; var p = mgc.painter2D;
@ -494,74 +281,13 @@ namespace Editor.GardensStageEditor
} }
DrawInfiniteGrid(p); DrawInfiniteGrid(p);
DrawCells(p, floor);
DrawLowerFloors(p); DrawObjects(p, floor.floorId);
DrawCells(p, floor, 1f);
DrawObjects(p, floor.floorId, 1f, true);
DrawOriginAxes(p); DrawOriginAxes(p);
DrawHoverCell(p);
DrawPreview(p); DrawPreview(p);
} }
private void DrawLowerFloors(Painter2D p)
{
if (stage is null || stage.floors is null)
{
return;
}
var activeIndex = Mathf.Clamp(stage.activeFloorIndex, 0, stage.floors.Count - 1); private void DrawCells(Painter2D p, StageFloorDefinition floor)
for (var i = 0; i < activeIndex; i++)
{
var lowerFloor = stage.floors[i];
if (lowerFloor is null)
{
continue;
}
var alpha = GetLowerFloorAlpha(i, activeIndex);
DrawCells(p, lowerFloor, alpha);
DrawObjects(p, lowerFloor.floorId, alpha, false);
}
}
private float GetLowerFloorAlpha(int floorIndex, int activeFloorIndex)
{
var distance = activeFloorIndex - floorIndex;
// Floor imediatamente abaixo aparece mais forte.
// Floors mais distantes ficam mais apagados.
return Mathf.Clamp(0.38f - ((distance - 1) * 0.10f), 0.10f, 0.38f);
}
private void FillTriangle(Painter2D p, Vector2 a, Vector2 b, Vector2 c, Color color)
{
p.fillColor = color;
p.BeginPath();
p.MoveTo(a);
p.LineTo(b);
p.LineTo(c);
p.ClosePath();
p.Fill();
}
private void StrokeTriangle(Painter2D p, Vector2 a, Vector2 b, Vector2 c, Color color, float width)
{
p.strokeColor = color;
p.lineWidth = width;
p.BeginPath();
p.MoveTo(a);
p.LineTo(b);
p.LineTo(c);
p.ClosePath();
p.Stroke();
}
private void DrawCells(Painter2D p, StageFloorDefinition floor, float alphaMultiplier)
{ {
foreach (var cell in floor.Cells) foreach (var cell in floor.Cells)
{ {
@ -571,103 +297,12 @@ namespace Editor.GardensStageEditor
continue; continue;
} }
color = color.WithAlpha(color.a * alphaMultiplier);
var rect = CellRect(cell.x, cell.y); var rect = CellRect(cell.x, cell.y);
FillRect(p, rect, color); FillRect(p, rect, color);
DrawStructuralIcon(p, cell.structural, rect);
} }
} }
private void DrawStructuralIcon(Painter2D p, StructuralCellKind kind, Rect rect) private void DrawObjects(Painter2D p, string floorId)
{
if (cellPixels < 18f)
{
return;
}
var pad = Mathf.Clamp(rect.width * 0.18f, 3f, 8f);
var inner = rect.Expanded(-pad);
var ink = Color.black.WithAlpha(0.55f);
var light = Color.white.WithAlpha(0.45f);
var line = Mathf.Clamp(cellPixels * 0.08f, 1.5f, 4f);
switch (kind)
{
case StructuralCellKind.Ground_Slab:
StrokeRect(p, inner, ink, line);
DrawLine(p, new Vector2(inner.xMin, inner.center.y), new Vector2(inner.xMax, inner.center.y), light,
line);
break;
case StructuralCellKind.Ground_Ramp_Front:
FillTriangle(
p,
new Vector2(inner.xMin, inner.yMax),
new Vector2(inner.xMax, inner.yMax),
new Vector2(inner.center.x, inner.yMin),
light
);
StrokeTriangle(
p,
new Vector2(inner.xMin, inner.yMax),
new Vector2(inner.xMax, inner.yMax),
new Vector2(inner.center.x, inner.yMin),
ink,
line
);
break;
case StructuralCellKind.Ground_Ramp_Left:
FillTriangle(
p,
new Vector2(inner.xMax, inner.yMin),
new Vector2(inner.xMin, inner.center.y),
new Vector2(inner.xMax, inner.yMax),
light
);
StrokeTriangle(
p,
new Vector2(inner.xMax, inner.yMin),
new Vector2(inner.xMin, inner.center.y),
new Vector2(inner.xMax, inner.yMax),
ink,
line
);
break;
case StructuralCellKind.Ground_Ramp_Right:
FillTriangle(
p,
new Vector2(inner.xMin, inner.yMin),
new Vector2(inner.xMax, inner.center.y),
new Vector2(inner.xMin, inner.yMax),
light
);
StrokeTriangle(
p,
new Vector2(inner.xMin, inner.yMin),
new Vector2(inner.xMax, inner.center.y),
new Vector2(inner.xMin, inner.yMax),
ink,
line
);
break;
case StructuralCellKind.Wall:
StrokeRect(p, inner, ink, line);
DrawLine(p, new Vector2(inner.xMin, inner.yMin), new Vector2(inner.xMax, inner.yMax), ink, line);
DrawLine(p, new Vector2(inner.xMax, inner.yMin), new Vector2(inner.xMin, inner.yMax), ink, line);
break;
case StructuralCellKind.Empty:
break;
default:
throw new ArgumentOutOfRangeException(nameof(kind), kind, null);
}
}
private void DrawObjects(Painter2D p, string floorId, float alphaMultiplier, bool allowSelection)
{ {
foreach (var obj in stage.objects) foreach (var obj in stage.objects)
{ {
@ -678,90 +313,16 @@ namespace Editor.GardensStageEditor
var rect = GridRect(obj.Bounds); var rect = GridRect(obj.Bounds);
var color = StageEditorColors.Layer(obj.layer); var color = StageEditorColors.Layer(obj.layer);
color = color.WithAlpha(color.a * alphaMultiplier);
FillRect(p, rect, color); FillRect(p, rect, color);
StrokeRect(p, rect, color.WithAlpha(Mathf.Min(1f, color.a + 0.25f * alphaMultiplier)), 2f); StrokeRect(p, rect, color.WithAlpha(Mathf.Min(1f, color.a + 0.25f)), 2f);
DrawObjectIcon(p, obj.kind, rect);
if (state.selectedObject == obj)
if (allowSelection && state.selectedObject == obj)
{ {
StrokeRect(p, rect.Expanded(2f), StageEditorColors.SelectionStroke, 3f); StrokeRect(p, rect.Expanded(2f), StageEditorColors.SelectionStroke, 3f);
if (obj.IsResizable)
{
DrawResizeHandle(p, obj);
}
} }
} }
} }
private void DrawObjectIcon(Painter2D p, StageObjectKind kind, Rect rect)
{
if (cellPixels < 18f)
{
return;
}
var pad = Mathf.Clamp(Mathf.Min(rect.width, rect.height) * 0.2f, 4f, 12f);
var inner = rect.Expanded(-pad);
var ink = Color.black.WithAlpha(0.65f);
var light = Color.white.WithAlpha(0.7f);
var line = Mathf.Clamp(cellPixels * 0.08f, 1.5f, 4f);
switch (kind)
{
case StageObjectKind.Trap_FallingFloor:
DrawLine(p, new Vector2(inner.xMin, inner.center.y), new Vector2(inner.center.x, inner.yMin), ink,
line);
DrawLine(p, new Vector2(inner.center.x, inner.yMin), new Vector2(inner.xMax, inner.yMax), ink,
line);
break;
case StageObjectKind.DoorHorizontal:
DrawLine(p, new Vector2(inner.xMin, inner.center.y), new Vector2(inner.xMax, inner.center.y), light,
line);
DrawLine(p, new Vector2(inner.xMin, inner.yMin), new Vector2(inner.xMin, inner.yMax), ink, line);
DrawLine(p, new Vector2(inner.xMax, inner.yMin), new Vector2(inner.xMax, inner.yMax), ink, line);
break;
case StageObjectKind.DoorVertical:
DrawLine(p, new Vector2(inner.center.x, inner.yMin), new Vector2(inner.center.x, inner.yMax), light,
line);
DrawLine(p, new Vector2(inner.xMin, inner.yMin), new Vector2(inner.xMax, inner.yMin), ink, line);
DrawLine(p, new Vector2(inner.xMin, inner.yMax), new Vector2(inner.xMax, inner.yMax), ink, line);
break;
case StageObjectKind.CameraBoundary:
DrawCornerBrackets(p, inner, ink, line);
break;
}
}
private void DrawCornerBrackets(Painter2D p, Rect rect, Color color, float width)
{
var l = Mathf.Min(rect.width, rect.height) * 0.25f;
DrawLine(p, new Vector2(rect.xMin, rect.yMin), new Vector2(rect.xMin + l, rect.yMin), color, width);
DrawLine(p, new Vector2(rect.xMin, rect.yMin), new Vector2(rect.xMin, rect.yMin + l), color, width);
DrawLine(p, new Vector2(rect.xMax, rect.yMin), new Vector2(rect.xMax - l, rect.yMin), color, width);
DrawLine(p, new Vector2(rect.xMax, rect.yMin), new Vector2(rect.xMax, rect.yMin + l), color, width);
DrawLine(p, new Vector2(rect.xMin, rect.yMax), new Vector2(rect.xMin + l, rect.yMax), color, width);
DrawLine(p, new Vector2(rect.xMin, rect.yMax), new Vector2(rect.xMin, rect.yMax - l), color, width);
DrawLine(p, new Vector2(rect.xMax, rect.yMax), new Vector2(rect.xMax - l, rect.yMax), color, width);
DrawLine(p, new Vector2(rect.xMax, rect.yMax), new Vector2(rect.xMax, rect.yMax - l), color, width);
}
private void DrawResizeHandle(Painter2D p, StageObjectDefinition obj)
{
var handle = GetResizeHandleRect(obj);
FillRect(p, handle, StageEditorColors.SelectionStroke);
StrokeRect(p, handle, Color.black.WithAlpha(0.75f), 1f);
}
private void DrawInfiniteGrid(Painter2D p) private void DrawInfiniteGrid(Painter2D p)
{ {
var r = contentRect; var r = contentRect;
@ -802,30 +363,19 @@ namespace Editor.GardensStageEditor
} }
} }
private void DrawHoverCell(Painter2D p)
{
if (!hoverCell.HasValue)
{
return;
}
var cell = hoverCell.Value;
StrokeRect(p, CellRect(cell.x, cell.y).Expanded(-2f), StageEditorColors.PreviewStroke.WithAlpha(0.45f), 1f);
}
private void DrawPreview(Painter2D p) private void DrawPreview(Painter2D p)
{ {
if (dragMode != DragMode.Paint || state.activePaletteEntry is null) if (!isPainting || state.activePaletteEntry is null)
{ {
return; return;
} }
var rect = GetDragRect(); var rect = GetDragRect();
var entry = state.activePaletteEntry; var entry = state.activePaletteEntry;
if (!entry.paintsStructural) if (!entry.paintsStructural && rect is { width: 1, height: 1 })
{ {
rect = GetPaletteObjectRect(entry, rect); rect = new RectInt(rect.x, rect.y, Mathf.Max(1, entry.defaultSize.x), Mathf.Max(1, entry.defaultSize.y));
} }
var screenRect = GridRect(rect); var screenRect = GridRect(rect);
@ -861,15 +411,7 @@ namespace Editor.GardensStageEditor
private Rect GridRect(RectInt rect) private Rect GridRect(RectInt rect)
{ {
return new Rect(pan.x + rect.x * cellPixels, pan.y + rect.y * cellPixels, rect.width * cellPixels, return new Rect(pan.x + rect.x * cellPixels, pan.y + rect.y * cellPixels, rect.width * cellPixels, rect.height * cellPixels);
rect.height * cellPixels);
}
private Rect GetResizeHandleRect(StageObjectDefinition obj)
{
var rect = GridRect(obj.Bounds);
var size = Mathf.Min(ResizeHandlePixels, Mathf.Max(8f, cellPixels * 0.35f));
return new Rect(rect.xMax - size, rect.yMax - size, size, size);
} }
private void FillRect(Painter2D p, Rect rect, Color color) private void FillRect(Painter2D p, Rect rect, Color color)
@ -921,4 +463,4 @@ namespace Editor.GardensStageEditor
return color; return color;
} }
} }
} }

View File

@ -19,7 +19,7 @@ namespace Editor.GardensStageEditor
public Vector2Int defaultSize = Vector2Int.one; public Vector2Int defaultSize = Vector2Int.one;
public Vector2Int minSize = Vector2Int.one; public Vector2Int minSize = Vector2Int.one;
public Vector2Int maxSize = new(32, 32); public Vector2Int maxSize = new(32, 32);
public bool resizable; public bool resizable = true;
public bool cutsGround; public bool cutsGround;
public bool blocksMovement; public bool blocksMovement;
@ -38,21 +38,9 @@ namespace Editor.GardensStageEditor
resizable = true resizable = true
}; };
} }
public static StagePaletteEntry Object(
string id,
string name,
StageLogicalLayer layer,
StageObjectKind kind,
string typeId,
Vector2Int defaultSize = default,
Vector2Int min = default,
Vector2Int max = default)
{
var kindDefault = StageObjectDefinition.GetDefaultSize(kind);
var kindMin = StageObjectDefinition.GetMinSize(kind);
var kindMax = StageObjectDefinition.GetMaxSize(kind);
public static StagePaletteEntry Object(string id, string name, StageLogicalLayer layer, StageObjectKind kind, string typeId, Vector2Int defaultSize)
{
return new StagePaletteEntry return new StagePaletteEntry
{ {
id = id, id = id,
@ -62,10 +50,10 @@ namespace Editor.GardensStageEditor
objectKind = kind, objectKind = kind,
typeId = typeId, typeId = typeId,
prefabId = string.Empty, prefabId = string.Empty,
defaultSize = defaultSize == default ? kindDefault : defaultSize, defaultSize = defaultSize,
minSize = min == default ? kindMin : min, minSize = Vector2Int.one,
maxSize = max == default ? kindMax : max, maxSize = new Vector2Int(64, 64),
resizable = StageObjectDefinition.IsKindResizable(kind) resizable = true
}; };
} }
@ -73,56 +61,26 @@ namespace Editor.GardensStageEditor
{ {
var entries = new List<StagePaletteEntry> var entries = new List<StagePaletteEntry>
{ {
Structural("struct_ground_slab", "Ground - Slab", StructuralCellKind.Ground_Slab), Structural("struct_ground", "Ground", StructuralCellKind.Ground),
Structural("struct_ground_ramp_front", "Ground - RF", StructuralCellKind.Ground_Ramp_Front),
Structural("struct_ground_ramp_left", "Ground - RL", StructuralCellKind.Ground_Ramp_Left),
Structural("struct_ground_ramp_right", "Ground - RR", StructuralCellKind.Ground_Ramp_Right),
Structural("struct_wall", "Wall", StructuralCellKind.Wall), Structural("struct_wall", "Wall", StructuralCellKind.Wall),
Structural("struct_empty", "Erase Structural", StructuralCellKind.Empty)
// leave it as last as possible
Structural("struct_empty", "Erase Structural", StructuralCellKind.Empty),
}; };
var trapFallingFloor = Object("trap_falling_floor", var trap = Object("trap_falling_floor", "Falling Floor", StageLogicalLayer.Design, StageObjectKind.Trap, "falling_floor", Vector2Int.one);
"Trap (Falling Floor)", trap.cutsGround = true;
StageLogicalLayer.Design, trap.blocksMovement = true;
StageObjectKind.Trap_FallingFloor, entries.Add(trap);
"trap_falling_floor",
defaultSize: Vector2Int.one);
trapFallingFloor.cutsGround = true;
trapFallingFloor.blocksMovement = true;
entries.Add(trapFallingFloor);
var doorHorizontal = Object("door_horizontal_standard", var door = Object("door_standard", "Door", StageLogicalLayer.Design, StageObjectKind.Door, "door_standard", new Vector2Int(1, 2));
"Door Horizontal", door.blocksMovement = true;
StageLogicalLayer.Design, entries.Add(door);
StageObjectKind.DoorHorizontal,
"door_horizontal_standard",
new Vector2Int(2, 1));
doorHorizontal.blocksMovement = true;
entries.Add(doorHorizontal);
var doorVertical = Object("door_vertical_standard",
"Door Vertical",
StageLogicalLayer.Design,
StageObjectKind.DoorVertical,
"door_vertical_standard",
new Vector2Int(1, 2));
doorVertical.blocksMovement = true;
entries.Add(doorVertical);
// entries.Add(Object("interactable", "Interactable", StageLogicalLayer.Design, StageObjectKind.Interactable, "interactable", Vector2Int.one)); entries.Add(Object("interactable", "Interactable", StageLogicalLayer.Design, StageObjectKind.Interactable, "interactable", Vector2Int.one));
// entries.Add(Object("portal", "Portal", StageLogicalLayer.Design, StageObjectKind.Portal, "portal", new Vector2Int(2, 2))); entries.Add(Object("portal", "Portal", StageLogicalLayer.Design, StageObjectKind.Portal, "portal", new Vector2Int(2, 2)));
entries.Add(Object("camera_boundary", entries.Add(Object("camera_zone", "Camera Zone", StageLogicalLayer.Camera, StageObjectKind.CameraZone, "camera_zone", new Vector2Int(8, 5)));
"Camera Boundary", entries.Add(Object("spawn_player", "Player Spawn", StageLogicalLayer.Markers, StageObjectKind.Spawn, "player_spawn", Vector2Int.one));
StageLogicalLayer.Camera, entries.Add(Object("elevator", "Elevator", StageLogicalLayer.Markers, StageObjectKind.Elevator, "elevator", new Vector2Int(2, 2)));
StageObjectKind.CameraBoundary, entries.Add(Object("marker", "Marker", StageLogicalLayer.Markers, StageObjectKind.Marker, "marker", Vector2Int.one));
"camera_boundary",
defaultSize: new Vector2Int(8, 5),
min: new Vector2Int(8, 5)));
// entries.Add(Object("spawn_player", "Player Spawn", StageLogicalLayer.Markers, StageObjectKind.Spawn, "player_spawn", Vector2Int.one));
// entries.Add(Object("elevator", "Elevator", StageLogicalLayer.Markers, StageObjectKind.Elevator, "elevator", new Vector2Int(2, 2)));
// entries.Add(Object("marker", "Marker", StageLogicalLayer.Markers, StageObjectKind.Marker, "marker", Vector2Int.one));
return entries; return entries;
} }

View File

@ -1,2 +1,3 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 0e7ed87816264200a12fcc4bf3584153 guid: 0e7ed87816264200a12fcc4bf3584153
timeCreated: 1781500522

View File

@ -40,7 +40,12 @@ namespace Editor.GardensStageEditor
} }
stage.EnsureDefaults(); stage.EnsureDefaults();
if (string.IsNullOrEmpty(stage.stageId))
{
messages.Add(new StageValidationMessage(StageValidationSeverity.Warning, "Stage id is empty."));
}
if (stage.floors.Count == 0) if (stage.floors.Count == 0)
{ {
messages.Add(new StageValidationMessage(StageValidationSeverity.Error, "Stage has no floors.")); messages.Add(new StageValidationMessage(StageValidationSeverity.Error, "Stage has no floors."));

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using Intrepid.Core.Entities.Messages; using Intrepid.Core.Entities.Messages;
using Intrepid.Core.Grounding; using Intrepid.Core.Grounding;
using Intrepid.Diagnostics; using Intrepid.Diagnostics;
@ -12,8 +11,6 @@ namespace Intrepid.Core.Entities
{ {
public sealed class EntityMotorTopDown : MonoBehaviour public sealed class EntityMotorTopDown : MonoBehaviour
{ {
private const float FlatGroundNormalThreshold = 0.999f;
[GroupInjections, SerializeField] private Entity entity; [GroupInjections, SerializeField] private Entity entity;
[GroupConfigurations, SerializeField] private LayerMask groundMask; [GroupConfigurations, SerializeField] private LayerMask groundMask;
@ -32,42 +29,32 @@ namespace Intrepid.Core.Entities
[GroupConfigurations, SerializeField] private float fallAcceleration = 35f; [GroupConfigurations, SerializeField] private float fallAcceleration = 35f;
[GroupConfigurations, SerializeField] private float maxFallSpeed = 18f; [GroupConfigurations, SerializeField] private float maxFallSpeed = 18f;
private readonly List<RaycastHit> _groundHits = new(16);
private RaycastHit _groundHit;
private Vector3 Origin { get; set; } private Vector3 Origin { get; set; }
private Vector3 End { get; set; } private Vector3 End { get; set; }
private bool HasHit { get; set; } private bool HasHit { get; set; }
private Vector3 _inheritedGroundVelocity; private Vector3 _inheritedGroundVelocity;
private float _fallVerticalSpeed; private float _fallVerticalSpeed;
private RaycastHit _groundHit;
private float GroundProbeRadius => IsFalling || IsFallingToAbyss private float GroundProbeRadius => IsFalling || IsFallingToAbyss
? groundProbeRadiusFalling ? groundProbeRadiusFalling
: groundProbeRadiusGrounded; : groundProbeRadiusGrounded;
public GroundProfiles CurrentGroundProfiles { get; private set; } = GroundProfiles.None; public GroundProfiles CurrentGroundProfiles { get; private set; } = GroundProfiles.None;
public float MaxSlopeAngle => maxSlopeAngle; public float MaxSlopeAngle => maxSlopeAngle;
[GroupDebug, ShowInInspector, ReadOnly] [GroupDebug, ShowInInspector, ReadOnly]
public Vector3 LastSafeGroundPosition { get; private set; } public Vector3 LastSafeGroundPosition { get; private set; }
[GroupDebug, ShowInInspector, ReadOnly] [GroupDebug, ShowInInspector, ReadOnly]
public bool HasStableGroundNormal { get; private set; } public bool HasStableGroundNormal { get; private set; }
[GroupDebug, ShowInInspector, ReadOnly] [GroupDebug, ShowInInspector, ReadOnly]
public Vector3 StableGroundNormal { get; private set; } public Vector3 StableGroundNormal { get; private set; }
[GroupDebug, ShowInInspector, ReadOnly] [GroupDebug, ShowInInspector, ReadOnly]
public bool IsFalling { get; private set; } public bool IsFalling { get; private set; }
[GroupDebug, ShowInInspector, ReadOnly] [GroupDebug, ShowInInspector, ReadOnly]
public bool IsFallingToAbyss { get; private set; } public bool IsFallingToAbyss { get; private set; }
[GroupDebug, ShowInInspector, ReadOnly] [GroupDebug, ShowInInspector, ReadOnly]
public bool IsGrounded { get; private set; } public bool IsGrounded { get; private set; }
[GroupDebug, ShowInInspector, ReadOnly] [GroupDebug, ShowInInspector, ReadOnly]
public Vector3 InheritedGroundVelocity => _inheritedGroundVelocity; public Vector3 InheritedGroundVelocity => _inheritedGroundVelocity;
[GroupDebug, ShowInInspector, ReadOnly] [GroupDebug, ShowInInspector, ReadOnly]
public float InheritedGroundVelocityTimer { get; private set; } public float InheritedGroundVelocityTimer { get; private set; }
@ -370,7 +357,7 @@ namespace Intrepid.Core.Entities
RegisterStableGroundNormal(normal); RegisterStableGroundNormal(normal);
} }
} }
private Vector3 ResolveMovementVelocity(Vector3 velocity) private Vector3 ResolveMovementVelocity(Vector3 velocity)
{ {
if (velocity.sqrMagnitude <= GonConstants.CommonZeroSqrt) if (velocity.sqrMagnitude <= GonConstants.CommonZeroSqrt)
@ -383,67 +370,10 @@ namespace Intrepid.Core.Entities
return velocity; return velocity;
} }
var projectedVelocity = ProjectVelocityOnPlane( return ProjectVelocityOnPlane(
velocity, velocity,
StableGroundNormal StableGroundNormal
); );
return ApplyGroundMovementProfile(
projectedVelocity,
StableGroundNormal
);
}
private Vector3 ApplyGroundMovementProfile(
Vector3 velocity,
Vector3 groundNormal)
{
if (!IsGrounded || !CurrentGroundProfiles.TryGetGroundProfileMovement(out var movement))
{
return velocity;
}
if (velocity.sqrMagnitude <= GonConstants.CommonZeroSqrt)
{
return Vector3.zero;
}
var downhill = Vector3.ProjectOnPlane(
Vector3.down,
groundNormal.normalized
);
if (downhill.sqrMagnitude <= GonConstants.CommonZeroSqrt)
{
return velocity * movement.SpeedMultiplier;
}
downhill.Normalize();
var moveDirection = velocity.normalized;
var downhillFactor = Vector3.Dot(moveDirection, downhill);
float directionalMultiplier;
if (downhillFactor > 0f)
{
directionalMultiplier = Mathf.Lerp(
movement.SidewaysSpeedMultiplier,
movement.DownhillSpeedMultiplier,
downhillFactor
);
}
else
{
directionalMultiplier = Mathf.Lerp(
movement.SidewaysSpeedMultiplier,
movement.UphillSpeedMultiplier,
-downhillFactor
);
}
return velocity * (movement.SpeedMultiplier * directionalMultiplier);
} }
private void RegisterStableGroundNormal(Vector3 normal) private void RegisterStableGroundNormal(Vector3 normal)
@ -462,134 +392,55 @@ namespace Intrepid.Core.Entities
return TryGetGroundSurfaceAt(position, out _, out _, out _); return TryGetGroundSurfaceAt(position, out _, out _, out _);
} }
private bool TryGetBestGroundSurfaceHit(
Vector3 position,
float checkDistance,
out RaycastHit hit,
out Vector3 normal,
out GroundProfiles groundProfiles)
{
hit = default;
normal = default;
groundProfiles = GroundProfiles.None;
Origin = position + Vector3.up * groundCheckHeight;
End = Origin + Vector3.down * checkDistance;
_groundHits.Clear();
var hitCount = PhysicUtils.SphereCast3DAll(
Origin,
GroundProbeRadius,
Vector3.down,
_groundHits,
tags: null,
maxDistance: checkDistance,
layerMask: groundMask,
query: QueryTriggerInteraction.Ignore
);
HasHit = hitCount > 0;
if (hitCount == 0)
{
return false;
}
var found = false;
var bestHit = default(RaycastHit);
var bestNormal = Vector3.zero;
var bestProfiles = GroundProfiles.None;
var bestIsSlope = false;
var bestDistance = float.PositiveInfinity;
foreach (var candidateHit in _groundHits)
{
if (candidateHit.collider.IsNull())
{
continue;
}
var surface = candidateHit.collider.GetComponentInParent<GroundSurface>();
if (surface.IsNull())
{
continue;
}
var candidateNormal = surface.Normal;
if (!IsWalkable(candidateNormal))
{
continue;
}
var candidateIsSlope = IsSlope(candidateNormal);
var candidateDistance = candidateHit.distance;
var shouldReplace =
!found ||
// any walkable slope wins a plane
candidateIsSlope && !bestIsSlope ||
// if both are slopes or planes take the closest one
candidateIsSlope == bestIsSlope &&
candidateDistance < bestDistance;
if (!shouldReplace)
{
continue;
}
found = true;
bestHit = candidateHit;
bestNormal = candidateNormal;
bestProfiles = surface.GroundProfiles;
bestIsSlope = candidateIsSlope;
bestDistance = candidateDistance;
}
if (!found)
{
return false;
}
hit = bestHit;
normal = bestNormal;
groundProfiles = bestProfiles;
return true;
}
private bool TryGetGroundSurfaceAt( private bool TryGetGroundSurfaceAt(
Vector3 position, Vector3 position,
out RaycastHit hit, out RaycastHit hit,
out Vector3 normal, out Vector3 normal,
out GroundProfiles groundProfiles) out GroundProfiles groundProfiles)
{ {
return TryGetBestGroundSurfaceHit( normal = default;
position, groundProfiles = GroundProfiles.None;
groundCheckDistance,
out hit, if (!TryGetGroundAt(position, out hit))
out normal, {
out groundProfiles return false;
); }
var surface = hit.collider.GetComponentInParent<GroundSurface>();
if (surface.IsNull())
{
return false;
}
normal = surface.Normal;
if (!IsWalkable(normal))
{
return false;
}
groundProfiles = surface.GroundProfiles;
return true;
} }
private bool TryGetGroundAt(Vector3 position, out RaycastHit hit) private bool TryGetGroundAt(Vector3 position, out RaycastHit hit)
{ {
return TryGetBestGroundSurfaceHit( Origin = position + Vector3.up * groundCheckHeight;
position, End = Origin + Vector3.down * groundCheckDistance;
groundCheckDistance,
HasHit = Physics.SphereCast(
Origin,
GroundProbeRadius,
Vector3.down,
out hit, out hit,
out _, groundCheckDistance,
out _ groundMask,
QueryTriggerInteraction.Ignore
); );
return HasHit;
} }
private bool TryAnyGroundSurfaceBelowAt( private bool TryAnyGroundSurfaceBelowAt(
@ -598,18 +449,43 @@ namespace Intrepid.Core.Entities
out Vector3 normal, out Vector3 normal,
out GroundProfiles groundProfiles) out GroundProfiles groundProfiles)
{ {
return TryGetBestGroundSurfaceHit( normal = default;
position, groundProfiles = GroundProfiles.None;
fallingGroundCheckDistance,
out hit,
out normal,
out groundProfiles
);
}
private static bool IsSlope(Vector3 normal) var origin = position + Vector3.up * groundCheckHeight;
{
return normal.y < FlatGroundNormalThreshold; HasHit = Physics.SphereCast(
origin,
GroundProbeRadius,
Vector3.down,
out hit,
fallingGroundCheckDistance,
groundMask,
QueryTriggerInteraction.Ignore
);
if (!HasHit)
{
return false;
}
var surface = hit.collider.GetComponentInParent<GroundSurface>();
if (surface.IsNull())
{
return false;
}
normal = surface.Normal;
if (!IsWalkable(normal))
{
return false;
}
groundProfiles = surface.GroundProfiles;
return true;
} }
private bool IsWalkable(Vector3 normal) private bool IsWalkable(Vector3 normal)

View File

@ -2,7 +2,7 @@ using Intrepid.Utilities;
namespace Intrepid.Core.Grounding namespace Intrepid.Core.Grounding
{ {
public abstract class GroundProfileBehaviour : Identification public abstract class GroundProfile : Identification
{ {
} }

View File

@ -0,0 +1,12 @@
using UnityEngine;
namespace Intrepid.Core.Grounding
{
public abstract class GroundProfileMotion : GroundProfile
{
public abstract Vector3 Velocity { get; protected set; }
public abstract Vector3 DeltaPosition { get; protected set; }
public abstract bool IsMoving { get; protected set; }
public abstract bool IsStatic { get; protected set; }
}
}

View File

@ -1,11 +0,0 @@
using UnityEngine;
namespace Intrepid.Core.Grounding
{
public class GroundProfileMotionBehaviour : GroundProfileBehaviour
{
[SerializeField] private GroundProfileMotion groundProfileMotion;
public GroundProfileMotion GroundProfileMotion => groundProfileMotion;
}
}

View File

@ -1,11 +0,0 @@
using UnityEngine;
namespace Intrepid.Core.Grounding
{
public class GroundProfileMovementBehaviour : GroundProfileBehaviour
{
[SerializeField] private GroundProfileMovement groundProfileMovement = GroundProfileMovement.NoModifiers;
public GroundProfileMovement GroundProfileMovement => groundProfileMovement;
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: bdd4ad30e2d149b58a2f84fa9a5b5fbc
timeCreated: 1781681309

View File

@ -1,129 +1,19 @@
using System; using System;
using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Intrepid.Core.Grounding namespace Intrepid.Core.Grounding
{ {
[Serializable]
public abstract class GroundProfile
{
}
[Serializable, GroupConfigurations("Motion Profile"), HideLabel]
public sealed class GroundProfileMotion : GroundProfile
{
[SerializeField] private Vector3 velocity;
[SerializeField] private Vector3 deltaPosition;
[SerializeField] private bool isMoving;
[SerializeField] private bool isStatic;
public Vector3 Velocity
{
get => velocity;
set => velocity = value;
}
public Vector3 DeltaPosition
{
get => deltaPosition;
set => deltaPosition = value;
}
public bool IsMoving
{
get => isMoving;
set => isMoving = value;
}
public bool IsStatic
{
get => isStatic;
set => isStatic = value;
}
}
[Serializable, GroupConfigurations("Movement Profile"), HideLabel]
public class GroundProfileMovement : GroundProfile
{
[SerializeField] private float speedMultiplier;
[SerializeField] private float accelerationMultiplier;
[SerializeField] private float decelerationMultiplier;
[SerializeField] private float uphillSpeedMultiplier;
[SerializeField] private float downhillSpeedMultiplier;
[SerializeField] private float sidewaysSpeedMultiplier;
public float SpeedMultiplier
{
get => speedMultiplier;
protected set => speedMultiplier = value;
}
public float AccelerationMultiplier
{
get => accelerationMultiplier;
protected set => accelerationMultiplier = value;
}
public float DecelerationMultiplier
{
get => decelerationMultiplier;
protected set => decelerationMultiplier = value;
}
public float UphillSpeedMultiplier
{
get => uphillSpeedMultiplier;
protected set => uphillSpeedMultiplier = value;
}
public float DownhillSpeedMultiplier
{
get => downhillSpeedMultiplier;
protected set => downhillSpeedMultiplier = value;
}
public float SidewaysSpeedMultiplier
{
get => sidewaysSpeedMultiplier;
protected set => sidewaysSpeedMultiplier = value;
}
public static GroundProfileMovement NoModifiers => new()
{
SpeedMultiplier = 1f,
AccelerationMultiplier = 1f,
DecelerationMultiplier = 1f,
UphillSpeedMultiplier = 1f,
DownhillSpeedMultiplier = 1f,
SidewaysSpeedMultiplier = 1f,
};
public static GroundProfileMovement operator *(GroundProfileMovement a, GroundProfileMovement b)
{
return new GroundProfileMovement
{
SpeedMultiplier = a.SpeedMultiplier * b.SpeedMultiplier,
AccelerationMultiplier = a.AccelerationMultiplier * b.AccelerationMultiplier,
DecelerationMultiplier = a.DecelerationMultiplier * b.DecelerationMultiplier,
UphillSpeedMultiplier = a.UphillSpeedMultiplier * b.UphillSpeedMultiplier,
DownhillSpeedMultiplier = a.DownhillSpeedMultiplier * b.DownhillSpeedMultiplier,
SidewaysSpeedMultiplier = a.SidewaysSpeedMultiplier * b.SidewaysSpeedMultiplier,
};
}
}
public readonly struct GroundProfiles public readonly struct GroundProfiles
{ {
public static readonly GroundProfiles None = new(false); public static readonly GroundProfiles None = new(false);
private readonly bool _isSafe; private readonly bool _isSafe;
private GroundProfileMotion GroundProfileMotion { get; } private GroundProfileMotion GroundProfileMotion { get; }
private GroundProfileMovement GroundProfileMovement { get; }
public bool IsSafe => CheckIfThisProfileIsSafe(); public bool IsSafe => CheckIfThisProfileIsSafe();
public GroundProfiles(bool isSafe, public GroundProfiles(bool isSafe, GroundProfileMotion groundProfileMotion = null)
GroundProfileMotion groundProfileMotion = null,
GroundProfileMovement groundProfileMovement = null)
{ {
_isSafe = isSafe; _isSafe = isSafe;
GroundProfileMotion = groundProfileMotion; GroundProfileMotion = groundProfileMotion;
GroundProfileMovement = groundProfileMovement;
} }
private bool CheckIfThisProfileIsSafe() private bool CheckIfThisProfileIsSafe()
@ -138,7 +28,7 @@ namespace Intrepid.Core.Grounding
private bool TryGet<T>(T value, out T profile) where T: GroundProfile private bool TryGet<T>(T value, out T profile) where T: GroundProfile
{ {
if (value is null) if (value.IsNull())
{ {
profile = null; profile = null;
return false; return false;
@ -152,10 +42,5 @@ namespace Intrepid.Core.Grounding
{ {
return TryGet(GroundProfileMotion, out profile); return TryGet(GroundProfileMotion, out profile);
} }
public bool TryGetGroundProfileMovement(out GroundProfileMovement profile)
{
return TryGet(GroundProfileMovement, out profile);
}
} }
} }

View File

@ -1,6 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using Intrepid.Utilities; using Intrepid.Utilities;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
using UnityEngine; using UnityEngine;
@ -15,8 +13,8 @@ namespace Intrepid.Core.Grounding
{ {
[GroupInjections, SerializeField] private BoxCollider boxCollider; [GroupInjections, SerializeField] private BoxCollider boxCollider;
[GroupConfigurations("Profiles"), SerializeField] private bool safe = true; [GroupConfigurations("Profiles"), SerializeField] private bool safe = true;
[GroupConfigurations("Profiles"), SerializeField] private GroundProfileMotionBehaviour motionProfile; [GroupConfigurations("Profiles"), SerializeField] private GroundProfileMotion groundProfileMotion;
[GroupConfigurations("Profiles"), SerializeField] private List<GroundProfileMovementBehaviour> movementProfiles = new();
[GroupDebug, ShowInInspector, ReadOnly] public Vector3 Position { get; private set; } [GroupDebug, ShowInInspector, ReadOnly] public Vector3 Position { get; private set; }
[GroupDebug, ShowInInspector, ReadOnly] public Vector3 Normal { get; private set; } [GroupDebug, ShowInInspector, ReadOnly] public Vector3 Normal { get; private set; }
@ -40,12 +38,7 @@ namespace Intrepid.Core.Grounding
[GroupDebug, Button(ButtonSizes.Medium)] [GroupDebug, Button(ButtonSizes.Medium)]
private void RefreshProfiles() private void RefreshProfiles()
{ {
var groundProfileMovement = movementProfiles.Count == 0 GroundProfiles = new GroundProfiles(safe, groundProfileMotion);
? null
: movementProfiles
.Select(behaviour => behaviour.GroundProfileMovement)
.Aggregate(GroundProfileMovement.NoModifiers, (a, b) => a * b);
GroundProfiles = new GroundProfiles(safe, motionProfile?.GroundProfileMotion, groundProfileMovement);
} }
[Button(ButtonSizes.Medium)] [Button(ButtonSizes.Medium)]

View File

@ -12,24 +12,19 @@ namespace Intrepid.Gameplay.Prototyping
[GroupConfigurations, SerializeField, ReadOnly] private int sizeX = 1; [GroupConfigurations, SerializeField, ReadOnly] private int sizeX = 1;
[GroupConfigurations, SerializeField, ReadOnly] private int sizeY = 1; [GroupConfigurations, SerializeField, ReadOnly] private int sizeY = 1;
[GroupConfigurations, SerializeField, ReadOnly] private int sizeZ = 1; [GroupConfigurations, SerializeField, ReadOnly] private int sizeZ = 1;
[GroupConfigurations, SerializeField, ReadOnly] private Vector2 offset_x = new(1f, 1.5f); [GroupConfigurations, SerializeField, ReadOnly] private float offset = 1f;
[GroupConfigurations, SerializeField, ReadOnly] private Vector2 offset_y = new(1f, 1.5f);
[GroupDebug, SerializeField, Min(1)] private int x = 1; [GroupDebug, SerializeField, Min(1)] private int x = 1;
[GroupDebug, SerializeField, Min(1)] private int y = 1; [GroupDebug, SerializeField, Min(1)] private int y = 1;
[GroupDebug, SerializeField, Min(1)] private int z = 1; [GroupDebug, SerializeField, Min(1)] private int z = 1;
[GroupDebug, SerializeField] private Vector2 contact_offset_x = new(1f, 1.5f); [GroupDebug, SerializeField, Range(0f, 1f)] private float contact_offset = 1f;
[GroupDebug, SerializeField] private Vector2 contact_offset_y = new(1f, 1.5f);
protected override void DebugResize() protected override void DebugResize()
{ {
sizeX = Mathf.Max(1, x); sizeX = Mathf.Max(1, x);
sizeY = Mathf.Max(1, y); sizeY = Mathf.Max(1, y);
sizeZ = Mathf.Max(1, z); sizeZ = Mathf.Max(1, z);
offset_x.x = Mathf.Clamp(contact_offset_x.x, 0f, 2f); offset = Mathf.Clamp01(contact_offset);
offset_x.y = Mathf.Clamp(contact_offset_x.y, 0f, 2f);
offset_y.x = Mathf.Clamp(contact_offset_y.x, 0f, 2f);
offset_y.y = Mathf.Clamp(contact_offset_y.y, 0f, 2f);
} }
protected override void Generate() protected override void Generate()
@ -46,11 +41,9 @@ namespace Intrepid.Gameplay.Prototyping
vertices.ToArray(), vertices.ToArray(),
triangles.ToArray(), triangles.ToArray(),
uvs.ToArray())); uvs.ToArray()));
var offsetX = offset_x.x + offset_x.y; PrototypeModel.BoxCollider.size = new Vector3(sizeX + offset, sizeY, sizeZ + offset);
var offsetY = offset_y.x + offset_y.y; PrototypeModel.BoxCollider.center = Vector3.zero;
PrototypeModel.BoxCollider.size = new Vector3(sizeX + offsetX, sizeY, sizeZ + offsetY);
PrototypeModel.BoxCollider.center = new Vector3((offset_x.x - offset_x.y) / 2f, 0f, (offset_y.x - offset_y.y) / 2f);
PrototypeModel.transform.localPosition = new Vector3(0f, sizeY / 2f, 0f); PrototypeModel.transform.localPosition = new Vector3(0f, sizeY / 2f, 0f);
} }
} }

View File

@ -1,9 +1,6 @@
using UnityEngine;
namespace Intrepid.Gameplay.Prototyping namespace Intrepid.Gameplay.Prototyping
{ {
public abstract class GroundModelPrototype : ModelPrototype public abstract class GroundModelPrototype : ModelPrototype
{ {
public abstract void SetSize(Vector2Int size);
} }
} }

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Intrepid.Utilities; using Intrepid.Utilities;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
@ -13,13 +14,6 @@ namespace Intrepid.Gameplay.Prototyping
[GroupDebug, SerializeField, Min(1)] private int x = 1; [GroupDebug, SerializeField, Min(1)] private int x = 1;
[GroupDebug, SerializeField, Min(1)] private int z = 1; [GroupDebug, SerializeField, Min(1)] private int z = 1;
public override void SetSize(Vector2Int size)
{
x = size.x;
z = size.y;
SizeFitting();
}
protected override void DebugResize() protected override void DebugResize()
{ {
sizeX = Mathf.Max(1, x); sizeX = Mathf.Max(1, x);

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Intrepid.Utilities; using Intrepid.Utilities;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
@ -15,13 +16,6 @@ namespace Intrepid.Gameplay.Prototyping
[GroupDebug, SerializeField, Min(1)] private int x = 1; [GroupDebug, SerializeField, Min(1)] private int x = 1;
[GroupDebug, SerializeField, Min(1)] private int z = 1; [GroupDebug, SerializeField, Min(1)] private int z = 1;
public override void SetSize(Vector2Int size)
{
x = size.x;
z = size.y;
SizeFitting();
}
protected override void DebugResize() protected override void DebugResize()
{ {
sizeX = Mathf.Max(1, x); sizeX = Mathf.Max(1, x);

View File

@ -1,116 +0,0 @@
using System.Collections.Generic;
using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Intrepid.Gameplay.Prototyping
{
public class GroundStairModelPrototype : GroundModelPrototype
{
[GroupConfigurations, SerializeField, ReadOnly] private int sizeX = 1;
[GroupConfigurations, SerializeField, ReadOnly] private int sizeZ = 1;
[GroupDebug, SerializeField, Min(1)] private int x = 1;
[GroupDebug, SerializeField, Min(1)] private int z = 1;
public override void SetSize(Vector2Int size)
{
x = size.x;
z = size.y;
SizeFitting();
}
protected override void DebugResize()
{
x = Mathf.Max(1, x);
z = Mathf.Max(1, z);
sizeX = x;
sizeZ = z;
}
protected override void Generate()
{
// PrototypeModel.BuildMesh(BuildRampMeshData(new Vector3(sizeX, sizeZ * .75f, sizeZ)));
//
// PrototypeModel.BoxCollider.transform.localEulerAngles = new Vector3(-36.87f, 0f, 0f);
// PrototypeModel.BoxCollider.center = new Vector3(0f, -0.025f, 0f);
// PrototypeModel.BoxCollider.size = new Vector3(sizeX, 0.05f, sizeZ * 1.25f);
//
// PrototypeModel.transform.localPosition = new Vector3(0f, sizeZ * .5f, 0f);
PrototypeModel.BuildMesh(BuildRampMeshData(new Vector3(sizeX, sizeZ, sizeZ)));
PrototypeModel.BoxCollider.transform.localEulerAngles = new Vector3(-45f, 0f, 0f);
PrototypeModel.BoxCollider.center = new Vector3(0f, -0.025f, 0f);
PrototypeModel.BoxCollider.size = new Vector3(sizeX, 0.05f, sizeZ * 1.4142f);
PrototypeModel.transform.localPosition = new Vector3(0f, sizeZ * .5f, 0f);
}
private static MeshData BuildRampMeshData(Vector3 size)
{
var halfX = size.x * 0.5f;
var halfY = size.y * 0.5f;
var halfZ = size.z * 0.5f;
var bottomY = -halfY;
var topY = halfY;
var countX = Mathf.Max(1, Mathf.RoundToInt(size.x));
var countZ = Mathf.Max(1, Mathf.RoundToInt(size.z));
var vertices = new List<Vector3>();
var triangles = new List<int>();
var uvs = new List<Vector2>();
var rampStep = new Vector3(
0f,
size.y / countZ,
size.z / countZ
);
// Ramp surface
MeshUtils.AddGridFace(
vertices,
triangles,
uvs,
origin: new Vector3(halfX, bottomY, -halfZ),
axisU: Vector3.left,
axisV: rampStep,
countU: countX,
countV: countZ
);
// Left
MeshUtils.AddTriangle(
vertices,
triangles,
uvs,
new Vector3(-halfX, bottomY, -halfZ),
new Vector3(-halfX, bottomY, halfZ),
new Vector3(-halfX, topY, halfZ),
new Vector2(0f, 0f),
new Vector2(size.z, 0f),
new Vector2(size.z, size.y)
);
// Right
MeshUtils.AddTriangle(
vertices,
triangles,
uvs,
new Vector3(halfX, bottomY, -halfZ),
new Vector3(halfX, topY, halfZ),
new Vector3(halfX, bottomY, halfZ),
new Vector2(0f, 0f),
new Vector2(size.z, size.y),
new Vector2(size.z, 0f)
);
return new MeshData(
vertices.ToArray(),
triangles.ToArray(),
uvs.ToArray()
);
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 3a3b1270c87c4456bdc61721ca19132f
timeCreated: 1781674851

View File

@ -43,7 +43,7 @@ namespace Intrepid.Gameplay.Prototyping
} }
[GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)] [GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
protected void SizeFitting() private void SetSize()
{ {
DebugResize(); DebugResize();
if (PrototypeModel.IsNull()) return; if (PrototypeModel.IsNull()) return;