I'm making an script that performs a morph animation when an Atom (called
Right now I have all the morphs that should change and the difference for each animation (stored in
I don't think making the animation itself will be difficult, but I don't know how to:
_collider
) enters a CollisionTrigger (_collisionBox
), but the lack of documentation it's really making it hard.Right now I have all the morphs that should change and the difference for each animation (stored in
_morphIncrement
), the animation duration (_durationStorable
) and a CollisionTrigger (added manually for the moment) that follows the containingAtom
's head.I don't think making the animation itself will be difficult, but I don't know how to:
- Create the CollisionTrigger by code
- Set the added CollisionTrigger to only react with the
_collider
atom - Call a script function (
OnCollision
) when it triggers
C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; // TypeDescriptor
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using SimpleJSON; // JSONNode
namespace JustAnotherUser {
public class TriggerIncrementer : MVRScript {
private List<DAZMorph> _morphs;
private Atom _collider; // the object that will colide with the collider region
private MotionAnimationControl _head;
private DAZCharacterSelector _characterSelector;
private JSONStorableStringChooser _colliderStorable;
private JSONStorableFloat _durationStorable;
private IDictionary<DAZMorph, JSONStorableFloat> _morphIncrement; // all the morphs that it should modify and its increment
private long _finalTime; // play the animation until finalTime
private Atom _collisionBox; // area where to detect collider
private static readonly string COLLISION_BOX_NAME = "TI_collision"; // TODO add {name} at the end
public override void Init() {
// plugin VaM GUI description
pluginLabelJSON.val = "TriggerIncrementer v0.1";
// get the objects
if (containingAtom.type != "Person" || (this._characterSelector = containingAtom.GetComponentInChildren<DAZCharacterSelector>()) == null) {
throw new InvalidOperationException("Missing DAZCharacterSelector");
}
if ((this._head = GetHead()) == null) throw new InvalidOperationException("Head not found in added object");
this._morphs = new List<DAZMorph>();
this._morphIncrement = new Dictionary<DAZMorph, JSONStorableFloat>();
}
// Runs once when plugin loads (after Init)
protected void Start() {
this._morphs.Clear();
ScanBank(this._characterSelector.morphBank1, this._morphs); // @author https://github.com/ProjectCanyon/morph-merger/blob/master/MorphMerger.cs
this._colliderStorable = new JSONStorableStringChooser("collider", SuperController.singleton.GetAtoms().Select(a => a.name).Distinct().ToList(), "", "Collider", (string colliderName) => {
this._collider = SuperController.singleton.GetAtoms().FirstOrDefault(a => a.name == colliderName);
SuperController.LogMessage("New collider");
});
RegisterStringChooser(this._colliderStorable);
var linkPopup = CreateFilterablePopup(this._colliderStorable);
linkPopup.popupPanelHeight = 600f;
JSONStorableStringChooser morphChooseList = new JSONStorableStringChooser("morph", this._morphs.Select(m => m.morphName).Distinct().ToList(), "", "Add morph", (string morphName) => {
if (this._morphIncrement.Keys.Select(e => e.morphName).Contains(morphName)) {
SuperController.LogMessage(morphName + " already added");
return;
}
SuperController.LogMessage("Added " + morphName);
AddMorph(morphName);
});
//RegisterStringChooser(morphChooseList); // TODO no need to register it (?) [we don't care about this information]
linkPopup = CreateFilterablePopup(morphChooseList, true); // create it on the right
linkPopup.popupPanelHeight = 600f;
this._durationStorable = new JSONStorableFloat("duration", 10.0f, 0.1f, 120.0f);
RegisterFloat(this._durationStorable);
CreateSlider(this._durationStorable);
this._collisionBox = GetCollisionBox();
// TODO change onCreate
this._collisionBox.GetStorableByID("scale").GetFloatJSONParam("scale").val = 0.4f;
this._collisionBox.GetStorableByID("trigger").GetFloatJSONParam("trigger").val = 0.4f;
//SuperController.LogMessage(pluginLabelJSON.val + " Loaded");
LoadJson(GetPluginJsonFromSave());
}
public void OnCollision() {
// TODO change _finalTime variable
}
public void FixedUpdate() { }
public void Update() {
if (this._collisionBox == null) return; // temporal, while the code doesn't add the trigger
this._collisionBox.mainController.transform.position = this._head.transform.position + new Vector3(0f, -0.05f, 0f);
// TODO rotation
// TODO animate with GetTimestamp
}
public void OnDestroy() {
// TODO remove collision box
}
public void OnUnLoad() {
// TODO remove collision box
}
public float GetDuration() {
return this._durationStorable.val;
}
private Atom GetCollisionBox() {
// does it already exists?
Atom r = SuperController.singleton.GetAtoms().FirstOrDefault(a => a.name == COLLISION_BOX_NAME);
if (r != null) return r;
// no collision box; generate a new one
// TODO
return r;
}
private void AddMorph(string morphName, float value = 0.0f) {
DAZMorph morph = FindMorphByName(this._morphs, morphName);
if (morph == null) return;
JSONStorableFloat jsonFloat = new JSONStorableFloat(morphName, value, -1.0f, 1.0f);
RegisterFloat(jsonFloat);
CreateSlider(jsonFloat);
// get jsonFloat.val
// change morphValue
this._morphIncrement.Add(morph, jsonFloat);
}
private void LoadJson(JSONNode node) {
if (node == null) return;
foreach (string entry in node.AsObject.Keys) {
switch (entry) {
case "collider":
this._colliderStorable.val = node[entry].ToString();
break;
case "duration":
this._durationStorable.val = node[entry].AsFloat;
break;
case "id":
case "pluginLabel":
break; // ignore
default:
// tracked morphs
try {
AddMorph(entry, node[entry].AsFloat);
} catch (Exception ex) { }
break;
}
}
}
// @author https://raw.githubusercontent.com/ChrisTopherTa54321/VamScripts/master/FloatMultiParamRandomizer.cs
public JSONNode GetPluginJsonFromSave() {
foreach (JSONNode atoms in SuperController.singleton.loadJson["atoms"].AsArray) {
if (!atoms["id"].Value.Equals(containingAtom.name)) continue;
foreach (JSONNode storable in atoms["storables"].AsArray) {
if (storable["id"].Value == this.storeId) {
return storable;
}
}
}
return null;
}
private MotionAnimationControl GetHead() {
foreach (MotionAnimationControl mac in containingAtom.motionAnimationControls) { // TODO get head inside linkableRigidbodies?
if (!mac.name.Equals("headControl")) continue;
return mac;
}
return null; // not found
}
private void ScanBank(DAZMorphBank bank, List<DAZMorph> morphs) { // TODO only morph (not morph & pose)
if (bank == null) return;
foreach (DAZMorph morph in bank.morphs) {
if (!morph.visible) continue;
morphs.Add(morph);
//SuperController.LogMessage(morph.morphName);
}
}
private DAZMorph FindMorphByName(List<DAZMorph> morphs, string name) {
foreach (DAZMorph morph in morphs) {
if (!morph.morphName.Equals(name)) continue;
return morph;
}
return null; // not found
}
}
}