Example #1
0
        public void Validate()
        {
            if (surfaceDefinition == null)
            {
                surfaceDefinition = new ChiselSurfaceDefinition();
            }

            stepHeight = Mathf.Max(kMinStepHeight, stepHeight);

            innerDiameter = Mathf.Min(outerDiameter - kMinStairsDepth, innerDiameter);
            innerDiameter = Mathf.Max(kMinInnerDiameter, innerDiameter);
            outerDiameter = Mathf.Max(innerDiameter + kMinStairsDepth, outerDiameter);
            outerDiameter = Mathf.Max(kMinOuterDiameter, outerDiameter);
            height        = Mathf.Max(stepHeight, Mathf.Abs(height)) * (height < 0 ? -1 : 1);
            treadHeight   = Mathf.Max(0, treadHeight);
            nosingDepth   = Mathf.Max(0, nosingDepth);
            nosingWidth   = Mathf.Max(0, nosingWidth);

            riserDepth = Mathf.Max(kMinRiserDepth, riserDepth);

            rotation = Mathf.Max(kMinRotation, Mathf.Abs(rotation)) * (rotation < 0 ? -1 : 1);

            innerSegments = Mathf.Max(kMinSegments, innerSegments);
            outerSegments = Mathf.Max(kMinSegments, outerSegments);

            surfaceDefinition.EnsureSize(8);
        }
Example #2
0
        public override void CalcBounds()
        {
            bounds.Center = Vector3.zero;
            bounds.Size   = Size;
            var minY   = -Size.y / 2;
            var maxY   = Size.y / 2;
            var minX   = float.MaxValue;
            var maxX   = float.MinValue;
            var minZ   = float.MaxValue;
            var maxZ   = float.MinValue;
            var points = new Vector3[]
            {
                new Vector3(Size.x / 2, 0, Size.z / 2),
                new Vector3(-Size.x / 2, 0, -Size.z / 2),
                new Vector3(-Size.x / 2, 0, Size.z / 2),
                new Vector3(Size.x / 2, 0, -Size.z / 2)
            };

            for (int i = 0; i < points.Length; i++)
            {
                points[i] = Quaternion * points[i];
                minX      = Mathf.Min(minX, points[i].x);
                maxX      = Mathf.Max(maxX, points[i].x);
                minZ      = Mathf.Min(minZ, points[i].z);
                maxZ      = Mathf.Max(maxZ, points[i].z);
            }
            bounds.Min    = new Vector3(minX, minY, minZ);
            bounds.Max    = new Vector3(maxX, maxY, maxZ);
            bounds.Center = Position;
        }
Example #3
0
 public static int AmountPawnWantsToPickUp(Pawn p, Thing t, HaulExplicitlyPosting posting)
 {
     return(Mathf.Min(new int[] {
         posting.RecordWithItem(t).RemainingToHaul(),
         p.carryTracker.AvailableStackSpace(t.def),
         t.stackCount
     }));
 }
Example #4
0
        public void Validate()
        {
            stepHeight = Mathf.Max(kMinStepHeight, stepHeight);

            innerDiameter = Mathf.Min(outerDiameter - kMinStairsDepth, innerDiameter);
            innerDiameter = Mathf.Max(kMinInnerDiameter, innerDiameter);
            outerDiameter = Mathf.Max(innerDiameter + kMinStairsDepth, outerDiameter);
            outerDiameter = Mathf.Max(kMinOuterDiameter, outerDiameter);
            height        = Mathf.Max(stepHeight, Mathf.Abs(height)) * (height < 0 ? -1 : 1);
            treadHeight   = Mathf.Max(0, treadHeight);
            nosingDepth   = Mathf.Max(0, nosingDepth);
            nosingWidth   = Mathf.Max(0, nosingWidth);

            riserDepth = Mathf.Max(kMinRiserDepth, riserDepth);

            rotation = Mathf.Max(kMinRotation, Mathf.Abs(rotation)) * (rotation < 0 ? -1 : 1);

            innerSegments = Mathf.Max(kMinSegments, innerSegments);
            outerSegments = Mathf.Max(kMinSegments, outerSegments);

            if (surfaceAssets == null ||
                surfaceAssets.Length != 6)
            {
                var defaultRenderMaterial  = CSGMaterialManager.DefaultWallMaterial;
                var defaultPhysicsMaterial = CSGMaterialManager.DefaultPhysicsMaterial;
                surfaceAssets = new CSGSurfaceAsset[6];
                for (int i = 0; i < 6; i++) // Note: sides share same material
                {
                    surfaceAssets[i] = CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial);
                }
            }

            if (surfaceDescriptions == null ||
                surfaceDescriptions.Length != 6)
            {
                var surfaceFlags = CSGDefaults.SurfaceFlags;
                surfaceDescriptions = new SurfaceDescription[6];
                for (int i = 0; i < 6; i++)
                {
                    surfaceDescriptions[i] = new SurfaceDescription {
                        surfaceFlags = surfaceFlags, UV0 = UVMatrix.centered, smoothingGroup = bottomSmoothingGroup
                    };
                }
            }
            else
            {
                for (int i = 0; i < 6; i++)
                {
                    surfaceDescriptions[i].smoothingGroup = bottomSmoothingGroup;
                }
            }
        }
