public void OnDestroy()
        {
            _enabled = false;
            foreach (var g in _visualGuides)
            {
                Destroy(g);
            }
            _visualGuides = new List <GameObject>();

            _mainGuides       = null;
            _mainGuidesManual = null;
            _headGuides       = null;
            _headGuidesManual = null;
            _faceGuides       = null;
            _bustGuides       = null;
            _underbustGuides  = null;
            _waistGuides      = null;
            _hipGuides        = null;
            _autoMeasurements = null;

            foreach (var h in _penisMarkersFromMorph)
            {
                Destroy(h);
            }

            if (_autoMeasurements != null)
            {
                if (_autoMeasurements.POI != null)
                {
                    _autoMeasurements.POI.Person = null;
                    _autoMeasurements.POI        = null;
                }
                _autoMeasurements = null;
            }
        }
        public static CharacterMeasurements StaticMeasurements(UI ui)
        {
            var measurements = new CharacterMeasurements {
                Height            = ui.manualHeightStorable.val / 100,
                ChinHeight        = ui.manualChinHeightStorable.val / 100,
                ShoulderHeight    = ui.manualShoulderHeightStorable.val / 100,
                NippleHeight      = ui.manualNippleHeightStorable.val / 100,
                UnderbustHeight   = ui.manualUnderbustHeightStorable.val / 100,
                NavelHeight       = ui.manualNavelHeightStorable.val / 100,
                CrotchHeight      = ui.manualCrotchHeightStorable.val / 100,
                KneeHeight        = ui.manualKneeBottomHeightStorable.val / 100,
                HeelHeight        = 0,
                HeelToFloorOffset = Vector3.zero
            };

            return(measurements);
        }
        // LineRenderer _debugLine;
        public CharacterMeasurements AutoMeasurements(UI ui, Atom atom)
        {
            var measurements = new CharacterMeasurements();

            if (atom.type != "Person")
            {
                return(measurements);
            }
            var poi = new CharacterPointsOfInterest(atom);

            // switching skins sometimes leaves things in a bad state for a few seconds - watch for that
            if (!poi.HasSkin)
            {
                return(measurements);
            }

            var rootTransform = atom.mainController.transform;
            var rootPos       = rootTransform.position;

            var floor = Vector3.ProjectOnPlane(rootPos, rootTransform.up);
            var floorDistanceOffset = Vector3.Distance(rootPos, floor) * (Vector3.Dot(rootPos - floor, rootTransform.up) < 0 ? -1 : 1);

            var headPos        = poi.CraniumHeight;
            var footPos        = poi.HeelHeight;
            var chinPos        = poi.ChinHeight;
            var shoulderPos    = poi.ShoulderHeight;
            var nipplePos      = poi.BustHeight;
            var underbustPos   = poi.UnderbustHeight;
            var navelPos       = poi.NavelHeight;
            var crotchPos      = poi.CrotchHeight;
            var kneePos        = poi.KneeUnderHeight;
            var eyeHeightPos   = poi.EyeLeftCenter;
            var mouthHeightPos = poi.MouthCenterHeight;

            // if(_debugLine == null) {
            //     var go = new GameObject();
            //     go.transform.SetParent(transform);
            //     var lr = go.AddComponent<LineRenderer>();
            //     lr.transform.SetParent(go.transform);
            //     lr.gameObject.SetActive(true);
            //     lr.startWidth = 0.01f;
            //     lr.endWidth = 0.01f;
            //     _debugLine = lr;
            // }
            // _debugLine.SetPositions(new Vector3[] {
            //     // footPos,
            //     Vector3.ProjectOnPlane(footPos, rootTransform.up),
            //     Vector3.ProjectOnPlane(rootPos, rootTransform.up)
            // });

            var footOffset = Vector3.Distance(footPos, Vector3.ProjectOnPlane(footPos, rootTransform.up)) - floorDistanceOffset;

            // set measurements
            measurements.HeelToFloorOffset = Vector3.up * footOffset;
            measurements.Height            = Vector3.Distance(headPos, Vector3.ProjectOnPlane(headPos, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.ChinHeight        = Vector3.Distance(chinPos, Vector3.ProjectOnPlane(chinPos, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.HeadWidth         = Vector3.Distance(poi.CraniumLeftSide, poi.CraniumRightSide);
            measurements.ShoulderHeight    = Vector3.Distance(shoulderPos, Vector3.ProjectOnPlane(shoulderPos, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.NippleHeight      = poi.IsMale ? (float?)null : Vector3.Distance(nipplePos, Vector3.ProjectOnPlane(nipplePos, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.UnderbustHeight   = poi.IsMale ? (float?)null : Vector3.Distance(underbustPos, Vector3.ProjectOnPlane(underbustPos, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.NavelHeight       = Vector3.Distance(navelPos, Vector3.ProjectOnPlane(navelPos, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.CrotchHeight      = Vector3.Distance(crotchPos, Vector3.ProjectOnPlane(crotchPos, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.KneeHeight        = Vector3.Distance(kneePos, Vector3.ProjectOnPlane(kneePos, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.HeelHeight        = 0;

            measurements.WaistSize = LineLength(poi.WaistPoints);
            measurements.HipSize   = LineLength(poi.HipPoints);

            if (poi.IsMale)
            {
                measurements.BustSize      = null;
                measurements.UnderbustSize = null;
                measurements.BandSize      = null;
                measurements.CupSize       = null;
            }
            else
            {
                var cupInfo = GetCupInfo(LineLength(poi.BustPoints), LineLength(poi.UnderbustPoints), ui.CupCalculator);
                if (cupInfo != null)
                {
                    measurements.BustSize      = cupInfo.Bust;
                    measurements.UnderbustSize = cupInfo.Underbust;
                    measurements.BandSize      = cupInfo.Band;
                    measurements.CupSize       = cupInfo.Cup;
                }
                else
                {
                    measurements.BustSize      = null;
                    measurements.UnderbustSize = null;
                    measurements.BandSize      = null;
                    measurements.CupSize       = null;
                }
            }

            measurements.EyesHeight           = Vector3.Distance(eyeHeightPos, Vector3.ProjectOnPlane(eyeHeightPos, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.EyesWidth            = Vector3.Distance(poi.EyeLeftOuterSide, poi.EyeRightOuterSide);
            measurements.EyesOffsetLeftRight  = 0;
            measurements.NoseHeight           = poi.IsMale ? (float?)null : Vector3.Distance(poi.NoseBottomHeight, Vector3.ProjectOnPlane(poi.NoseBottomHeight, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.MouthHeight          = poi.IsMale ? (float?)null : Vector3.Distance(mouthHeightPos, Vector3.ProjectOnPlane(mouthHeightPos, rootTransform.up)) - floorDistanceOffset - footOffset;
            measurements.MouthWidth           = poi.IsMale ? (float?)null : Vector3.Distance(poi.MouthLeftSide, poi.MouthRightSide);
            measurements.MouthOffsetLeftRight = 0;

            if (poi.IsMale)
            {
                measurements.PenisLength = _penisLength;
                measurements.PenisGirth  = _penisGirth;
                measurements.PenisWidth  = _penisWidth;
            }
            else
            {
                measurements.PenisLength = null;
                measurements.PenisGirth  = null;
                measurements.PenisWidth  = null;
            }

            measurements.POI = poi;

            return(measurements);
        }
        bool _enabledPrev = false; // allows for performant disabling
        public void Update()
        {
            if (SuperController.singleton.freezeAnimation)
            {
                return;
            }

            // allows for performant disabling with OnEnable/Disable
            // if disabling, the Update should still try and shut off
            // components one last time
            if (_enabledPrev == false && !_enabled)
            {
                return;
            }
            _enabledPrev = _enabled;

            if (_ui == null)
            {
                return;
            }

            try {
                _autoMeasurements = AutoMeasurements(_ui, containingAtom);

                _manualMeasurements = StaticMeasurements(_ui);
                _manualMeasurements.HeelToFloorOffset = _autoMeasurements.HeelToFloorOffset;

                if (containingAtom.type == "Person" && _ui.manualMarkersCopy.val)
                {
                    _ui.manualHeightStorable.val           = (_autoMeasurements.Height ?? 0) * 100;
                    _ui.manualChinHeightStorable.val       = (_autoMeasurements.ChinHeight ?? 0) * 100;
                    _ui.manualShoulderHeightStorable.val   = (_autoMeasurements.ShoulderHeight ?? 0) * 100;
                    _ui.manualNippleHeightStorable.val     = (_autoMeasurements.NippleHeight ?? 0) * 100;
                    _ui.manualUnderbustHeightStorable.val  = (_autoMeasurements.UnderbustHeight ?? 0) * 100;
                    _ui.manualNavelHeightStorable.val      = (_autoMeasurements.NavelHeight ?? 0) * 100;
                    _ui.manualCrotchHeightStorable.val     = (_autoMeasurements.CrotchHeight ?? 0) * 100;
                    _ui.manualKneeBottomHeightStorable.val = (_autoMeasurements.KneeHeight ?? 0) * 100;
                }

                _ui.headSizeHeightStorable.val   = _autoMeasurements.HeadHeight ?? 0;
                _ui.headSizeWidthStorable.val    = _autoMeasurements.HeadWidth ?? 0;
                _ui.fullHeightStorable.val       = _autoMeasurements.Height ?? 0;
                _ui.heightInHeadsStorable.val    = _ui.headSizeHeightStorable.val == 0 ? 0 : _ui.fullHeightStorable.val / _ui.headSizeHeightStorable.val;
                _ui.chinHeightStorable.val       = _autoMeasurements.ChinHeight ?? 0;
                _ui.shoulderHeightStorable.val   = _autoMeasurements.ShoulderHeight ?? 0;
                _ui.nippleHeightStorable.val     = _autoMeasurements.NippleHeight ?? 0;
                _ui.underbustHeightStorable.val  = _autoMeasurements.UnderbustHeight ?? 0;
                _ui.navelHeightStorable.val      = _autoMeasurements.NavelHeight ?? 0;
                _ui.crotchHeightStorable.val     = _autoMeasurements.CrotchHeight ?? 0;
                _ui.kneeBottomHeightStorable.val = _autoMeasurements.KneeHeight ?? 0;

                _ui.waistSizeStorable.val = _autoMeasurements.WaistSize ?? 0;
                _ui.hipSizeStorable.val   = _autoMeasurements.HipSize ?? 0;

                _ui.breastBustStorable.val      = _autoMeasurements.BustSize ?? 0;
                _ui.breastUnderbustStorable.val = _autoMeasurements.UnderbustSize ?? 0;
                _ui.breastBandStorable.val      = _autoMeasurements.BandSize ?? 0;
                _ui.breastCupStorable.val       = _autoMeasurements.CupSize ?? "";

                _ui.penisLength.val = _autoMeasurements.PenisLength ?? 0;
                _ui.penisWidth.val  = _autoMeasurements.PenisWidth ?? 0;
                _ui.penisGirth.val  = _autoMeasurements.PenisGirth ?? 0;

                UpdateVisuals();
                UpdatePenisMarkers();
            }
            catch (Exception e) {
                SuperController.LogError(e.ToString());
            }
        }