mirror of
https://github.com/boudji-ludwig-pett/cnam-geometry-dash.git
synced 2025-05-18 12:02:58 +02:00
Map editor design (#59)
This commit is contained in:
parent
97b473cb01
commit
7f2db297fa
@ -109,6 +109,7 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
>>>>>>> develop
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
@ -147,8 +148,7 @@ TextureImporter:
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
RegularBlock01_0: 229215520534054086
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
|
@ -147,8 +147,7 @@ TextureImporter:
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
CubePortalLabelled_0: -799402021850825835
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
|
@ -147,8 +147,7 @@ TextureImporter:
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
ShipPortalLabelled_0: -1834338360412052916
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
|
@ -222,63 +222,6 @@ MonoBehaviour:
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
--- !u!1001 &109370708
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 1771296619209216840, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: BonusSlowSpeed
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6543394447596783970, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -5.4423084
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6543394447596783970, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -2.783749
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6543394447596783970, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6543394447596783970, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6543394447596783970, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6543394447596783970, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6543394447596783970, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6543394447596783970, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6543394447596783970, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6543394447596783970, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: e9dda45aef9258745a40efb48437d584, type: 3}
|
||||
--- !u!1 &245275147
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -434,6 +377,63 @@ CanvasRenderer:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 487176671}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1001 &496264820
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3025146551836412649, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: BonusBoostSpeed
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7134261581051338486, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -2
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7134261581051338486, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -2.88
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7134261581051338486, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7134261581051338486, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 0.99681437
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7134261581051338486, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7134261581051338486, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7134261581051338486, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0.079757296
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7134261581051338486, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7134261581051338486, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7134261581051338486, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: -9.149
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 5d01d2d55c6c25541b0db90186e76c2b, type: 3}
|
||||
--- !u!1 &519420028
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -7475,4 +7475,4 @@ SceneRoots:
|
||||
- {fileID: 1371294550}
|
||||
- {fileID: 521952202}
|
||||
- {fileID: 555497623}
|
||||
- {fileID: 109370708}
|
||||
- {fileID: 496264820}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class LevelEditor : MonoBehaviour
|
||||
@ -34,6 +35,21 @@ public class LevelEditor : MonoBehaviour
|
||||
GenerateButtons();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (IsPointerOverUI()) return;
|
||||
|
||||
if (isPlacingBlock && currentBlock != null)
|
||||
HandleBlockPlacement();
|
||||
else
|
||||
HandleBlockSelection();
|
||||
|
||||
HandleBlockResizing();
|
||||
HandleBlockDeletion();
|
||||
}
|
||||
|
||||
#region UI
|
||||
|
||||
void LoadPrefabs()
|
||||
{
|
||||
blockPrefabs.AddRange(Resources.LoadAll<GameObject>("Prefabs"));
|
||||
@ -41,21 +57,9 @@ public class LevelEditor : MonoBehaviour
|
||||
|
||||
void GenerateButtons()
|
||||
{
|
||||
if (buttonPrefabTemplate == null)
|
||||
{
|
||||
Debug.LogError("LevelEditor.GenerateButtons(): buttonPrefabTemplate n’est pas assigné !");
|
||||
return;
|
||||
}
|
||||
if (blockGroupContainer == null)
|
||||
{
|
||||
Debug.LogError("LevelEditor.GenerateButtons(): blockGroupContainer n’est pas assigné !");
|
||||
return;
|
||||
}
|
||||
ClearCurrentButtons();
|
||||
|
||||
Transform container = blockGroupContainer;
|
||||
|
||||
if (container == null || buttonPrefabTemplate == null)
|
||||
if (blockGroupContainer == null || buttonPrefabTemplate == null)
|
||||
{
|
||||
Debug.LogError("UI Container ou prefab de bouton manquant.");
|
||||
return;
|
||||
@ -66,34 +70,10 @@ public class LevelEditor : MonoBehaviour
|
||||
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
GameObject button = Instantiate(buttonPrefabTemplate, container);
|
||||
GameObject button = Instantiate(buttonPrefabTemplate, blockGroupContainer);
|
||||
button.SetActive(true);
|
||||
|
||||
Transform canvas = button.transform.Find("Canvas");
|
||||
Transform bg = canvas?.Find("BlankSquare");
|
||||
Transform icon = canvas?.Find("PrefabIcon");
|
||||
|
||||
if (bg == null || icon == null)
|
||||
{
|
||||
Destroy(button);
|
||||
continue;
|
||||
}
|
||||
|
||||
float xOffset = -375f + (i - start) * 125f;
|
||||
bg.GetComponent<RectTransform>().anchoredPosition = new Vector2(xOffset, bg.GetComponent<RectTransform>().anchoredPosition.y);
|
||||
icon.GetComponent<RectTransform>().anchoredPosition = new Vector2(xOffset, icon.GetComponent<RectTransform>().anchoredPosition.y);
|
||||
|
||||
Image bgImage = bg.GetComponent<Image>();
|
||||
Image iconImage = icon.GetComponent<Image>();
|
||||
|
||||
bgImage.sprite = Resources.Load<Sprite>("InGame/ButtonSkin/BlankSquare");
|
||||
iconImage.sprite = blockPrefabs[i].GetComponent<SpriteRenderer>()?.sprite;
|
||||
|
||||
string prefabName = blockPrefabs[i].name.ToLower();
|
||||
if (prefabName.Contains("smallspike") || prefabName.Contains("smallobstacle"))
|
||||
icon.GetComponent<RectTransform>().sizeDelta = new Vector2(50, 25);
|
||||
else
|
||||
icon.GetComponent<RectTransform>().sizeDelta = new Vector2(50, 50);
|
||||
SetupButtonVisual(button.transform, blockPrefabs[i], i - start);
|
||||
|
||||
GameObject prefab = blockPrefabs[i];
|
||||
button.GetComponent<Button>().onClick.AddListener(() => SelectPrefab(prefab));
|
||||
@ -101,18 +81,40 @@ public class LevelEditor : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
void SetupButtonVisual(Transform buttonTransform, GameObject prefab, int index)
|
||||
{
|
||||
Transform canvas = buttonTransform.Find("Canvas");
|
||||
Transform bg = canvas?.Find("BlankSquare");
|
||||
Transform icon = canvas?.Find("PrefabIcon");
|
||||
|
||||
if (bg == null || icon == null)
|
||||
{
|
||||
Destroy(buttonTransform.gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
float xOffset = -375f + index * 125f;
|
||||
bg.GetComponent<RectTransform>().anchoredPosition = new Vector2(xOffset, bg.GetComponent<RectTransform>().anchoredPosition.y);
|
||||
icon.GetComponent<RectTransform>().anchoredPosition = new Vector2(xOffset, icon.GetComponent<RectTransform>().anchoredPosition.y);
|
||||
|
||||
bg.GetComponent<Image>().sprite = Resources.Load<Sprite>("InGame/ButtonSkin/BlankSquare");
|
||||
icon.GetComponent<Image>().sprite = prefab.GetComponent<SpriteRenderer>()?.sprite;
|
||||
|
||||
icon.GetComponent<RectTransform>().sizeDelta = prefab.name.ToLower().Contains("small")
|
||||
? new Vector2(50, 25)
|
||||
: new Vector2(50, 50);
|
||||
}
|
||||
|
||||
void ClearCurrentButtons()
|
||||
{
|
||||
foreach (var button in currentButtons)
|
||||
Destroy(button);
|
||||
|
||||
currentButtons.Clear();
|
||||
}
|
||||
|
||||
public void NextPage()
|
||||
{
|
||||
int maxPage = 3;
|
||||
Debug.Log(currentPage);
|
||||
int maxPage = Mathf.CeilToInt(blockPrefabs.Count / (float)buttonsPerPage);
|
||||
if (currentPage < maxPage - 1)
|
||||
{
|
||||
currentPage++;
|
||||
@ -122,7 +124,6 @@ public class LevelEditor : MonoBehaviour
|
||||
|
||||
public void PreviousPage()
|
||||
{
|
||||
Debug.Log(currentPage);
|
||||
if (currentPage > 0)
|
||||
{
|
||||
currentPage--;
|
||||
@ -130,308 +131,196 @@ public class LevelEditor : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Placement
|
||||
|
||||
void SelectPrefab(GameObject prefab)
|
||||
{
|
||||
if (isPlacingBlock) return;
|
||||
|
||||
string name = prefab.name.ToLower();
|
||||
|
||||
if (name.Contains("portal"))
|
||||
currentScale = new Vector3(0.5f, 0.5f, 1);
|
||||
else if (name.Contains("small"))
|
||||
currentScale = new Vector3(0.15f, 0.07f, 1);
|
||||
else if (name.Contains("spike"))
|
||||
currentScale = new Vector3(0.15f, 0.15f, 1);
|
||||
else if (name.Contains("block"))
|
||||
currentScale = new Vector3(0.2f, 0.2f, 1);
|
||||
else if (name.Contains("bonus"))
|
||||
currentScale = new Vector3(0.3f, 0.3f, 1);
|
||||
else
|
||||
currentScale = new Vector3(1f, 1f, 1);
|
||||
|
||||
currentScale = DetermineScaleFromName(prefab.name);
|
||||
InstantiateAndPrepare(prefab, currentScale);
|
||||
}
|
||||
void Update()
|
||||
|
||||
Vector3 DetermineScaleFromName(string name)
|
||||
{
|
||||
// Déplacement de l'objet en cours de placement
|
||||
if (isPlacingBlock && currentBlock != null)
|
||||
name = name.ToLower();
|
||||
|
||||
if (name.Contains("portal")) return new Vector3(0.5f, 0.5f, 1);
|
||||
if (name.Contains("small")) return new Vector3(0.15f, 0.07f, 1);
|
||||
if (name.Contains("spike")) return new Vector3(0.15f, 0.15f, 1);
|
||||
if (name.Contains("block")) return new Vector3(0.2f, 0.2f, 1);
|
||||
if (name.Contains("bonus")) return new Vector3(0.3f, 0.3f, 1);
|
||||
|
||||
return new Vector3(1f, 1f, 1);
|
||||
}
|
||||
|
||||
void HandleBlockPlacement()
|
||||
{
|
||||
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
currentBlock.transform.position = new Vector3(Mathf.Round(mousePos.x), Mathf.Round(mousePos.y), -1);
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.R))
|
||||
HandleBlockRotation();
|
||||
|
||||
if (!currentBlock.name.ToLower().Contains("portal"))
|
||||
{
|
||||
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
currentBlock.transform.position = new Vector3(Mathf.Round(mousePos.x), Mathf.Round(mousePos.y), -1);
|
||||
|
||||
if (currentBlock != null && Input.GetKeyDown(KeyCode.R))
|
||||
float scroll = Input.GetAxis("Mouse ScrollWheel");
|
||||
if (scroll != 0)
|
||||
{
|
||||
HandleBlockRotation(); // ✅ Nouvelle rotation
|
||||
}
|
||||
|
||||
if (!currentBlock.name.ToLower().Contains("portal"))
|
||||
{
|
||||
float scroll = Input.GetAxis("Mouse ScrollWheel");
|
||||
if (scroll != 0)
|
||||
{
|
||||
float newScale = Mathf.Max(0.1f, currentScale.x + scroll * scaleStep);
|
||||
currentScale = new Vector3(newScale, newScale, 1);
|
||||
currentBlock.transform.localScale = currentScale;
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
Collider2D[] overlaps = Physics2D.OverlapBoxAll(
|
||||
currentBlock.transform.position,
|
||||
currentBlock.GetComponent<Collider2D>().bounds.size,
|
||||
0f
|
||||
);
|
||||
|
||||
if (overlaps.Length > 1)
|
||||
{
|
||||
Debug.Log("Placement annulé : un objet est déjà présent à cet endroit.");
|
||||
return;
|
||||
}
|
||||
|
||||
PlaceBlock();
|
||||
float newScale = Mathf.Max(0.1f, currentScale.x + scroll * scaleStep);
|
||||
currentScale = new Vector3(newScale, newScale, 1);
|
||||
currentBlock.transform.localScale = currentScale;
|
||||
}
|
||||
}
|
||||
else if (Input.GetMouseButtonDown(0)) // Clic gauche pour reprendre un objet déjà placé
|
||||
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
if (!IsPlacementValid())
|
||||
{
|
||||
Debug.Log("Placement annulé : collision.");
|
||||
return;
|
||||
}
|
||||
|
||||
PlaceBlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsPlacementValid()
|
||||
{
|
||||
Collider2D[] overlaps = Physics2D.OverlapBoxAll(
|
||||
currentBlock.transform.position,
|
||||
currentBlock.GetComponent<Collider2D>().bounds.size,
|
||||
0f
|
||||
);
|
||||
|
||||
foreach (var col in overlaps)
|
||||
{
|
||||
if (col.transform.root == currentBlock.transform || col.CompareTag("Ground"))
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleBlockSelection()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
Collider2D hit = Physics2D.OverlapPoint(mousePos);
|
||||
|
||||
if (hit != null && hit.transform != null)
|
||||
if (hit != null && !hit.CompareTag("Ground"))
|
||||
{
|
||||
if (hit.CompareTag("Ground"))
|
||||
{
|
||||
Debug.Log("Impossible de déplacer le sol (tag Ground).");
|
||||
return;
|
||||
}
|
||||
currentBlock = hit.gameObject;
|
||||
isPlacingBlock = true;
|
||||
currentScale = currentBlock.transform.localScale;
|
||||
Debug.Log($"Déplacement de l'objet : {currentBlock.name}");
|
||||
return;
|
||||
Debug.Log($"Bloc sélectionné : {currentBlock.name}");
|
||||
}
|
||||
}
|
||||
|
||||
// Redimensionnement d'un objet déjà placé
|
||||
if (Input.GetMouseButtonDown(0) && Input.GetKey(KeyCode.LeftShift) && !isPlacingBlock)
|
||||
{
|
||||
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
Collider2D hit = Physics2D.OverlapPoint(mousePos);
|
||||
|
||||
if (hit != null && hit.transform != null && !hit.CompareTag("Ground"))
|
||||
{
|
||||
resizingTarget = hit.gameObject;
|
||||
originalMousePos = mousePos;
|
||||
originalScale = resizingTarget.transform.localScale;
|
||||
|
||||
Vector2 localClick = mousePos - (Vector2)resizingTarget.transform.position;
|
||||
float ratio = resizingTarget.GetComponent<Collider2D>().bounds.size.x /
|
||||
resizingTarget.GetComponent<Collider2D>().bounds.size.y;
|
||||
|
||||
currentResizeAxis = Mathf.Abs(localClick.x) > Mathf.Abs(localClick.y * ratio)
|
||||
? ResizeAxis.Horizontal
|
||||
: ResizeAxis.Vertical;
|
||||
|
||||
isResizing = true;
|
||||
Debug.Log($"Début de redimensionnement : {resizingTarget.name}, axe = {currentResizeAxis}");
|
||||
}
|
||||
}
|
||||
|
||||
if (isResizing && resizingTarget != null)
|
||||
{
|
||||
Vector3 currentMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
Vector3 delta = currentMousePos - originalMousePos;
|
||||
|
||||
Vector3 newScale = originalScale;
|
||||
|
||||
if (currentResizeAxis == ResizeAxis.Horizontal)
|
||||
newScale.x = Mathf.Max(0.1f, originalScale.x + delta.x);
|
||||
else if (currentResizeAxis == ResizeAxis.Vertical)
|
||||
newScale.y = Mathf.Max(0.1f, originalScale.y + delta.y);
|
||||
|
||||
// Temporarily apply the new scale for collision testing
|
||||
Vector3 originalPos = resizingTarget.transform.position;
|
||||
resizingTarget.transform.localScale = newScale;
|
||||
|
||||
Bounds bounds = resizingTarget.GetComponent<Collider2D>().bounds;
|
||||
Collider2D[] overlaps = Physics2D.OverlapBoxAll(bounds.center, bounds.size, 0f);
|
||||
|
||||
bool hasCollision = false;
|
||||
foreach (var col in overlaps)
|
||||
{
|
||||
if (col.gameObject != resizingTarget)
|
||||
{
|
||||
hasCollision = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasCollision)
|
||||
{
|
||||
resizingTarget.transform.localScale = originalScale; // revert
|
||||
Debug.Log("Étirement annulé : collision détectée.");
|
||||
}
|
||||
|
||||
if (Input.GetMouseButtonUp(0))
|
||||
{
|
||||
isResizing = false;
|
||||
resizingTarget = null;
|
||||
currentResizeAxis = ResizeAxis.None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Clic droit pour supprimer un objet déjà placé (sauf le sol)
|
||||
if (Input.GetMouseButtonDown(1))
|
||||
{
|
||||
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
Collider2D hit = Physics2D.OverlapPoint(mousePos);
|
||||
|
||||
if (hit != null && hit.transform != null)
|
||||
{
|
||||
if (hit.CompareTag("Ground"))
|
||||
{
|
||||
Debug.Log("Impossible de supprimer le sol (tag Ground).");
|
||||
return;
|
||||
}
|
||||
|
||||
Destroy(hit.gameObject);
|
||||
Debug.Log($"Objet supprimé : {hit.name}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PlaceBlock()
|
||||
{
|
||||
bool skipVerticalSnap = false;
|
||||
string name = currentBlock.name.ToLower();
|
||||
|
||||
if (currentBlock.name.ToLower().Contains("smallobstacle") || currentBlock.name.ToLower().Contains("portal"))
|
||||
bool grounded = name.Contains("spike") || name.Contains("bonus") || name.Contains("smallobstacle");
|
||||
|
||||
if (grounded)
|
||||
{
|
||||
skipVerticalSnap = true; // On saute l'alignement vertical pour ces cas-là
|
||||
StickBlockToGround();
|
||||
}
|
||||
else if (!ShouldSkipVerticalSnap(name))
|
||||
{
|
||||
SnapBlockVertically();
|
||||
TrySnapToNearbyBlock(); // ✅ seulement ici
|
||||
}
|
||||
else
|
||||
{
|
||||
TrySnapToNearbyBlock(); // ex: autres blocs
|
||||
}
|
||||
|
||||
if (!skipVerticalSnap)
|
||||
{
|
||||
Vector2 origin = currentBlock.transform.position;
|
||||
RaycastHit2D[] hitsBelow = Physics2D.RaycastAll(origin, Vector2.down, 100f);
|
||||
|
||||
float highestY = -Mathf.Infinity;
|
||||
GameObject bestTargetBelow = null;
|
||||
|
||||
foreach (var hit in hitsBelow)
|
||||
{
|
||||
if (hit.collider != null && hit.collider.gameObject != currentBlock)
|
||||
{
|
||||
float topOfObject = hit.collider.bounds.max.y;
|
||||
if (topOfObject > highestY)
|
||||
{
|
||||
highestY = topOfObject;
|
||||
bestTargetBelow = hit.collider.gameObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestTargetBelow != null)
|
||||
{
|
||||
float height = currentBlock.GetComponent<Collider2D>().bounds.size.y;
|
||||
currentBlock.transform.position = new Vector3(currentBlock.transform.position.x, highestY + height / 2f, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
float height = currentBlock.GetComponent<Collider2D>().bounds.size.y;
|
||||
currentBlock.transform.position = new Vector3(currentBlock.transform.position.x, height / 2f, -1);
|
||||
}
|
||||
}
|
||||
// ➔ Toujours essayer de snap sur la droite et en bas même pour Portal et SmallObstacle
|
||||
TrySnapToNearbyBlock();
|
||||
|
||||
isPlacingBlock = false;
|
||||
currentBlock = null;
|
||||
}
|
||||
|
||||
|
||||
private void TrySnapToNearbyBlock()
|
||||
void StickBlockToGround()
|
||||
{
|
||||
if (currentBlock == null)
|
||||
return;
|
||||
Collider2D col = currentBlock.GetComponent<Collider2D>();
|
||||
Bounds bounds = col.bounds;
|
||||
|
||||
Collider2D blockCollider = currentBlock.GetComponent<Collider2D>();
|
||||
Bounds bounds = blockCollider.bounds;
|
||||
Vector2 origin = new Vector2(bounds.center.x, bounds.min.y);
|
||||
float rayLength = 100f; // on descend loin pour être sûr de toucher le sol
|
||||
|
||||
float snapDistance = 1f; // Distance de snap (en Unity units)
|
||||
RaycastHit2D hit = Physics2D.Raycast(origin, Vector2.down, rayLength);
|
||||
|
||||
// Zone de scan à droite
|
||||
Vector2 rightAreaStart = new Vector2(bounds.max.x, bounds.min.y);
|
||||
Vector2 rightAreaEnd = new Vector2(bounds.max.x + snapDistance, bounds.max.y);
|
||||
|
||||
// Zone de scan à gauche
|
||||
Vector2 leftAreaStart = new Vector2(bounds.min.x - snapDistance, bounds.min.y);
|
||||
Vector2 leftAreaEnd = new Vector2(bounds.min.x, bounds.max.y);
|
||||
|
||||
// Zone de scan en dessous
|
||||
Vector2 bottomAreaStart = new Vector2(bounds.min.x, bounds.min.y - snapDistance);
|
||||
Vector2 bottomAreaEnd = new Vector2(bounds.max.x, bounds.min.y);
|
||||
|
||||
// Zone de scan au dessus
|
||||
Vector2 topAreaStart = new Vector2(bounds.min.x, bounds.max.y);
|
||||
Vector2 topAreaEnd = new Vector2(bounds.max.x, bounds.max.y + snapDistance);
|
||||
|
||||
Collider2D[] hitsRight = Physics2D.OverlapAreaAll(rightAreaStart, rightAreaEnd);
|
||||
Collider2D[] hitsLeft = Physics2D.OverlapAreaAll(leftAreaStart, leftAreaEnd);
|
||||
Collider2D[] hitsBelow = Physics2D.OverlapAreaAll(bottomAreaStart, bottomAreaEnd);
|
||||
Collider2D[] hitsAbove = Physics2D.OverlapAreaAll(topAreaStart, topAreaEnd);
|
||||
|
||||
// ➔ Priorité : droite > gauche > bas > haut
|
||||
|
||||
foreach (var hit in hitsRight)
|
||||
if (hit.collider != null && hit.collider.gameObject != currentBlock)
|
||||
{
|
||||
if (hit != null && hit.gameObject != currentBlock)
|
||||
{
|
||||
float theirLeft = hit.bounds.min.x;
|
||||
float ourWidth = bounds.size.x;
|
||||
currentBlock.transform.position = new Vector3(theirLeft - ourWidth / 2f, currentBlock.transform.position.y, -1);
|
||||
Debug.Log("✅ Snap automatique à droite !");
|
||||
return;
|
||||
}
|
||||
}
|
||||
float topY = hit.collider.bounds.max.y;
|
||||
float height = bounds.size.y;
|
||||
float newY = topY + height / 2f;
|
||||
|
||||
foreach (var hit in hitsLeft)
|
||||
{
|
||||
if (hit != null && hit.gameObject != currentBlock)
|
||||
{
|
||||
float theirRight = hit.bounds.max.x;
|
||||
float ourWidth = bounds.size.x;
|
||||
currentBlock.transform.position = new Vector3(theirRight + ourWidth / 2f, currentBlock.transform.position.y, -1);
|
||||
Debug.Log("✅ Snap automatique à gauche !");
|
||||
return;
|
||||
}
|
||||
currentBlock.transform.position = new Vector3(currentBlock.transform.position.x, newY, -1f);
|
||||
Debug.Log($"📌 Bloc descendu sur {hit.collider.name} à Y={newY}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("❗ Aucun support trouvé en dessous pour aligner le bloc.");
|
||||
}
|
||||
}
|
||||
|
||||
bool ShouldSkipVerticalSnap(string name)
|
||||
{
|
||||
name = name.ToLower();
|
||||
return name.Contains("smallobstacle") || name.Contains("portal");
|
||||
}
|
||||
|
||||
void SnapBlockVertically()
|
||||
{
|
||||
Collider2D col = currentBlock.GetComponent<Collider2D>();
|
||||
Bounds bounds = col.bounds;
|
||||
|
||||
float snapThreshold = 0.1f; // ➜ 0.1 unité = environ 2 pixels
|
||||
|
||||
Vector2 checkStart = new Vector2(bounds.min.x, bounds.min.y - snapThreshold);
|
||||
Vector2 checkEnd = new Vector2(bounds.max.x, bounds.min.y);
|
||||
|
||||
Collider2D[] hitsBelow = Physics2D.OverlapAreaAll(checkStart, checkEnd);
|
||||
|
||||
float highestY = -Mathf.Infinity;
|
||||
GameObject bestTarget = null;
|
||||
|
||||
foreach (var hit in hitsBelow)
|
||||
{
|
||||
if (hit != null && hit.gameObject != currentBlock)
|
||||
if (hit == null || hit.gameObject == currentBlock || hit.transform.IsChildOf(currentBlock.transform))
|
||||
continue;
|
||||
|
||||
float top = hit.bounds.max.y;
|
||||
if (top > highestY)
|
||||
{
|
||||
float theirTop = hit.bounds.max.y;
|
||||
float ourHeight = bounds.size.y;
|
||||
currentBlock.transform.position = new Vector3(currentBlock.transform.position.x, theirTop + ourHeight / 2f, -1);
|
||||
Debug.Log("✅ Snap automatique en bas !");
|
||||
return;
|
||||
highestY = top;
|
||||
bestTarget = hit.gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var hit in hitsAbove)
|
||||
if (bestTarget != null)
|
||||
{
|
||||
if (hit != null && hit.gameObject != currentBlock)
|
||||
{
|
||||
float theirBottom = hit.bounds.min.y;
|
||||
float ourHeight = bounds.size.y;
|
||||
currentBlock.transform.position = new Vector3(currentBlock.transform.position.x, theirBottom - ourHeight / 2f, -1);
|
||||
Debug.Log("✅ Snap automatique en haut !");
|
||||
return;
|
||||
}
|
||||
float blockHeight = bounds.size.y;
|
||||
float snapY = highestY + blockHeight / 2f;
|
||||
|
||||
currentBlock.transform.position = new Vector3(currentBlock.transform.position.x, snapY, -1f);
|
||||
Debug.Log($"✅ Snap vertical à {snapY} sur {bestTarget.name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("❌ Aucun bloc trouvé assez proche en dessous pour snap.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InstantiateAndPrepare(GameObject prefab, Vector3? scaleOverride = null)
|
||||
{
|
||||
GameObject obj = Instantiate(prefab);
|
||||
@ -439,15 +328,194 @@ public class LevelEditor : MonoBehaviour
|
||||
obj.transform.localScale = scaleOverride ?? currentScale;
|
||||
|
||||
try { obj.tag = prefab.name; }
|
||||
catch { Debug.LogWarning($"Le tag '{prefab.name}' n'existe pas. Ajoutez-le dans Project Settings > Tags."); }
|
||||
catch { Debug.LogWarning($"Le tag '{prefab.name}' est manquant."); }
|
||||
|
||||
currentBlock = obj;
|
||||
isPlacingBlock = true;
|
||||
}
|
||||
|
||||
private void HandleBlockRotation()
|
||||
void HandleBlockRotation()
|
||||
{
|
||||
currentBlock.transform.Rotate(0f, 0f, -90f); // ➔ Rotation de 90° dans le sens horaire
|
||||
currentBlock.transform.Rotate(0f, 0f, -90f);
|
||||
Debug.Log("🔄 Bloc pivoté de 90° !");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resizing & Deletion
|
||||
|
||||
void HandleBlockResizing()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0) && Input.GetKey(KeyCode.LeftShift) && !isPlacingBlock)
|
||||
{
|
||||
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
Collider2D hit = Physics2D.OverlapPoint(mousePos);
|
||||
|
||||
if (hit != null && !hit.CompareTag("Ground"))
|
||||
{
|
||||
BeginResizing(hit.gameObject, mousePos);
|
||||
}
|
||||
}
|
||||
|
||||
if (isResizing && resizingTarget != null)
|
||||
{
|
||||
PerformResizing();
|
||||
}
|
||||
}
|
||||
|
||||
void BeginResizing(GameObject target, Vector2 mousePos)
|
||||
{
|
||||
resizingTarget = target;
|
||||
originalMousePos = mousePos;
|
||||
originalScale = target.transform.localScale;
|
||||
|
||||
Vector2 localClick = mousePos - (Vector2)target.transform.position;
|
||||
float ratio = target.GetComponent<Collider2D>().bounds.size.x / target.GetComponent<Collider2D>().bounds.size.y;
|
||||
|
||||
currentResizeAxis = Mathf.Abs(localClick.x) > Mathf.Abs(localClick.y * ratio)
|
||||
? ResizeAxis.Horizontal
|
||||
: ResizeAxis.Vertical;
|
||||
|
||||
isResizing = true;
|
||||
Debug.Log($"🧰 Début du redimensionnement : {target.name} (axe : {currentResizeAxis})");
|
||||
}
|
||||
|
||||
void PerformResizing()
|
||||
{
|
||||
Vector3 currentMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
Vector3 delta = currentMousePos - originalMousePos;
|
||||
|
||||
Vector3 newScale = originalScale;
|
||||
if (currentResizeAxis == ResizeAxis.Horizontal)
|
||||
newScale.x = Mathf.Max(0.1f, originalScale.x + delta.x);
|
||||
else if (currentResizeAxis == ResizeAxis.Vertical)
|
||||
newScale.y = Mathf.Max(0.1f, originalScale.y + delta.y);
|
||||
|
||||
resizingTarget.transform.localScale = newScale;
|
||||
|
||||
if (IsOverlapping(resizingTarget))
|
||||
{
|
||||
resizingTarget.transform.localScale = originalScale;
|
||||
Debug.Log("❌ Redimensionnement annulé : collision.");
|
||||
}
|
||||
|
||||
if (Input.GetMouseButtonUp(0))
|
||||
{
|
||||
isResizing = false;
|
||||
resizingTarget = null;
|
||||
currentResizeAxis = ResizeAxis.None;
|
||||
Debug.Log("✅ Fin du redimensionnement");
|
||||
}
|
||||
}
|
||||
|
||||
bool IsOverlapping(GameObject obj)
|
||||
{
|
||||
Bounds bounds = obj.GetComponent<Collider2D>().bounds;
|
||||
Collider2D[] overlaps = Physics2D.OverlapBoxAll(bounds.center, bounds.size, 0f);
|
||||
|
||||
foreach (var col in overlaps)
|
||||
{
|
||||
if (col.gameObject != obj)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HandleBlockDeletion()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(1))
|
||||
{
|
||||
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
Collider2D hit = Physics2D.OverlapPoint(mousePos);
|
||||
|
||||
if (hit != null && !hit.CompareTag("Ground"))
|
||||
{
|
||||
GameObject toDestroy = hit.gameObject;
|
||||
|
||||
// ✅ Cas spécial : ObstacleBlock ou ses enfants
|
||||
if (toDestroy.name.Contains("ObstacleSafer") || toDestroy.name.Contains("ObstacleKiller"))
|
||||
{
|
||||
Transform parent = toDestroy.transform.parent;
|
||||
if (parent != null && parent.name.Contains("ObstacleBlock"))
|
||||
{
|
||||
toDestroy = parent.gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
if (toDestroy == currentBlock)
|
||||
{
|
||||
currentBlock = null;
|
||||
isPlacingBlock = false;
|
||||
}
|
||||
|
||||
Destroy(toDestroy);
|
||||
Debug.Log($"🗑️ Supprimé : {toDestroy.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utility
|
||||
|
||||
bool IsPointerOverUI()
|
||||
{
|
||||
return EventSystem.current != null && EventSystem.current.IsPointerOverGameObject();
|
||||
}
|
||||
|
||||
void TrySnapToNearbyBlock()
|
||||
{
|
||||
if (currentBlock == null) return;
|
||||
|
||||
Collider2D blockCollider = currentBlock.GetComponent<Collider2D>();
|
||||
Bounds bounds = blockCollider.bounds;
|
||||
float snapDistance = 1f;
|
||||
|
||||
Vector2[] directions =
|
||||
{
|
||||
Vector2.right, Vector2.left, Vector2.down, Vector2.up
|
||||
};
|
||||
|
||||
foreach (var dir in directions)
|
||||
{
|
||||
Vector2 extent2D = new Vector2(bounds.extents.x, bounds.extents.y);
|
||||
Vector2 start = (Vector2)bounds.center + dir * (extent2D + Vector2.one * (snapDistance / 2f));
|
||||
Collider2D[] hits = Physics2D.OverlapCircleAll(start, snapDistance);
|
||||
|
||||
foreach (var hit in hits)
|
||||
{
|
||||
if (hit != null && hit.gameObject != currentBlock)
|
||||
{
|
||||
SnapToTarget(hit, dir);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SnapToTarget(Collider2D hit, Vector2 dir)
|
||||
{
|
||||
Bounds hitBounds = hit.bounds;
|
||||
Bounds ourBounds = currentBlock.GetComponent<Collider2D>().bounds;
|
||||
|
||||
Vector3 newPos = currentBlock.transform.position;
|
||||
|
||||
if (dir == Vector2.right)
|
||||
newPos.x = hitBounds.min.x - ourBounds.size.x / 2f;
|
||||
else if (dir == Vector2.left)
|
||||
newPos.x = hitBounds.max.x + ourBounds.size.x / 2f;
|
||||
else if (dir == Vector2.down)
|
||||
newPos.y = hitBounds.max.y + ourBounds.size.y / 2f;
|
||||
else if (dir == Vector2.up)
|
||||
newPos.y = hitBounds.min.y - ourBounds.size.y / 2f;
|
||||
|
||||
currentBlock.transform.position = new Vector3(newPos.x, newPos.y, -1);
|
||||
Debug.Log("✅ Snap à " + dir);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
// TODO : Sauvegarde du niveau
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user