Example #5
0
        public static float Clamp(float x, float limit1, float limit2)
        {
            float max = Mathf.Max(limit1, limit2);
            float min = Mathf.Min(limit1, limit2);

            if (x < min)
            {
                return(min);
            }
            if (x > max)
            {
                return(max);
            }
            return(x);
        }
Example #6
0
        /** Clamps the velocity to the max speed and optionally the forwards direction.
         * \param velocity Desired velocity of the character. In world units per second.
         * \param maxSpeed Max speed of the character. In world units per second.
         * \param slowdownFactor Value between 0 and 1 which determines how much slower the character should move than normal.
         *      Normally 1 but should go to 0 when the character approaches the end of the path.
         * \param slowWhenNotFacingTarget Prevent the velocity from being too far away from the forward direction of the character
         *      and slow the character down if the desired velocity is not in the same direction as the forward vector.
         * \param forward Forward direction of the character. Used together with the \a slowWhenNotFacingTarget parameter.
         *
         * Note that all vectors are 2D vectors, not 3D vectors.
         *
         * \returns The clamped velocity in world units per second.
         */
        public static Vector2 ClampVelocity(Vector2 velocity, float maxSpeed, float slowdownFactor, bool slowWhenNotFacingTarget, Vector2 forward)
        {
            // Max speed to use for this frame
            var currentMaxSpeed = maxSpeed * slowdownFactor;

            // Check if the agent should slow down in case it is not facing the direction it wants to move in
            if (slowWhenNotFacingTarget && (forward.x != 0 || forward.y != 0))
            {
                float currentSpeed;
                var   normalizedVelocity = VectorMath.Normalize(velocity.ToPFV2(), out currentSpeed);
                float dot = Vector2.Dot(normalizedVelocity.ToUnityV2(), forward);

                // Lower the speed when the character's forward direction is not pointing towards the desired velocity
                // 1 when velocity is in the same direction as forward
                // 0.2 when they point in the opposite directions
                float directionSpeedFactor = Mathf.Clamp(dot + 0.707f, 0.2f, 1.0f);
                currentMaxSpeed *= directionSpeedFactor;
                currentSpeed     = Mathf.Min(currentSpeed, currentMaxSpeed);

                // Angle between the forwards direction of the character and our desired velocity
                float angle = Mathf.Acos(Mathf.Clamp(dot, -1, 1));

                // Clamp the angle to 20 degrees
                // We cannot keep the velocity exactly in the forwards direction of the character
                // because we use the rotation to determine in which direction to rotate and if
                // the velocity would always be in the forwards direction of the character then
                // the character would never rotate.
                // Allow larger angles when near the end of the path to prevent oscillations.
                angle = Mathf.Min(angle, (20f + 180f * (1 - slowdownFactor * slowdownFactor)) * Mathf.Deg2Rad);

                float sin = Mathf.Sin(angle);
                float cos = Mathf.Cos(angle);

                // Determine if we should rotate clockwise or counter-clockwise to move towards the current velocity
                sin *= Mathf.Sign(normalizedVelocity.x * forward.y - normalizedVelocity.y * forward.x);
                // Rotate the #forward vector by #angle radians
                // The rotation is done using an inlined rotation matrix.
                // See https://en.wikipedia.org/wiki/Rotation_matrix
                return(new Vector2(forward.x * cos + forward.y * sin, forward.y * cos - forward.x * sin) * currentSpeed);
            }
            else
            {
                return(Vector2.ClampMagnitude(velocity, currentMaxSpeed));
            }
        }
