Last active
August 28, 2021 10:07
-
-
Save simon56modder/eea8c648639a73711195a7bd28fb3b1c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using ICities; | |
using ColossalFramework; | |
using UnityEngine; | |
using ProceduralObjects; | |
using ProceduralObjects.Classes; | |
using ProceduralObjects.UI; | |
using ProceduralObjects.Tools; | |
namespace BackAndForthModule | |
{ | |
public class BackAndForthPOMod : LoadingExtensionBase, IUserMod | |
{ | |
public string Name { get { return "Back-and-Forth Module"; } } | |
public string Description { get { return "Back-and-forth behaviour module for Procedural Objects"; } } | |
private POModuleType moduleType; | |
public override void OnCreated(ILoading loading) | |
{ | |
base.OnCreated(loading); | |
if (moduleType == null) | |
{ | |
moduleType = new POModuleType() | |
{ | |
Name = Name, | |
Author = "Simon Royer", | |
TypeID = "BackAndForthModule", | |
ModuleType = typeof(BackAndForthModule), | |
maxModulesOnMap = 1000 | |
}; | |
} | |
if (!ProceduralObjectsMod.ModuleTypes.Contains(moduleType)) | |
ProceduralObjectsMod.ModuleTypes.Add(moduleType); | |
} | |
public override void OnReleased() | |
{ | |
base.OnReleased(); | |
if (moduleType == null) | |
return; | |
if (ProceduralObjectsMod.ModuleTypes.Contains(moduleType)) | |
ProceduralObjectsMod.ModuleTypes.Remove(moduleType); | |
} | |
} | |
public class BackAndForthModule : POModule | |
{ | |
public Vector3 absPointA = Vector3.zero, absPointB = Vector3.zero, relPointA, relPointB; | |
public byte speedCurve; | |
public bool groupFollows; | |
public float animDurationAB = 3f, animDurationBA = 3f, restingTimePointA = 1f, restingTimePointB = 1f; | |
private float totalTime, Timer; | |
public readonly Vector3 modifyingMarker = new Vector3(2000f, -95.267894f, 2000f); | |
private GUIUtils.FloatInputField animABfield, animBAfield, restAfield, restBfield; | |
public override void OnModuleCreated(ProceduralObjectsLogic logic) | |
{ | |
base.OnModuleCreated(logic); | |
window = new Rect(0, 0, 325, 250); | |
animABfield = new GUIUtils.FloatInputField(animDurationAB); | |
animBAfield = new GUIUtils.FloatInputField(animDurationBA); | |
restAfield = new GUIUtils.FloatInputField(restingTimePointA); | |
restBfield = new GUIUtils.FloatInputField(restingTimePointB); | |
if ((absPointA == Vector3.zero && absPointB == Vector3.zero) && (relPointA != Vector3.zero && relPointB != Vector3.zero)) | |
{ | |
absPointA = parentObject.m_position - relPointA; | |
absPointB = parentObject.m_position + relPointB; | |
} | |
else if ((absPointA != Vector3.zero && absPointB != Vector3.zero) && (relPointA == Vector3.zero && relPointB == Vector3.zero)) | |
calculateRelativePos(); | |
} | |
public override void GetData(Dictionary<string, string> data, bool forSaveGame) | |
{ | |
if (forSaveGame) | |
{ | |
data.Add("pointA", absPointA.ToStringUnrounded()); | |
data.Add("pointB", absPointB.ToStringUnrounded()); | |
} | |
else | |
{ | |
data.Add("relPointA", relPointA.ToStringUnrounded()); | |
data.Add("relPointB", relPointB.ToStringUnrounded()); | |
} | |
data.Add("speedCurve", speedCurve.ToString()); | |
data.Add("groupFollows", groupFollows.ToString()); | |
data.Add("timer", Timer.ToString()); | |
data.Add("animDurationAB", animDurationAB.ToString()); | |
data.Add("animDurationBA", animDurationBA.ToString()); | |
data.Add("restingTimePointA", restingTimePointA.ToString()); | |
data.Add("restingTimePointB", restingTimePointB.ToString()); | |
} | |
public override void LoadData(Dictionary<string, string> data, bool fromSaveGame) | |
{ | |
if (fromSaveGame) | |
{ | |
if (data.ContainsKey("pointA")) | |
absPointA = VertexUtils.ParseVector3(data["pointA"]); | |
if (data.ContainsKey("pointB")) | |
absPointB = VertexUtils.ParseVector3(data["pointB"]); | |
} | |
else | |
{ | |
if (data.ContainsKey("relPointA")) | |
relPointA = VertexUtils.ParseVector3(data["relPointA"]); | |
if (data.ContainsKey("relPointB")) | |
relPointB = VertexUtils.ParseVector3(data["relPointB"]); | |
} | |
if (data.ContainsKey("speedCurve")) | |
speedCurve = byte.Parse(data["speedCurve"]); | |
if (data.ContainsKey("groupFollows")) | |
groupFollows = bool.Parse(data["groupFollows"]); | |
if (data.ContainsKey("timer")) | |
Timer = float.Parse(data["timer"]); | |
if (data.ContainsKey("animDurationAB")) | |
animDurationAB = float.Parse(data["animDurationAB"]); | |
if (data.ContainsKey("animDurationBA")) | |
animDurationBA = float.Parse(data["animDurationBA"]); | |
if (data.ContainsKey("restingTimePointA")) | |
restingTimePointA = float.Parse(data["restingTimePointA"]); | |
if (data.ContainsKey("restingTimePointB")) | |
restingTimePointB = float.Parse(data["restingTimePointB"]); | |
} | |
public override void UpdateModule(ProceduralObjectsLogic logic, bool simulationPaused, bool layerVisible) | |
{ | |
if (absPointA == Vector3.zero && absPointB == Vector3.zero) | |
return; | |
if (logic.IsSettingPosition()) | |
{ | |
if (notBeingModified()) | |
{ | |
absPointA = parentObject.m_position - relPointA; | |
absPointB = parentObject.m_position + relPointB; | |
} | |
return; | |
} | |
if (simulationPaused || !layerVisible) | |
return; | |
if (absPointA == modifyingMarker || absPointB == modifyingMarker) | |
return; | |
totalTime = restingTimePointA + animDurationAB + restingTimePointB + animDurationBA; | |
float t = 0f; | |
if (Timer >= (totalTime - animDurationBA)) | |
t = (totalTime - Timer) / animDurationBA; | |
else if (Timer >= restingTimePointA + animDurationAB) | |
t = 1f; | |
else if (Timer < restingTimePointA) | |
t = 0f; | |
else // animDurationAB | |
t = (Timer - restingTimePointA) / animDurationAB; | |
Vector3 newPos = Vector3.Lerp(absPointA, absPointB, GetTimeForCurve(t)); | |
MoveChildrenObj(newPos); | |
parentObject.m_position = newPos; | |
if (notBeingModified()) | |
calculateRelativePos(); | |
Timer += Time.deltaTime; | |
if (Timer > totalTime) | |
Timer = Timer - totalTime; | |
} | |
public override void DrawCustomizationWindow(int id) | |
{ | |
base.DrawCustomizationWindow(id); | |
GUI.Label(new Rect(5, 50, 200, 22), "Points :"); | |
if (GUI.Button(new Rect(5, 72, 155, 28), (absPointA == Vector3.zero || absPointA == modifyingMarker) ? "UNSET / Click to set" : "Point A / Click to set")) | |
{ | |
bool wasModified = (absPointA == modifyingMarker); | |
absPointA = parentObject.m_position; | |
if (absPointB != modifyingMarker && !wasModified) | |
absPointB = modifyingMarker; | |
calculateRelativePos(); | |
} | |
if (GUI.Button(new Rect(165, 72, 155, 28), (absPointB == Vector3.zero || absPointB == modifyingMarker) ? "UNSET / Click to set" : "Point B / Click to set")) | |
{ | |
bool wasModified = (absPointB == modifyingMarker); | |
absPointB = parentObject.m_position; | |
if (absPointA != modifyingMarker && !wasModified) | |
absPointA = modifyingMarker; | |
calculateRelativePos(); | |
} | |
GUI.Label(new Rect(5, 105, 90, 20), "Speed curve :"); | |
speedCurve = (byte)GUI.Toolbar(new Rect(100, 102, 220, 26), speedCurve, new string[] { "Straight", "Smooth", "Logistic" }); | |
if (!(absPointA == Vector3.zero || absPointA == modifyingMarker)) | |
{ | |
if (GUI.Button(new Rect(4, 129, 127, 22), "")) | |
{ | |
if (notBeingModified()) | |
{ | |
Vector3 newPos = absPointA; | |
// MoveChildrenObj(newPos); | |
parentObject.m_position = newPos; | |
calculateRelativePos(); | |
Timer = 0f; | |
} | |
} | |
} | |
GUI.Label(new Rect(5, 130, 120, 20), "Rest at A (s)"); | |
GUI.Label(new Rect(5, 150, 120, 20), "From A to B (s)"); | |
if (!(absPointB == Vector3.zero || absPointB == modifyingMarker)) | |
{ | |
if (GUI.Button(new Rect(4, 169, 127, 22), "")) | |
{ | |
if (notBeingModified()) | |
{ | |
Vector3 newPos = absPointB; | |
// MoveChildrenObj(newPos); | |
parentObject.m_position = newPos; | |
calculateRelativePos(); | |
Timer = restingTimePointA + animDurationAB; | |
} | |
} | |
} | |
GUI.Label(new Rect(5, 170, 120, 20), "Rest at B (s)"); | |
GUI.Label(new Rect(5, 190, 120, 20), "From B to A (s)"); | |
restingTimePointA = restAfield.DrawField(new Rect(135, 130, 180, 20), restingTimePointA, false).returnValue; | |
animDurationAB = animABfield.DrawField(new Rect(135, 150, 180, 20), animDurationAB, false).returnValue; | |
restingTimePointB = restBfield.DrawField(new Rect(135, 170, 180, 20), restingTimePointB, false).returnValue; | |
animDurationBA = animBAfield.DrawField(new Rect(135, 190, 180, 20), animDurationBA, false).returnValue; | |
if (GUI.Button(new Rect(5, 220, 315, 23), "Children in group follow motion : " + (groupFollows ? "ON" : "OFF"))) | |
groupFollows = !groupFollows; | |
} | |
public override POModule Clone() | |
{ | |
var m = (BackAndForthModule)this.MemberwiseClone(); | |
if (m.relPointA != Vector3.zero && m.relPointB != Vector3.zero) | |
{ | |
m.absPointA = Vector3.zero; | |
m.absPointB = Vector3.zero; | |
} | |
return m; | |
} | |
private float GetTimeForCurve(float t) | |
{ | |
if (speedCurve == 0) | |
return t; | |
if (speedCurve == 1) | |
return (1.063f / (1 + Mathf.Exp(-7f * t + 3.4f))) - 0.035f; | |
if (speedCurve == 2) | |
return (1.0135f / (1 + Mathf.Exp(-10f * t + 5))) - 0.0067f; | |
return 0; | |
} | |
private void MoveChildrenObj(Vector3 newPos) | |
{ | |
if (!groupFollows || !parentObject.isRootOfGroup) | |
return; | |
if (parentObject.group == null) | |
return; | |
var diffPos = newPos - parentObject.m_position; | |
foreach (var child in parentObject.group.objects.Where(p => p != parentObject)) | |
child.m_position += diffPos; | |
} | |
private bool notBeingModified() | |
{ | |
return (absPointA != modifyingMarker && absPointB != modifyingMarker); | |
} | |
private void calculateRelativePos() | |
{ | |
if (absPointA != modifyingMarker) | |
relPointA = parentObject.m_position - absPointA; | |
if (absPointB != modifyingMarker) | |
relPointB = absPointB - parentObject.m_position; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment