Merge pull request #126 from minenice55/snap-and-copy
Custom Snap and Entity Copying
This commit is contained in:
commit
4c25272eca
File diff suppressed because it is too large
Load diff
|
@ -20,6 +20,7 @@ namespace HeavenStudio
|
|||
|
||||
public List<Entity> entities = new List<Entity>();
|
||||
public List<TempoChange> tempoChanges = new List<TempoChange>();
|
||||
public List<VolumeChange> volumeChanges = new List<VolumeChange>();
|
||||
public float firstBeatOffset;
|
||||
|
||||
[Serializable]
|
||||
|
@ -53,6 +54,12 @@ namespace HeavenStudio
|
|||
return this.MemberwiseClone();
|
||||
}
|
||||
|
||||
public Entity DeepCopy()
|
||||
{
|
||||
//lol the AI generated this
|
||||
return JsonConvert.DeserializeObject<Entity>(JsonConvert.SerializeObject(this));
|
||||
}
|
||||
|
||||
public object this[string propertyName]
|
||||
{
|
||||
get
|
||||
|
@ -85,5 +92,18 @@ namespace HeavenStudio
|
|||
return this.MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class VolumeChange : ICloneable
|
||||
{
|
||||
public float beat;
|
||||
public float length;
|
||||
public float volume;
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return this.MemberwiseClone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -48,12 +48,13 @@ namespace HeavenStudio.Editor
|
|||
[SerializeField] private Button UndoBTN;
|
||||
[SerializeField] private Button RedoBTN;
|
||||
[SerializeField] private Button MusicSelectBTN;
|
||||
[SerializeField] private Button EditorSettingsBTN;
|
||||
[SerializeField] private Button EditorThemeBTN;
|
||||
[SerializeField] private Button FullScreenBTN;
|
||||
[SerializeField] private Button TempoFinderBTN;
|
||||
[SerializeField] private Button SnapDiagBTN;
|
||||
|
||||
[SerializeField] private Button EditorThemeBTN;
|
||||
[SerializeField] private Button EditorSettingsBTN;
|
||||
|
||||
[Header("Tooltip")]
|
||||
public TMP_Text tooltipText;
|
||||
|
||||
|
@ -102,12 +103,12 @@ namespace HeavenStudio.Editor
|
|||
Tooltip.AddTooltip(UndoBTN.gameObject, "Undo <color=#adadad>[Ctrl+Z]</color>");
|
||||
Tooltip.AddTooltip(RedoBTN.gameObject, "Redo <color=#adadad>[Ctrl+Y or Ctrl+Shift+Z]</color>");
|
||||
Tooltip.AddTooltip(MusicSelectBTN.gameObject, "Music Select");
|
||||
Tooltip.AddTooltip(EditorSettingsBTN.gameObject, "Editor Settings <color=#adadad>[Ctrl+Shift+O]</color>");
|
||||
Tooltip.AddTooltip(EditorThemeBTN.gameObject, "Editor Theme");
|
||||
Tooltip.AddTooltip(FullScreenBTN.gameObject, "Preview <color=#adadad>[Tab]</color>");
|
||||
Tooltip.AddTooltip(TempoFinderBTN.gameObject, "Tempo Finder");
|
||||
Tooltip.AddTooltip(SnapDiagBTN.gameObject, "Snap Settings");
|
||||
|
||||
Tooltip.AddTooltip(EditorSettingsBTN.gameObject, "Editor Settings <color=#adadad>[Ctrl+Shift+O]</color>");
|
||||
UpdateEditorStatus(true);
|
||||
}
|
||||
|
||||
|
|
8
Assets/Scripts/LevelEditor/SettingsDialog.meta
Normal file
8
Assets/Scripts/LevelEditor/SettingsDialog.meta
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 907f7d1eb5d90af408aa531ea366e63e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
27
Assets/Scripts/LevelEditor/SettingsDialog/SettingsDialog.cs
Normal file
27
Assets/Scripts/LevelEditor/SettingsDialog/SettingsDialog.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using HeavenStudio.Editor.Track;
|
||||
|
||||
using TMPro;
|
||||
|
||||
namespace HeavenStudio.Editor
|
||||
{
|
||||
public class SettingsDialog : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject settingsMenu;
|
||||
|
||||
private void Start() {}
|
||||
|
||||
public void SwitchSettingsDialog()
|
||||
{
|
||||
if(settingsMenu.activeSelf) {
|
||||
settingsMenu.SetActive(false);
|
||||
} else {
|
||||
settingsMenu.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update() {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d82cc04699de2e54483ca0e0468d9ed2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,28 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HeavenStudio.Editor
|
||||
{
|
||||
public class SnapDialog : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject snapSetter;
|
||||
private void Awake()
|
||||
{
|
||||
}
|
||||
|
||||
public void SwitchSnapDialog()
|
||||
{
|
||||
if(snapSetter.activeSelf) {
|
||||
snapSetter.SetActive(false);
|
||||
} else {
|
||||
snapSetter.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
8
Assets/Scripts/LevelEditor/SnapDialog.meta
Normal file
8
Assets/Scripts/LevelEditor/SnapDialog.meta
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 537580972fcefa548bd9ee5e8254cbfc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
22
Assets/Scripts/LevelEditor/SnapDialog/SnapChangeButton.cs
Normal file
22
Assets/Scripts/LevelEditor/SnapDialog/SnapChangeButton.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace HeavenStudio.Editor
|
||||
{
|
||||
public class SnapChangeButton : Button, IPointerDownHandler
|
||||
{
|
||||
public SnapDialog SnapDialog;
|
||||
public bool isDown;
|
||||
|
||||
public override void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (eventData.button == PointerEventData.InputButton.Left)
|
||||
{
|
||||
SnapDialog.ChangeCommon(isDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7e0cac45de7228a4c8f7bc6adb0751a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
52
Assets/Scripts/LevelEditor/SnapDialog/SnapDialog.cs
Normal file
52
Assets/Scripts/LevelEditor/SnapDialog/SnapDialog.cs
Normal file
|
@ -0,0 +1,52 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using HeavenStudio.Editor.Track;
|
||||
|
||||
using TMPro;
|
||||
|
||||
namespace HeavenStudio.Editor
|
||||
{
|
||||
public class SnapDialog : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject snapSetter;
|
||||
[SerializeField] private TMP_Text snapText;
|
||||
private Timeline timeline;
|
||||
|
||||
private static float[] CommonDenominators = { 1, 2, 3, 4, 6, 8, 12, 16};
|
||||
private int currentCommon = 3;
|
||||
private void Start()
|
||||
{
|
||||
timeline = Timeline.instance;
|
||||
}
|
||||
|
||||
public void SwitchSnapDialog()
|
||||
{
|
||||
if(snapSetter.activeSelf) {
|
||||
snapSetter.SetActive(false);
|
||||
} else {
|
||||
snapSetter.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeCommon(bool down = false)
|
||||
{
|
||||
if(down) {
|
||||
currentCommon--;
|
||||
} else {
|
||||
currentCommon++;
|
||||
}
|
||||
if(currentCommon < 0) {
|
||||
currentCommon = 0;
|
||||
} else if(currentCommon >= CommonDenominators.Length) {
|
||||
currentCommon = CommonDenominators.Length - 1;
|
||||
}
|
||||
timeline.SetSnap(1f / CommonDenominators[currentCommon]);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
snapText.text = $"1/{CommonDenominators[currentCommon]}";
|
||||
}
|
||||
}
|
||||
}
|
8
Assets/Scripts/LevelEditor/TempoFinder.meta
Normal file
8
Assets/Scripts/LevelEditor/TempoFinder.meta
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 36b14c8563ea37442aa7a2f0342549b5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -131,7 +131,16 @@ namespace HeavenStudio.Editor.Track
|
|||
UpdateOffsetText();
|
||||
}
|
||||
|
||||
private void AddTempoChange(bool create, Beatmap.TempoChange tempoChange_ = null)
|
||||
public void ClearTempoTimeline()
|
||||
{
|
||||
foreach (TempoTimelineObj tempoTimelineObj in tempoTimelineObjs)
|
||||
{
|
||||
Destroy(tempoTimelineObj.gameObject);
|
||||
}
|
||||
tempoTimelineObjs.Clear();
|
||||
}
|
||||
|
||||
public void AddTempoChange(bool create, Beatmap.TempoChange tempoChange_ = null)
|
||||
{
|
||||
GameObject tempoChange = Instantiate(RefTempoChange.gameObject, this.transform);
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ namespace HeavenStudio.Editor.Track
|
|||
|
||||
public static float SnapInterval() { return instance.snapInterval; }
|
||||
|
||||
public void SetSnap(float snap) { snapInterval = snap; }
|
||||
|
||||
public class CurrentTimelineState
|
||||
{
|
||||
public bool selected;
|
||||
|
@ -101,6 +103,7 @@ namespace HeavenStudio.Editor.Track
|
|||
|
||||
public void LoadRemix()
|
||||
{
|
||||
// beatmap entities
|
||||
for (int i = 0; i < eventObjs.Count; i++)
|
||||
{
|
||||
Destroy(eventObjs[i].gameObject);
|
||||
|
@ -109,11 +112,21 @@ namespace HeavenStudio.Editor.Track
|
|||
|
||||
for (int i = 0; i < GameManager.instance.Beatmap.entities.Count; i++)
|
||||
{
|
||||
var entity = GameManager.instance.Beatmap.entities[i];
|
||||
var e = GameManager.instance.Beatmap.entities[i];
|
||||
|
||||
AddEventObject(e.datamodel, false, new Vector3(e.beat, -e.track * LayerHeight()), e, false, RandomID());
|
||||
}
|
||||
|
||||
//tempo changes
|
||||
TempoInfo.ClearTempoTimeline();
|
||||
for (int i = 0; i < GameManager.instance.Beatmap.tempoChanges.Count; i++)
|
||||
{
|
||||
var t = GameManager.instance.Beatmap.tempoChanges[i];
|
||||
|
||||
TempoInfo.AddTempoChange(false, t);
|
||||
}
|
||||
|
||||
//volume changes
|
||||
}
|
||||
|
||||
public void Init()
|
||||
|
@ -559,36 +572,36 @@ namespace HeavenStudio.Editor.Track
|
|||
GameManager.instance.SortEventsList();
|
||||
|
||||
tempEntity = en;
|
||||
|
||||
// default param value
|
||||
var game = EventCaller.instance.GetMinigame(eventName.Split(0));
|
||||
var ep = EventCaller.instance.GetGameAction(game, eventName.Split(1)).parameters;
|
||||
|
||||
if (ep != null)
|
||||
{
|
||||
for (int i = 0; i < ep.Count; i++)
|
||||
{
|
||||
object returnVal = ep[i].parameter;
|
||||
|
||||
var propertyType = returnVal.GetType();
|
||||
if (propertyType == typeof(EntityTypes.Integer))
|
||||
{
|
||||
returnVal = ((EntityTypes.Integer)ep[i].parameter).val;
|
||||
}
|
||||
else if (propertyType == typeof(EntityTypes.Float))
|
||||
{
|
||||
returnVal = ((EntityTypes.Float)ep[i].parameter).val;
|
||||
}
|
||||
|
||||
tempEntity[ep[i].propertyName] = returnVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GameManager.instance.Beatmap.entities.Add(entity);
|
||||
GameManager.instance.SortEventsList();
|
||||
}
|
||||
|
||||
// default param value
|
||||
var game = EventCaller.instance.GetMinigame(eventName.Split(0));
|
||||
var ep = EventCaller.instance.GetGameAction(game, eventName.Split(1)).parameters;
|
||||
|
||||
if (ep != null)
|
||||
{
|
||||
for (int i = 0; i < ep.Count; i++)
|
||||
{
|
||||
object returnVal = ep[i].parameter;
|
||||
|
||||
var propertyType = returnVal.GetType();
|
||||
if (propertyType == typeof(EntityTypes.Integer))
|
||||
{
|
||||
returnVal = ((EntityTypes.Integer)ep[i].parameter).val;
|
||||
}
|
||||
else if (propertyType == typeof(EntityTypes.Float))
|
||||
{
|
||||
returnVal = ((EntityTypes.Float)ep[i].parameter).val;
|
||||
}
|
||||
|
||||
tempEntity[ep[i].propertyName] = returnVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eventObjs.Add(eventObj);
|
||||
|
@ -598,6 +611,14 @@ namespace HeavenStudio.Editor.Track
|
|||
return eventObj;
|
||||
}
|
||||
|
||||
public TimelineEventObj CopyEventObject(Beatmap.Entity e)
|
||||
{
|
||||
Beatmap.Entity clone = e.DeepCopy();
|
||||
TimelineEventObj dup = AddEventObject(clone.datamodel, false, new Vector3(clone.beat, -clone.track * Timeline.instance.LayerHeight()), clone, true, RandomID());
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
public void DestroyEventObject(Beatmap.Entity entity)
|
||||
{
|
||||
if (EventParameterManager.instance.entity == entity)
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace HeavenStudio.Editor.Track
|
|||
private bool resizingLeft;
|
||||
private bool resizingRight;
|
||||
private bool inResizeRegion;
|
||||
private bool wasDuplicated;
|
||||
public Vector2 lastMovePos;
|
||||
public bool isCreating;
|
||||
public string eventObjID;
|
||||
|
@ -167,6 +168,13 @@ namespace HeavenStudio.Editor.Track
|
|||
|
||||
if (Timeline.instance.eventObjs.FindAll(c => c.moving).Count > 0 && selected)
|
||||
{
|
||||
//duplicate the entity if holding alt or r-click
|
||||
if ((!wasDuplicated) && (Input.GetKey(KeyCode.LeftAlt) || Input.GetMouseButton(1)))
|
||||
{
|
||||
wasDuplicated = true;
|
||||
var te = Timeline.instance.CopyEventObject(entity);
|
||||
}
|
||||
|
||||
Vector3 mousePos = Editor.instance.EditorCamera.ScreenToWorldPoint(Input.mousePosition);
|
||||
|
||||
lastPos_ = transform.localPosition;
|
||||
|
@ -291,6 +299,7 @@ namespace HeavenStudio.Editor.Track
|
|||
}
|
||||
|
||||
moving = false;
|
||||
wasDuplicated = false;
|
||||
|
||||
Cancel();
|
||||
if (isCreating == true)
|
||||
|
|
|
@ -16,6 +16,8 @@ namespace HeavenStudio.Editor.Track
|
|||
public TMP_InputField StartingVolume;
|
||||
private RectTransform StartingVolumeRect;
|
||||
|
||||
public List<VolumeTimelineObj> volumeTimelineObjs = new List<VolumeTimelineObj>();
|
||||
|
||||
private bool firstUpdate;
|
||||
|
||||
void Start()
|
||||
|
@ -74,8 +76,8 @@ namespace HeavenStudio.Editor.Track
|
|||
}
|
||||
else if (newVol < 0)
|
||||
{
|
||||
StartingVolume.text = "1";
|
||||
newVol = 1;
|
||||
StartingVolume.text = "0";
|
||||
newVol = 0;
|
||||
}
|
||||
|
||||
GameManager.instance.Beatmap.musicVolume = newVol;
|
||||
|
|
105
Assets/Scripts/LevelEditor/Timeline/VolumeTimelineObj.cs
Normal file
105
Assets/Scripts/LevelEditor/Timeline/VolumeTimelineObj.cs
Normal file
|
@ -0,0 +1,105 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
using TMPro;
|
||||
|
||||
using DG.Tweening;
|
||||
|
||||
namespace HeavenStudio.Editor.Track
|
||||
{
|
||||
public class VolumeTimelineObj : MonoBehaviour
|
||||
{
|
||||
[Header("Components")]
|
||||
[SerializeField] private RectTransform rectTransform;
|
||||
[SerializeField] private TMP_Text volumeTXT;
|
||||
[SerializeField] private RectTransform raycastRect;
|
||||
|
||||
public Beatmap.VolumeChange volumeChange;
|
||||
|
||||
private float startPosX;
|
||||
private bool moving = false;
|
||||
|
||||
public bool hovering;
|
||||
|
||||
private float lastPosX;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
rectTransform = GetComponent<RectTransform>();
|
||||
volumeTXT = transform.GetChild(2).GetComponent<TMP_Text>();
|
||||
UpdateVolume();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Timeline.instance.timelineState.musicVolume && !Conductor.instance.NotStopped())
|
||||
{
|
||||
if (RectTransformUtility.RectangleContainsScreenPoint(raycastRect, Input.mousePosition, Editor.instance.EditorCamera))
|
||||
{
|
||||
float newVolume = Input.mouseScrollDelta.y;
|
||||
|
||||
if (Input.GetKey(KeyCode.LeftShift))
|
||||
newVolume *= 5f;
|
||||
if (Input.GetKey(KeyCode.LeftControl))
|
||||
newVolume /= 100f;
|
||||
|
||||
volumeChange.volume += newVolume;
|
||||
|
||||
//make sure volume is positive
|
||||
volumeChange.volume = Mathf.Clamp(volumeChange.volume, 0, 100);
|
||||
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
Vector3 mousePos = Editor.instance.EditorCamera.ScreenToWorldPoint(Input.mousePosition);
|
||||
startPosX = mousePos.x - transform.position.x;
|
||||
moving = true;
|
||||
lastPosX = transform.localPosition.x;
|
||||
}
|
||||
else if (Input.GetMouseButtonDown(1))
|
||||
{
|
||||
GameManager.instance.Beatmap.volumeChanges.Remove(volumeChange);
|
||||
transform.parent.GetComponent<VolumeTimeline>().volumeTimelineObjs.Remove(this);
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
|
||||
hovering = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
hovering = false;
|
||||
}
|
||||
|
||||
if (moving)
|
||||
{
|
||||
Vector3 mousePos = Editor.instance.EditorCamera.ScreenToWorldPoint(Input.mousePosition);
|
||||
|
||||
transform.position = new Vector3(mousePos.x - startPosX, transform.position.y, 0);
|
||||
transform.localPosition = new Vector3(Mathf.Clamp(Starpelly.Mathp.Round2Nearest(transform.localPosition.x, Timeline.SnapInterval()), 0, Mathf.Infinity), transform.localPosition.y);
|
||||
}
|
||||
if (Input.GetMouseButtonUp(0))
|
||||
{
|
||||
if (transform.parent.GetComponent<VolumeTimeline>().volumeTimelineObjs.Find(c => c.gameObject.transform.localPosition.x == this.transform.localPosition.x && c != this) != null)
|
||||
{
|
||||
transform.localPosition = new Vector3(lastPosX, transform.localPosition.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
volumeChange.beat = transform.localPosition.x;
|
||||
}
|
||||
|
||||
moving = false;
|
||||
lastPosX = transform.localPosition.x;
|
||||
}
|
||||
|
||||
UpdateVolume();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVolume()
|
||||
{
|
||||
volumeTXT.text = $"{volumeChange.volume}%";
|
||||
Timeline.instance.FitToSong();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 86bb8f2f290876a4387f1ea6fedf332b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in a new issue