Example #7
0
        private static bool ProjectOverlapTest(Vector3 axis, Vector3[] srcPoints, Vector3[] dstPoints, out float overlap)
        {
            float srcMin = float.MaxValue;
            float dstMin = float.MaxValue;
            float srcMax = float.MinValue;
            float dstMax = float.MinValue;

            for (int i = 0; i < srcPoints.Length; i++)
            {
                var p = Vector3.Dot(axis, srcPoints[i]);
                if (p < srcMin)
                {
                    srcMin = p;
                }
                if (p > srcMax)
                {
                    srcMax = p;
                }
            }
            for (int i = 0; i < dstPoints.Length; i++)
            {
                var p = Vector3.Dot(axis, dstPoints[i]);
                if (p < dstMin)
                {
                    dstMin = p;
                }
                if (p > dstMax)
                {
                    dstMax = p;
                }
            }
            if (srcMax < dstMin || srcMin > dstMax)
            {
                overlap = 0;
                return(false);
            }
            overlap = Mathf.Min(srcMax, dstMax) - Mathf.Max(srcMin, dstMin);
            if ((srcMax > dstMax && srcMin < dstMin) || (srcMax < dstMax && srcMin > dstMin))
            {
                var min = Mathf.Abs(srcMin - dstMin);
                var max = Mathf.Abs(srcMax - dstMax);
                overlap += Mathf.Min(min, max);
            }
            return(true);
        }
Example #8
0
        public static Frustum GetCameraSubFrustum(Camera camera, Rect rect)
        {
            var oldMatrix = UnityEditor.Handles.matrix;

            UnityEditor.Handles.matrix = Matrix4x4.identity;

            var min_x = Mathf.Min(rect.xMin, rect.xMax);
            var max_x = Mathf.Max(rect.xMin, rect.xMax);
            var min_y = Mathf.Min(rect.yMin, rect.yMax);
            var max_y = Mathf.Max(rect.yMin, rect.yMax);

            var o0 = new Vector2(min_x, min_y);
            var o1 = new Vector2(max_x, min_y);
            var o2 = new Vector2(max_x, max_y);
            var o3 = new Vector2(min_x, max_y);

            var r0 = HandleUtility.GUIPointToWorldRay(o0);
            var r1 = HandleUtility.GUIPointToWorldRay(o1);
            var r2 = HandleUtility.GUIPointToWorldRay(o2);
            var r3 = HandleUtility.GUIPointToWorldRay(o3);

            UnityEditor.Handles.matrix = oldMatrix;

            var n0 = r0.origin;
            var n1 = r1.origin;
            var n2 = r2.origin;
            var n3 = r3.origin;

            var far = camera.farClipPlane;
            var f0  = n0 + (r0.direction * far);
            var f1  = n1 + (r1.direction * far);
            var f2  = n2 + (r2.direction * far);
            var f3  = n3 + (r3.direction * far);

            var frustum = new Frustum();

            frustum.Planes[0] = new Plane(n2, n1, f1); // right  +
            frustum.Planes[1] = new Plane(f3, f0, n0); // left   -
            frustum.Planes[2] = new Plane(n1, n0, f0); // top    -
            frustum.Planes[3] = new Plane(n3, n2, f2); // bottom +
            frustum.Planes[4] = new Plane(n0, n1, n2); // near   -
            frustum.Planes[5] = new Plane(f2, f1, f0); // far    +
            return(frustum);
        }
Example #9
0
        /// <summary>
        /// Calculates a value from two given values based on the desired calculation method.
        /// </summary>
        /// <param name="lhs">The first value.</param>
        /// <param name="rhs">The second value.</param>
        /// <param name="calculation">How the final value should be calculated.</param>
        public static float Calculate(float lhs, float rhs, PhysicsMaterialCombine calculation)
        {
            switch (calculation)
            {
            case PhysicsMaterialCombine.Average:
                return((lhs + rhs) / 2f);

            case PhysicsMaterialCombine.Multiply:
                return(lhs * rhs);

            case PhysicsMaterialCombine.Maximum:
                return(Mathf.Max(lhs, rhs));

            case PhysicsMaterialCombine.Minimum:
                return(Mathf.Min(lhs, rhs));

            default:
                throw new System.NotImplementedException();
            }
        }
