BITFALL/Assets/GSpawn - Level Designer/Scripts/Level Design/Object Spawn/PropsObjectSpawn.cs

332 lines
15 KiB
C#

#if UNITY_EDITOR
using UnityEngine;
using System;
using System.Collections.Generic;
using UnityEditor;
namespace GSpawn
{
public class PropsObjectSpawn : ObjectSpawnTool
{
[NonSerialized]
private ObjectSpawnGuideSettings _spawnGuideSettings;
[NonSerialized]
private ObjectSurfaceSnapSettings _surfaceSnapSettings;
[NonSerialized]
private ObjectDragSpawnSettings _dragSpawnSettings;
[NonSerialized]
private TerrainFlattenSettings _terrainFlattenSettings;
[SerializeField]
private ObjectSurfaceSnapSession _surfaceSnapSession;
[SerializeField]
private ObjectMirrorGizmo _mirrorGizmo;
[NonSerialized]
private ObjectMirrorGizmoSettings _mirrorGizmoSettings;
[NonSerialized]
private Vector3 _lastSurfacePickPoint;
[NonSerialized]
private SceneRaycastFilter _pickPrefabRaycastFilter = new SceneRaycastFilter();
[NonSerialized]
private List<OBB> _obbBuffer = new List<OBB>();
[NonSerialized]
private List<Vector3> _vector3Buffer = new List<Vector3>();
[NonSerialized]
private Vector3[] _terrainPatchCorners = new Vector3[4];
[SerializeField]
private int _decorRuleIndex = 0;
[NonSerialized]
private DecorRuleApplyResult _prevDecorRuleApplyResult = new DecorRuleApplyResult();
[NonSerialized]
private DecorRuleApplyResult _decorRuleApplyResult = new DecorRuleApplyResult();
[NonSerialized]
private GameObject _surfaceObjectPrefab = null;
[NonSerialized]
private GameObject _prevSurfaceObjectPrefab = null;
private ObjectSurfaceSnapSession surfaceSnapSession
{
get
{
if (_surfaceSnapSession == null)
{
_surfaceSnapSession = CreateInstance<ObjectSurfaceSnapSession>();
_surfaceSnapSession.sharedSettings = surfaceSnapSettings;
}
return _surfaceSnapSession;
}
}
public ObjectSurfaceSnapSettings surfaceSnapSettings
{
get
{
if (_surfaceSnapSettings == null) _surfaceSnapSettings = AssetDbEx.loadScriptableObject<ObjectSurfaceSnapSettings>(PluginFolders.settings, typeof(PropsObjectSpawn).Name + "_" + typeof(ObjectSurfaceSnapSettings).Name);
return _surfaceSnapSettings;
}
}
public ObjectDragSpawnSettings dragSpawnSettings
{
get
{
if (_dragSpawnSettings == null) _dragSpawnSettings = AssetDbEx.loadScriptableObject<ObjectDragSpawnSettings>(PluginFolders.settings, typeof(PropsObjectSpawn).Name + "_" + typeof(ObjectDragSpawnSettings).Name);
return _dragSpawnSettings;
}
}
public TerrainFlattenSettings terrainFlattenSettings
{
get
{
if (_terrainFlattenSettings == null) _terrainFlattenSettings = AssetDbEx.loadScriptableObject<TerrainFlattenSettings>(PluginFolders.settings, typeof(PropsObjectSpawn).Name + "_" + typeof(TerrainFlattenSettings).Name);
return _terrainFlattenSettings;
}
}
public override ObjectSpawnGuideSettings spawnGuideSettings
{
get
{
if (_spawnGuideSettings == null) _spawnGuideSettings = AssetDbEx.loadScriptableObject<ObjectSpawnGuideSettings>(PluginFolders.settings, typeof(PropsObjectSpawn).Name + "_" + typeof(ObjectSpawnGuideSettings).Name);
return _spawnGuideSettings;
}
}
public ObjectMirrorGizmoSettings mirrorGizmoSettings
{
get
{
if (_mirrorGizmoSettings == null) _mirrorGizmoSettings = AssetDbEx.loadScriptableObject<ObjectMirrorGizmoSettings>(PluginFolders.settings, typeof(PropsObjectSpawn).Name + "_" + typeof(ObjectMirrorGizmoSettings).Name);
return _mirrorGizmoSettings;
}
}
public override ObjectSpawnToolId spawnToolId { get { return ObjectSpawnToolId.Props; } }
public override bool requiresSpawnGuide { get { return true; } }
public override ObjectMirrorGizmo mirrorGizmo { get { return _mirrorGizmo; } }
public PropsObjectSpawn()
{
}
public override void setSpawnGuidePrefab(PluginPrefab prefab)
{
spawnGuide.usePrefab(prefab, surfaceSnapSession);
}
public override void onNoLongerActive()
{
spawnGuide.destroyGuide();
}
public void executeSurfaceSnapSessionCommand(ObjectSurfaceSnapSessionCommand command)
{
surfaceSnapSession.executeCommand(command);
}
protected override void doOnSceneGUI()
{
spawnGuide.onSceneGUI();
_mirrorGizmo.onSceneGUI();
Event e = Event.current;
if (FixedShortcuts.enablePickSpawnGuidePrefabFromScene(e))
{
if (e.isLeftMouseButtonDownEvent())
{
var prefabPickResult = PluginScene.instance.pickPrefab(PluginCamera.camera.getCursorRay(), _pickPrefabRaycastFilter, ObjectRaycastConfig.defaultConfig);
if (prefabPickResult != null)
{
setSpawnGuidePrefab(prefabPickResult.pickedPluginPrefab);
spawnGuide.setRotationAndScale(prefabPickResult.pickedObject.transform.rotation, prefabPickResult.pickedObject.transform.lossyScale);
}
}
}
if (surfaceSnapSession.isActive)
{
if (spawnGuideSettings.applyDecorRules)
{
if (FixedShortcuts.changeDecorRuleIndex(e))
{
if (e.getMouseScrollSign() > 0) ++_decorRuleIndex;
else --_decorRuleIndex;
e.disable();
}
if (surfaceSnapSession.surfaceObject != null)
{
_surfaceObjectPrefab = surfaceSnapSession.surfaceObject.getOutermostPrefabAsset();
if (_surfaceObjectPrefab != null && _prevSurfaceObjectPrefab != _surfaceObjectPrefab)
{
var decorPrefab = PrefabDecorRuleDb.instance.getDecor(spawnGuide.sourcePrefab.prefabAsset);
if (decorPrefab != null) _decorRuleIndex = decorPrefab.getFavPropsSpawnRule(surfaceSnapSession.surfaceObject);
_prevSurfaceObjectPrefab = _surfaceObjectPrefab;
}
}
PrefabDecorRuleDb.instance.applyDecorRule(spawnGuide.gameObject,
spawnGuide.sourcePrefab.prefabAsset, surfaceSnapSession.surfaceObject, _decorRuleIndex,
e.delta.magnitude != 0.0f, _decorRuleApplyResult);
_prevDecorRuleApplyResult.copy(_decorRuleApplyResult);
_decorRuleIndex = _decorRuleApplyResult.ruleIndex;
}
if (surfaceSnapSession.isSurfaceValid)
{
if (e.isLeftMouseButtonDownEvent() && !e.alt)
{
surfaceSnapSession.addObjectHierarchyIgnoredAsSurface(spawn());
_lastSurfacePickPoint = surfaceSnapSession.surfacePickPoint;
if (surfaceSnapSession.isSurfaceTerrain) surfaceSnapSession.setSurfaceLocked(true);
}
else
if (e.isLeftMouseButtonDragEvent() && !e.alt)
{
float minDragDistance = dragSpawnSettings.minDragDistance;
if (dragSpawnSettings.useSafeDragDistance) minDragDistance = Mathf.Max(minDragDistance, spawnGuide.volumeRadius * 2.0f);
if ((_lastSurfacePickPoint - surfaceSnapSession.surfacePickPoint).magnitude >= minDragDistance)
{
surfaceSnapSession.addObjectHierarchyIgnoredAsSurface(spawn());
_lastSurfacePickPoint = surfaceSnapSession.surfacePickPoint;
if (surfaceSnapSession.isSurfaceTerrain) surfaceSnapSession.setSurfaceLocked(true);
}
}
else
if (FixedShortcuts.changeRadiusByScrollWheel(e))
{
if (terrainFlattenSettings.flattenTerrain)
{
e.disable();
int amount = (int)(e.getMouseScrollSign() * 0.5f);
if (amount == 0) amount = (int)(e.getMouseScrollSign());
terrainFlattenSettings.terrainQuadRadius -= amount;
EditorUtility.SetDirty(terrainFlattenSettings);
}
}
if (_mirrorGizmo.enabled)
{
_mirrorGizmo.mirrorOBB(spawnGuide.calcWorldOBB(), _obbBuffer);
_mirrorGizmo.drawMirroredOBBs(_obbBuffer);
}
}
}
if (e.type == EventType.MouseUp || e.type == EventType.MouseLeaveWindow)
{
surfaceSnapSession.clearObjectsIgnoredAsSurface();
surfaceSnapSession.setSurfaceLocked(false);
}
}
protected override void draw()
{
if (surfaceSnapSession.isActive)
{
if (surfaceSnapSession.isSurfaceUnityTerrain && terrainFlattenSettings.flattenTerrain)
{
Terrain terrain = surfaceSnapSession.surfaceObject.getTerrain();
float terrainYPos = terrain.transform.position.y;
spawnGuide.calcWorldOBB().calcCorners(_vector3Buffer, false);
AABB aabb = new AABB(_vector3Buffer);
terrain.calcTerrainPatchCorners(terrainFlattenSettings.terrainQuadRadius, aabb, _terrainPatchCorners);
HandlesEx.saveColor();
Handles.color = ObjectSpawnPrefs.instance.propsSpawnTerrainFlattenAreaColor;
const int numSamplePoints = 30;
float stepSize = 1.0f / (float)numSamplePoints;
for (int lineIndex = 0; lineIndex < 4; ++lineIndex)
{
Vector3 p0 = _terrainPatchCorners[lineIndex];
Vector3 p1 = _terrainPatchCorners[(lineIndex + 1) % 4];
Vector3 dir = (p1 - p0);
Vector3 prevPt = terrain.projectPoint(terrainYPos, p0);
for (int i = 0; i < numSamplePoints; ++i)
{
Vector3 currentPt = terrain.projectPoint(terrainYPos, prevPt + dir * stepSize);
Handles.DrawLine(prevPt, currentPt);
prevPt = currentPt;
}
}
HandlesEx.restoreColor();
}
if (spawnGuideSettings.applyDecorRules)
{
Handles.BeginGUI();
Vector3 labelPos = HandlesEx.calcLabelPositionAboveOBB(spawnGuide.calcWorldOBB());
var labelStyle = new GUIStyle(GUIStyleDb.instance.sceneViewInfoLabel);
labelStyle.normal.textColor = Color.green;
labelStyle.hover.textColor = Color.green;
Handles.Label(labelPos, "Decor rules: " + _decorRuleApplyResult.rules.Count + "\nSelected rule: " + _decorRuleIndex, labelStyle);
Handles.EndGUI();
}
}
}
private GameObject spawn()
{
Vector3 surfaceNormal = surfaceSnapSession.surfacePickNormal;
if (!surfaceSnapSettings.alignAxis) surfaceNormal = surfaceSnapSession.getNoAlignmentRotationAxis();
if (spawnGuideSettings.applyDecorRules)
{
var decorPrefab = PrefabDecorRuleDb.instance.getDecor(spawnGuide.sourcePrefab.prefabAsset);
if (decorPrefab != null)
decorPrefab.setFavPropsSpawnRule(surfaceSnapSession.surfaceObject, _decorRuleIndex);
}
GameObject spawnedObject;
if (surfaceSnapSession.isSurfaceUnityTerrain && terrainFlattenSettings.flattenTerrain)
{
Terrain terrain = surfaceSnapSession.surfaceObject.getTerrain();
TerrainFlattenConfig flattenConfig = new TerrainFlattenConfig();
flattenConfig.terrainQuadRadius = terrainFlattenSettings.terrainQuadRadius;
flattenConfig.mode = terrainFlattenSettings.mode;
flattenConfig.applyFalloff = terrainFlattenSettings.applyFalloff;
terrain.flattenAroundOBB(spawnGuide.calcWorldOBB(), flattenConfig);
surfaceSnapSession.projectTargetsOnSurface();
spawnedObject = spawnGuide.spawn();
}
else spawnedObject = spawnGuide.spawn();
if (_mirrorGizmo.enabled) _mirrorGizmo.mirrorObject_NoDuplicateCommand(spawnedObject, spawnGuide.sourcePrefab.prefabAsset);
if (spawnGuideSettings.randomizePrefab)
{
RandomPrefab randomPrefab = spawnGuideSettings.randomPrefabProfile.pickPrefab();
if (randomPrefab != null) setSpawnGuidePrefab(randomPrefab.pluginPrefab);
}
spawnGuide.randomizeTransformIfNecessary(spawnGuideSettings.transformRandomizationSettings, surfaceNormal);
return spawnedObject;
}
protected override void onEnabled()
{
_pickPrefabRaycastFilter = createDefaultPrefabPickRaycastFilter();
surfaceSnapSession.sharedSettings = surfaceSnapSettings;
if (_mirrorGizmo == null)
{
_mirrorGizmo = ScriptableObject.CreateInstance<ObjectMirrorGizmo>();
_mirrorGizmo.enabled = false;
}
_mirrorGizmo.sharedSettings = mirrorGizmoSettings;
}
protected override void onDestroy()
{
ScriptableObjectEx.destroyImmediate(_surfaceSnapSession);
}
}
}
#endif