private static float MousePositionToParameter(Vec <float> mouseWorldPosition, Coordinate coordinate,
                                                      Axis axis)
        {
            var worldPositionAsUnityVector =
                new Vector3(mouseWorldPosition.X, mouseWorldPosition.Y, mouseWorldPosition.Z);
            var directionVector = UnityAdapter.DirectionVector(axis.Direction);

            return(Vector3.Dot(worldPositionAsUnityVector, directionVector) - coordinate.ParentValue);
        }
        public static (float value, bool inOppositeDirection) UpdateDrag(Coordinate draggedCoordinate,
                                                                         Axis axisOfDraggedCoordinate)
        {
            // mouse position to parameter
            var pos = MouseInput.RaycastPosition;
            var worldPositionAsUnityVector = new Vector3(pos.X, pos.Y, pos.Z);

            var deltaToOldValue = Vector3.Dot(worldPositionAsUnityVector,
                                              UnityAdapter.DirectionVector(axisOfDraggedCoordinate.Direction)) -
                                  draggedCoordinate.Value;

            //todo take lambdas into consideration!!!

            var multiplier = CalculateMultiplierAlongPathRecursive(draggedCoordinate, draggedCoordinate.Parameter);

            float CalculateMultiplierAlongPathRecursive(Coordinate currentNode, Parameter parameter)
            {
                if (currentNode.GetType() == typeof(Origin))
                {
                    return(0f);
                }

                if (currentNode.GetType() == typeof(Lambda))
                {
                    var lambdaCoordinate = currentNode as Lambda;
                    Debug.Assert(lambdaCoordinate != null, nameof(lambdaCoordinate) + " != null");
                    var lambda = lambdaCoordinate.Parameter.Value;
                    var p0     = lambdaCoordinate.Parents[0];
                    var p1     = lambdaCoordinate.Parents[1];
                    return((1f - lambda) * CalculateMultiplierAlongPathRecursive(p0, parameter)
                           + lambda * CalculateMultiplierAlongPathRecursive(p1, parameter));
                }

                var mueCoordinate = currentNode as Mue;

                Debug.Assert(mueCoordinate != null, nameof(mueCoordinate) + " != null");

                if (mueCoordinate.Parameter != parameter)
                {
                    return(CalculateMultiplierAlongPathRecursive(mueCoordinate.Parents[0], parameter));
                }

                var weightForThisCoordinate = mueCoordinate.PointsInNegativeDirection ? -1f : 1f;

                return(weightForThisCoordinate +
                       CalculateMultiplierAlongPathRecursive(mueCoordinate.Parents[0], parameter));
            }

            var mue = draggedCoordinate as Mue;

            if (mue.PointsInNegativeDirection)
            {
                multiplier *= -1f;
            }

            if (multiplier == 0)
            {
                return(draggedCoordinate.Parameter.Value, mue.PointsInNegativeDirection);
            }

            var deltaThatTakesOtherCoordinatesIntoConsideration = deltaToOldValue / multiplier;
            var output = mue.PointsInNegativeDirection
                ? (value : draggedCoordinate.Parameter.Value - deltaThatTakesOtherCoordinatesIntoConsideration,
                   inoppositeDirection : true)
                         : (value : draggedCoordinate.Parameter.Value + deltaThatTakesOtherCoordinatesIntoConsideration,
                            inoppositeDirection : false);

            if (output.value < Epsilon)
            {
                output.value = Epsilon;
            }

            return(output);
        }