Example #10
0
        public static bool Intersect(CubeXCollider src, CubeXCollider dst, out XContact?contact)
        {
            Vector3 normal;
            float   penetration;

            if (!SATTest(src, dst, out normal, out penetration))
            {
                contact = null;
                return(false);
            }
            var srcExtents = src.Size * 0.5f;
            var dstExtents = dst.Size * 0.5f;
            var srcMinY    = src.Position.y - srcExtents.y;
            var srcMaxY    = src.Position.y + srcExtents.y;
            var dstMinY    = dst.Position.y - dstExtents.y;
            var dstMaxY    = dst.Position.y + dstExtents.y;

            var overlapY = Mathf.Min(srcMaxY, dstMaxY) - Mathf.Max(srcMinY, dstMinY);

            if ((srcMaxY > dstMaxY && srcMinY < dstMinY) || (srcMaxY < dstMaxY && srcMinY > dstMinY))
            {
                var min = Mathf.Abs(srcMinY - dstMinY);
                var max = Mathf.Abs(srcMaxY - dstMaxY);
                overlapY += Mathf.Min(min, max);
            }

            if (overlapY < penetration)
            {
                penetration = overlapY;
                normal      = Vector3.up;
            }

            if (Vector3.Dot(normal, dst.Position - src.Position) < 0)
            {
                normal = -normal;
            }

            contact = new XContact(src, dst, normal, penetration);
            return(true);
        }
Example #11
0
        public static Toil PickUpThing(TargetIndex haulxItemInd, Toil nextToilIfBeingOpportunistic)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn  actor  = toil.actor;
                Job   job    = actor.CurJob;
                Thing target = job.GetTarget(haulxItemInd).Thing;
                if (Toils_Haul.ErrorCheckForCarry(actor, target))
                {
                    return;
                }

                Thing carriedItem             = actor.carryTracker.CarriedThing;
                int   targetInitialStackcount = target.stackCount;
                int   countToPickUp           = Mathf.Min(
                    job.count - (carriedItem?.stackCount ?? 0),
                    actor.carryTracker.AvailableStackSpace(target.def),
                    targetInitialStackcount);
                if (countToPickUp <= 0)
                {
                    throw new Exception("PickUpThing countToPickUp = " + countToPickUp);
                }

                //pick up
                int countPickedUp = actor.carryTracker.TryStartCarry(target, countToPickUp);
                if (countPickedUp < targetInitialStackcount)
                {
                    actor.Map.reservationManager.Release(target, actor, job);
                }
                carriedItem = actor.carryTracker.CarriedThing;
                job.SetTarget(haulxItemInd, carriedItem);
                actor.records.Increment(RecordDefOf.ThingsHauled);

                //register the carried item (into the HaulExplicitly job)
                if (carriedItem.IsAHaulableSetToHaulable())
                {
                    carriedItem.ToggleHaulDesignation();
                }
                var driver = (JobDriver_HaulExplicitly)actor.jobs.curDriver;
                driver.posting.TryAddItemSplinter(carriedItem);

                //pick up next available item in job?
                if (actor.CurJob.haulOpportunisticDuplicates)
                {
                    Thing prospect  = null;
                    int   best_dist = 999;
                    foreach (Thing item in driver.record.items.Where(
                                 i => i.Spawned && WorkGiver_HaulExplicitly.CanGetThing(actor, i, false)))
                    {
                        IntVec3 offset = item.Position - actor.Position;
                        int     dist   = Math.Abs(offset.x) + Math.Abs(offset.z);
                        if (dist < best_dist && dist < 7)
                        {
                            prospect  = item;
                            best_dist = dist;
                        }
                    }
                    if (prospect == null)
                    {
                        return;
                    }
                    int space_request = WorkGiver_HaulExplicitly
                                        .AmountPawnWantsToPickUp(actor, prospect, driver.posting);
                    if (space_request == 0)
                    {
                        return;
                    }
                    var            destInfo = DeliverableDestinations.For(prospect, actor, driver.posting);
                    List <IntVec3> dests    = destInfo.RequestSpaceForItemAmount(
                        Math.Max(0, space_request - driver.dest_space_available));
                    int new_dest_space = destInfo.FreeSpaceInCells(dests);
                    var count          = Math.Min(space_request, driver.dest_space_available + new_dest_space);
                    if (count < 1)
                    {
                        return;
                    }

                    //commit to it
                    actor.Reserve(prospect, job);
                    job.SetTarget(haulxItemInd, prospect);
                    job.SetTarget(TargetIndex.C, prospect.Position);
                    foreach (var dest in dests)
                    {
                        actor.Reserve(dest, job);
                        job.targetQueueB.Add(dest);
                    }
                    job.count += count;
                    driver.JumpToToil(nextToilIfBeingOpportunistic);
                }
            };
            return(toil);
        }
Example #12
0
        public void OnEdit(IChiselHandles handles)
        {
            var normal       = Vector3.up;
            var topDirection = Vector3.forward;
            var lowDirection = Vector3.forward;

            var originalOuterDiameter = this.outerDiameter;
            var originalInnerDiameter = this.innerDiameter;
            var originalStartAngle    = this.startAngle;
            var originalStepHeight    = this.stepHeight;
            var originalRotation      = this.rotation;
            var originalHeight        = this.height;
            var originalOrigin        = this.origin;
            var cylinderTop           = new BrushMeshFactory.ChiselCircleDefinition(1, originalOrigin.y + originalHeight);
            var cylinderLow           = new BrushMeshFactory.ChiselCircleDefinition(1, originalOrigin.y);
            var originalTopPoint      = normal * cylinderTop.height;
            var originalLowPoint      = normal * cylinderLow.height;
            var originalMidPoint      = (originalTopPoint + originalLowPoint) * 0.5f;

            var outerDiameter = originalOuterDiameter;
            var innerDiameter = originalInnerDiameter;
            var topPoint      = originalTopPoint;
            var lowPoint      = originalLowPoint;
            var midPoint      = originalMidPoint;
            var startAngle    = originalStartAngle;
            var rotation      = originalRotation;

            {
                var currRotation = startAngle + rotation;
                handles.DoRotatableLineHandle(ref startAngle, lowPoint, outerDiameter * 0.5f, normal, lowDirection, Vector3.Cross(normal, lowDirection));
                handles.DoRotatableLineHandle(ref currRotation, topPoint, outerDiameter * 0.5f, normal, topDirection, Vector3.Cross(normal, topDirection));
                if (handles.modified)
                {
                    rotation = currRotation - startAngle;
                }


                // TODO: properly show things as backfaced
                // TODO: temporarily show inner or outer diameter as disabled when resizing one or the other
                // TODO: FIXME: why aren't there any arrows?
                handles.DoDirectionHandle(ref topPoint, normal, snappingStep: originalStepHeight);
                topPoint.y = Mathf.Max(lowPoint.y + originalStepHeight, topPoint.y);
                handles.DoDirectionHandle(ref lowPoint, -normal, snappingStep: originalStepHeight);
                lowPoint.y = Mathf.Min(topPoint.y - originalStepHeight, lowPoint.y);

                float minOuterDiameter = innerDiameter + ChiselSpiralStairsDefinition.kMinStairsDepth;
                {
                    var outerRadius = outerDiameter * 0.5f;
                    handles.DoRadiusHandle(ref outerRadius, Vector3.up, topPoint, renderDisc: false);
                    handles.DoRadiusHandle(ref outerRadius, Vector3.up, lowPoint, renderDisc: false);
                    outerDiameter = Mathf.Max(minOuterDiameter, outerRadius * 2.0f);
                }

                float maxInnerDiameter = outerDiameter - ChiselSpiralStairsDefinition.kMinStairsDepth;
                {
                    var innerRadius = innerDiameter * 0.5f;
                    handles.DoRadiusHandle(ref innerRadius, Vector3.up, midPoint, renderDisc: false);
                    innerDiameter = Mathf.Min(maxInnerDiameter, innerRadius * 2.0f);
                }



                // TODO: somehow put this into a separate renderer
                cylinderTop.diameterZ = cylinderTop.diameterX = cylinderLow.diameterZ = cylinderLow.diameterX = originalInnerDiameter;
                BrushMeshFactory.GetConicalFrustumVertices(cylinderLow, cylinderTop, 0, this.innerSegments, ref innerVertices);

                cylinderTop.diameterZ = cylinderTop.diameterX = cylinderLow.diameterZ = cylinderLow.diameterX = originalOuterDiameter;
                BrushMeshFactory.GetConicalFrustumVertices(cylinderLow, cylinderTop, 0, this.outerSegments, ref outerVertices);

                var originalColor = handles.color;
                var color         = handles.color;
                var outlineColor  = Color.black;
                outlineColor.a = color.a;

                handles.color = outlineColor;
                {
                    var sides = this.outerSegments;
                    for (int i = 0, j = sides - 1; i < sides; j = i, i++)
                    {
                        var t0 = outerVertices[i];
                        var t1 = outerVertices[j];
                        var b0 = outerVertices[i + sides];
                        var b1 = outerVertices[j + sides];

                        handles.DrawLine(t0, b0, thickness: 1.0f);
                        handles.DrawLine(t0, t1, thickness: 1.0f);
                        handles.DrawLine(b0, b1, thickness: 1.0f);
                    }
                }
                {
                    var sides = this.innerSegments;
                    for (int i = 0, j = sides - 1; i < sides; j = i, i++)
                    {
                        var t0 = innerVertices[i];
                        var t1 = innerVertices[j];
                        var b0 = innerVertices[i + sides];
                        var b1 = innerVertices[j + sides];

                        handles.DrawLine(t0, b0, thickness: 1.0f);
                        handles.DrawLine(t0, t1, thickness: 1.0f);
                        handles.DrawLine(b0, b1, thickness: 1.0f);
                    }
                }

                handles.color = originalColor;
                {
                    var sides = this.outerSegments;
                    for (int i = 0, j = sides - 1; i < sides; j = i, i++)
                    {
                        var t0 = outerVertices[i];
                        var t1 = outerVertices[j];
                        var b0 = outerVertices[i + sides];
                        var b1 = outerVertices[j + sides];

                        handles.DrawLine(t0, b0, thickness: 1.0f);
                        handles.DrawLine(t0, t1, thickness: 1.0f);
                        handles.DrawLine(b0, b1, thickness: 1.0f);
                    }
                }
                {
                    var sides = this.innerSegments;
                    for (int i = 0, j = sides - 1; i < sides; j = i, i++)
                    {
                        var t0 = innerVertices[i];
                        var t1 = innerVertices[j];
                        var b0 = innerVertices[i + sides];
                        var b1 = innerVertices[j + sides];


                        handles.DrawLine(t0, b0, thickness: 1.0f);
                        handles.DrawLine(t0, t1, thickness: 1.0f);
                        handles.DrawLine(b0, b1, thickness: 1.0f);

                        var m0 = (t0 + b0) * 0.5f;
                        var m1 = (t1 + b1) * 0.5f;
                        handles.DrawLine(m0, m1, thickness: 2.0f);
                    }
                }
            }
            if (handles.modified)
            {
                this.outerDiameter = outerDiameter;
                this.innerDiameter = innerDiameter;
                this.startAngle    = startAngle;
                this.rotation      = rotation;

                if (topPoint != originalTopPoint)
                {
                    this.height = topPoint.y - lowPoint.y;
                }

                if (lowPoint != originalLowPoint)
                {
                    this.height = topPoint.y - lowPoint.y;
                    var newOrigin = originalOrigin;
                    newOrigin.y += lowPoint.y - originalLowPoint.y;
                    this.origin  = newOrigin;
                }
            }
        }
Example #13
0
        //
        // TODO: code below needs to be cleaned up & simplified
        //


        public void OnEdit(IChiselHandles handles)
        {
            var newDefinition = this;

            {
                var stepDepthOffset = this.StepDepthOffset;
                var stepHeight      = this.stepHeight;
                var stepCount       = this.StepCount;
                var bounds          = this.bounds;

                var steps = handles.moveSnappingSteps;
                steps.y = stepHeight;

                if (handles.DoBoundsHandle(ref bounds, snappingSteps: steps))
                {
                    newDefinition.bounds = bounds;
                }

                var min = new Vector3(Mathf.Min(bounds.min.x, bounds.max.x), Mathf.Min(bounds.min.y, bounds.max.y), Mathf.Min(bounds.min.z, bounds.max.z));
                var max = new Vector3(Mathf.Max(bounds.min.x, bounds.max.x), Mathf.Max(bounds.min.y, bounds.max.y), Mathf.Max(bounds.min.z, bounds.max.z));

                var size = (max - min);

                var heightStart = bounds.max.y + (bounds.size.y < 0 ? size.y : 0);

                var edgeHeight = heightStart - stepHeight * stepCount;
                var pHeight0   = new Vector3(min.x, edgeHeight, max.z);
                var pHeight1   = new Vector3(max.x, edgeHeight, max.z);

                var depthStart = bounds.min.z - (bounds.size.z < 0 ? size.z : 0);

                var pDepth0 = new Vector3(min.x, max.y, depthStart + stepDepthOffset);
                var pDepth1 = new Vector3(max.x, max.y, depthStart + stepDepthOffset);

                if (handles.DoTurnHandle(ref bounds))
                {
                    newDefinition.bounds = bounds;
                }

                if (handles.DoEdgeHandle1D(out edgeHeight, Axis.Y, pHeight0, pHeight1, snappingStep: stepHeight))
                {
                    var         totalStepHeight = Mathf.Clamp((heightStart - edgeHeight), size.y % stepHeight, size.y);
                    const float kSmudgeValue    = 0.0001f;
                    var         oldStepCount    = newDefinition.StepCount;
                    var         newStepCount    = Mathf.Max(1, Mathf.FloorToInt((Mathf.Abs(totalStepHeight) + kSmudgeValue) / stepHeight));

                    newDefinition.stepDepth     = (oldStepCount * newDefinition.stepDepth) / newStepCount;
                    newDefinition.plateauHeight = size.y - (stepHeight * newStepCount);
                }

                if (handles.DoEdgeHandle1D(out stepDepthOffset, Axis.Z, pDepth0, pDepth1, snappingStep: ChiselLinearStairsDefinition.kMinStepDepth))
                {
                    stepDepthOffset        -= depthStart;
                    stepDepthOffset         = Mathf.Clamp(stepDepthOffset, 0, this.absDepth - ChiselLinearStairsDefinition.kMinStepDepth);
                    newDefinition.stepDepth = ((this.absDepth - stepDepthOffset) / this.StepCount);
                }

                float heightOffset;
                var   prevModified = handles.modified;
                {
                    var direction = Vector3.Cross(Vector3.forward, pHeight0 - pDepth0).normalized;
                    handles.DoEdgeHandle1DOffset(out var height0vec, Axis.Y, pHeight0, pDepth0, direction, snappingStep: stepHeight);
                    handles.DoEdgeHandle1DOffset(out var height1vec, Axis.Y, pHeight1, pDepth1, direction, snappingStep: stepHeight);
                    var height0 = Vector3.Dot(direction, height0vec);
                    var height1 = Vector3.Dot(direction, height1vec);
                    if (Mathf.Abs(height0) > Mathf.Abs(height1))
                    {
                        heightOffset = height0;
                    }
                    else
                    {
                        heightOffset = height1;
                    }
                }
                if (prevModified != handles.modified)
                {
                    newDefinition.plateauHeight += heightOffset;
                }
            }
            if (handles.modified)
            {
                this = newDefinition;
            }
        }
Example #14
0
 public virtual bool Add(float amount)
 {
     timer = Mathf.Min(timer + amount, CurrentTimeValue);
     return(Finished);
 }
Example #15
0
        public static bool GenerateTorusAsset(CSGBrushMeshAsset brushMeshAsset, CSGTorusDefinition definition)
        {
            Vector3[] vertices = null;
            if (!GenerateTorusVertices(definition, ref vertices))
            {
                brushMeshAsset.Clear();
                return(false);
            }

            definition.Validate();
            var surfaces     = definition.surfaceAssets;
            var descriptions = definition.surfaceDescriptions;
            var tubeRadiusX  = (definition.tubeWidth * 0.5f);
            var tubeRadiusY  = (definition.tubeHeight * 0.5f);
            var torusRadius  = (definition.outerDiameter * 0.5f) - tubeRadiusX;


            var horzSegments = definition.horizontalSegments;
            var vertSegments = definition.verticalSegments;

            var horzDegreePerSegment = (definition.totalAngle / horzSegments);
            var vertDegreePerSegment = (360.0f / vertSegments) * Mathf.Deg2Rad;
            var descriptionIndex     = new int[2 + vertSegments];

            descriptionIndex[0] = 0;
            descriptionIndex[1] = 1;

            var circleVertices = new Vector2[vertSegments];

            var min             = new Vector2(float.PositiveInfinity, float.PositiveInfinity);
            var max             = new Vector2(float.NegativeInfinity, float.NegativeInfinity);
            var tubeAngleOffset = ((((vertSegments & 1) == 1) ? 0.0f : ((360.0f / vertSegments) * 0.5f)) + definition.tubeRotation) * Mathf.Deg2Rad;

            for (int v = 0; v < vertSegments; v++)
            {
                var vRad = tubeAngleOffset + (v * vertDegreePerSegment);
                circleVertices[v] = new Vector2((Mathf.Cos(vRad) * tubeRadiusX) - torusRadius,
                                                (Mathf.Sin(vRad) * tubeRadiusY));
                min.x = Mathf.Min(min.x, circleVertices[v].x);
                min.y = Mathf.Min(min.y, circleVertices[v].y);
                max.x = Mathf.Max(max.x, circleVertices[v].x);
                max.y = Mathf.Max(max.y, circleVertices[v].y);
                descriptionIndex[v + 2] = 2;
            }

            if (definition.fitCircle)
            {
                var center = (max + min) * 0.5f;
                var size   = (max - min) * 0.5f;
                size.x = tubeRadiusX / size.x;
                size.y = tubeRadiusY / size.y;
                for (int v = 0; v < vertSegments; v++)
                {
                    circleVertices[v].x  = (circleVertices[v].x - center.x) * size.x;
                    circleVertices[v].y  = (circleVertices[v].y - center.y) * size.y;
                    circleVertices[v].x -= torusRadius;
                }
            }

            var subMeshes  = new CSGBrushSubMesh[horzSegments];
            var horzOffset = definition.startAngle;

            for (int h = 1, p = 0; h < horzSegments + 1; p = h, h++)
            {
                var hDegree0        = (p * horzDegreePerSegment) + horzOffset;
                var hDegree1        = (h * horzDegreePerSegment) + horzOffset;
                var rotation0       = Quaternion.AngleAxis(hDegree0, Vector3.up);
                var rotation1       = Quaternion.AngleAxis(hDegree1, Vector3.up);
                var subMeshVertices = new Vector3[vertSegments * 2];
                for (int v = 0; v < vertSegments; v++)
                {
                    subMeshVertices[v + vertSegments] = rotation0 * circleVertices[v];
                    subMeshVertices[v] = rotation1 * circleVertices[v];
                }

                var subMesh = new CSGBrushSubMesh();
                CreateExtrudedSubMesh(subMesh, vertSegments, descriptionIndex, descriptionIndex, 0, 1, subMeshVertices, surfaces, descriptions);
                if (!subMesh.Validate())
                {
                    brushMeshAsset.Clear();
                    return(false);
                }
                subMeshes[h - 1] = subMesh;
            }

            brushMeshAsset.SubMeshes = subMeshes;

            brushMeshAsset.CalculatePlanes();
            brushMeshAsset.SetDirty();
            return(true);
        }
Example #16
0
        public static bool GenerateTorusVertices(CSGTorusDefinition definition, ref Vector3[] vertices)
        {
            definition.Validate();
            //var surfaces		= definition.surfaceAssets;
            //var descriptions	= definition.surfaceDescriptions;
            var tubeRadiusX = (definition.tubeWidth * 0.5f);
            var tubeRadiusY = (definition.tubeHeight * 0.5f);
            var torusRadius = (definition.outerDiameter * 0.5f) - tubeRadiusX;


            var horzSegments = definition.horizontalSegments;
            var vertSegments = definition.verticalSegments;

            var horzDegreePerSegment = (definition.totalAngle / horzSegments);
            var vertDegreePerSegment = (360.0f / vertSegments) * Mathf.Deg2Rad;

            var circleVertices = new Vector2[vertSegments];

            var min             = new Vector2(float.PositiveInfinity, float.PositiveInfinity);
            var max             = new Vector2(float.NegativeInfinity, float.NegativeInfinity);
            var tubeAngleOffset = ((((vertSegments & 1) == 1) ? 0.0f : ((360.0f / vertSegments) * 0.5f)) + definition.tubeRotation) * Mathf.Deg2Rad;

            for (int v = 0; v < vertSegments; v++)
            {
                var vRad = tubeAngleOffset + (v * vertDegreePerSegment);
                circleVertices[v] = new Vector2((Mathf.Cos(vRad) * tubeRadiusX) - torusRadius,
                                                (Mathf.Sin(vRad) * tubeRadiusY));
                min.x = Mathf.Min(min.x, circleVertices[v].x);
                min.y = Mathf.Min(min.y, circleVertices[v].y);
                max.x = Mathf.Max(max.x, circleVertices[v].x);
                max.y = Mathf.Max(max.y, circleVertices[v].y);
            }

            if (definition.fitCircle)
            {
                var center = (max + min) * 0.5f;
                var size   = (max - min) * 0.5f;
                size.x = tubeRadiusX / size.x;
                size.y = tubeRadiusY / size.y;
                for (int v = 0; v < vertSegments; v++)
                {
                    circleVertices[v].x  = (circleVertices[v].x - center.x) * size.x;
                    circleVertices[v].y  = (circleVertices[v].y - center.y) * size.y;
                    circleVertices[v].x -= torusRadius;
                }
            }

            if (definition.totalAngle != 360)
            {
                horzSegments++;
            }

            var horzOffset  = definition.startAngle;
            var vertexCount = vertSegments * horzSegments;

            if (vertices == null ||
                vertices.Length != vertexCount)
            {
                vertices = new Vector3[vertexCount];
            }
            for (int h = 0, v = 0; h < horzSegments; h++)
            {
                var hDegree1  = (h * horzDegreePerSegment) + horzOffset;
                var rotation1 = Quaternion.AngleAxis(hDegree1, Vector3.up);
                for (int i = 0; i < vertSegments; i++, v++)
                {
                    vertices[v] = rotation1 * circleVertices[i];
                }
            }
            return(true);
        }