Example #1
0
        public void Update(float elapsedTime)
        {
            Vector3 movementDir = new Vector3();
            if (this.MovementEnabled)
            {
                Vector2 controller = this.main.Camera.GetWorldSpaceControllerCoordinates(this.Movement);
                movementDir = new Vector3(controller.X, 0, controller.Y);
                if (this.Up)
                    movementDir = movementDir.SetComponent(Direction.PositiveY, 1.0f);
                else if (this.Down)
                    movementDir = movementDir.SetComponent(Direction.NegativeY, 1.0f);

                if (this.MapEditMode)
                {
                    bool moving = movementDir.LengthSquared() > 0.0f;

                    // When the user lets go of the key, reset the timer
                    // That way they can hit the key faster than the 0.1 sec interval
                    if (!moving)
                        this.movementInterval = 0.5f;

                    if (this.movementInterval > (this.SpeedMode ? 0.05f : 0.1f))
                    {
                        if (moving)
                            this.movementInterval = 0.0f;
                        if (movementDir.LengthSquared() > 0.0f)
                        {
                            Map map = this.SelectedEntities[0].Get<Map>();
                            Direction relativeDir = map.GetRelativeDirection(movementDir);
                            this.coord = this.coord.Move(relativeDir);
                            if (this.EditSelection)
                            {
                                this.VoxelSelectionStart.Value = new Map.Coordinate
                                {
                                    X = Math.Min(this.selectionStart.X, this.coord.X),
                                    Y = Math.Min(this.selectionStart.Y, this.coord.Y),
                                    Z = Math.Min(this.selectionStart.Z, this.coord.Z),
                                };
                                this.VoxelSelectionEnd.Value = new Map.Coordinate
                                {
                                    X = Math.Max(this.selectionStart.X, this.coord.X) + 1,
                                    Y = Math.Max(this.selectionStart.Y, this.coord.Y) + 1,
                                    Z = Math.Max(this.selectionStart.Z, this.coord.Z) + 1,
                                };
                            }
                            else if (this.TransformMode.Value == TransformModes.Translate)
                            {
                                this.NeedsSave.Value = true;

                                this.restoreMap(this.VoxelSelectionStart, this.VoxelSelectionEnd, !this.voxelDuplicate);

                                Map.Coordinate newSelectionStart = this.VoxelSelectionStart.Value.Move(relativeDir);
                                this.VoxelSelectionStart.Value = newSelectionStart;
                                this.VoxelSelectionEnd.Value = this.VoxelSelectionEnd.Value.Move(relativeDir);

                                this.mapState.Add(map.GetChunksBetween(this.VoxelSelectionStart, this.VoxelSelectionEnd));

                                Map.Coordinate offset = this.originalSelectionStart.Minus(newSelectionStart);
                                this.restoreMap(newSelectionStart, this.VoxelSelectionEnd, false, offset.X, offset.Y, offset.Z);
                            }
                            this.Position.Value = map.GetAbsolutePosition(this.coord);
                        }
                    }
                    this.movementInterval += elapsedTime;
                }
                else
                    this.Position.Value = this.Position.Value + movementDir * (this.SpeedMode ? 50.0f : 25.0f) * elapsedTime;
            }

            if (this.MapEditMode)
            {
                if (!this.Fill && !this.Empty)
                    this.justCommitedOrRevertedVoxelOperation = false;

                Map map = this.SelectedEntities[0].Get<Map>();
                Map.Coordinate coord = map.GetCoordinate(this.Position);
                if (this.TransformMode.Value == TransformModes.None && (this.Fill || this.Empty || this.Extend) && !this.justCommitedOrRevertedVoxelOperation)
                {
                    this.NeedsSave.Value = true;
                    if (this.Brush == "[Procedural]")
                    {
                        ProceduralGenerator generator = this.Entity.Get<ProceduralGenerator>();
                        if (this.Fill)
                        {
                            if (this.VoxelSelectionActive)
                            {
                                foreach (Map.Coordinate c in this.VoxelSelectionStart.Value.CoordinatesBetween(this.VoxelSelectionEnd))
                                    map.Fill(c, generator.GetValue(map, c));
                            }
                            else
                                this.brushStroke(map, coord, this.BrushSize, x => generator.GetValue(map, x), true, false);
                        }
                        else if (this.Empty)
                        {
                            if (this.VoxelSelectionActive)
                                map.Empty(this.VoxelSelectionStart.Value.CoordinatesBetween(this.VoxelSelectionEnd).Where(x => generator.GetValue(map, x).ID == 0));
                            else
                                this.brushStroke(map, coord, this.BrushSize, x => generator.GetValue(map, x), false, true);
                        }
                    }
                    else
                    {
                        if (this.Fill)
                        {
                            Map.CellState material;
                            if (WorldFactory.StatesByName.TryGetValue(this.Brush, out material))
                            {
                                if (this.VoxelSelectionActive)
                                    map.Fill(this.VoxelSelectionStart, this.VoxelSelectionEnd, material);
                                else
                                    this.brushStroke(map, coord, this.BrushSize, material);
                            }
                        }
                        else if (this.Empty)
                        {
                            if (this.VoxelSelectionActive)
                                map.Empty(this.VoxelSelectionStart, this.VoxelSelectionEnd);
                            else
                                this.brushStroke(map, coord, this.BrushSize, new Map.CellState());
                        }
                    }

                    if (this.Extend && !this.coord.Equivalent(this.lastCoord))
                    {
                        Direction dir = DirectionExtensions.GetDirectionFromVector(Vector3.TransformNormal(movementDir, Matrix.Invert(map.Transform)));
                        Map.Box box = map.GetBox(this.lastCoord);
                        bool grow = map.GetBox(this.coord) != box;
                        if (box != null)
                        {
                            List<Map.Coordinate> removals = new List<Map.Coordinate>();
                            if (dir.IsParallel(Direction.PositiveX))
                            {
                                for (int y = box.Y; y < box.Y + box.Height; y++)
                                {
                                    for (int z = box.Z; z < box.Z + box.Depth; z++)
                                    {
                                        if (grow)
                                            map.Fill(this.coord.X, y, z, box.Type);
                                        else
                                            removals.Add(map.GetCoordinate(this.lastCoord.X, y, z));
                                    }
                                }
                            }
                            if (dir.IsParallel(Direction.PositiveY))
                            {
                                for (int x = box.X; x < box.X + box.Width; x++)
                                {
                                    for (int z = box.Z; z < box.Z + box.Depth; z++)
                                    {
                                        if (grow)
                                            map.Fill(x, this.coord.Y, z, box.Type);
                                        else
                                            removals.Add(map.GetCoordinate(x, this.lastCoord.Y, z));
                                    }
                                }
                            }
                            if (dir.IsParallel(Direction.PositiveZ))
                            {
                                for (int x = box.X; x < box.X + box.Width; x++)
                                {
                                    for (int y = box.Y; y < box.Y + box.Height; y++)
                                    {
                                        if (grow)
                                            map.Fill(x, y, this.coord.Z, box.Type);
                                        else
                                            removals.Add(map.GetCoordinate(x, y, this.lastCoord.Z));
                                    }
                                }
                            }
                            map.Empty(removals);
                        }
                    }
                    map.Regenerate();
                }
                this.lastCoord = this.coord;
            }
            else if (this.TransformMode.Value == TransformModes.Translate)
            {
                // Translate entities
                this.NeedsSave.Value = true;
                float rayLength = (this.transformCenter - this.main.Camera.Position.Value).Length();
                Vector2 mouseOffset = this.Mouse - this.originalTransformMouse;
                Vector3 offset = ((this.main.Camera.Right.Value * mouseOffset.X * rayLength) + (this.main.Camera.Up.Value * -mouseOffset.Y * rayLength)) * 0.0025f;
                switch (this.TransformAxis.Value)
                {
                    case TransformAxes.X:
                        offset.Y = offset.Z = 0.0f;
                        break;
                    case TransformAxes.Y:
                        offset.X = offset.Z = 0.0f;
                        break;
                    case TransformAxes.Z:
                        offset.X = offset.Y = 0.0f;
                        break;
                }
                if (this.SelectedTransform.Value != null)
                    this.SelectedTransform.Value.Position.Value = this.offsetTransforms[0].Translation + offset;
                else
                {
                    int i = 0;
                    foreach (Entity entity in this.SelectedEntities)
                    {
                        Transform transform = entity.Get<Transform>();
                        if (transform != null)
                        {
                            Matrix originalTransform = this.offsetTransforms[i];
                            transform.Position.Value = originalTransform.Translation + offset;
                            i++;
                        }
                    }
                }
            }
            else if (this.TransformMode.Value == TransformModes.Rotate)
            {
                // Rotate entities
                this.NeedsSave.Value = true;
                Vector3 screenSpaceCenter = this.main.GraphicsDevice.Viewport.Project(this.transformCenter, this.main.Camera.Projection, this.main.Camera.View, Matrix.Identity);
                Vector2 originalOffset = new Vector2(this.originalTransformMouse.X - screenSpaceCenter.X, this.originalTransformMouse.Y - screenSpaceCenter.Y);
                float originalAngle = (float)Math.Atan2(originalOffset.Y, originalOffset.X);
                Vector2 newOffset = new Vector2(this.Mouse.Value.X - screenSpaceCenter.X, this.Mouse.Value.Y - screenSpaceCenter.Y);
                float newAngle = (float)Math.Atan2(newOffset.Y, newOffset.X);
                Vector3 axis = this.main.Camera.Forward;
                switch (this.TransformAxis.Value)
                {
                    case TransformAxes.X:
                        axis = Vector3.Right;
                        break;
                    case TransformAxes.Y:
                        axis = Vector3.Up;
                        break;
                    case TransformAxes.Z:
                        axis = Vector3.Forward;
                        break;
                }
                if (this.SelectedTransform.Value != null)
                {
                    Matrix originalTransform = this.offsetTransforms[0];
                    originalTransform.Translation -= this.transformCenter;
                    originalTransform *= Matrix.CreateFromAxisAngle(axis, newAngle - originalAngle);
                    originalTransform.Translation += this.transformCenter;
                    this.SelectedTransform.Value.Matrix.Value = originalTransform;
                }
                else
                {
                    int i = 0;
                    foreach (Entity entity in this.SelectedEntities)
                    {
                        Transform transform = entity.Get<Transform>();
                        if (transform != null)
                        {
                            Matrix originalTransform = this.offsetTransforms[i];
                            originalTransform.Translation -= this.transformCenter;
                            originalTransform *= Matrix.CreateFromAxisAngle(axis, newAngle - originalAngle);
                            originalTransform.Translation += this.transformCenter;
                            transform.Matrix.Value = originalTransform;
                            i++;
                        }
                    }
                }
            }
        }
Example #2
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            PointLight light = result.GetOrCreate<PointLight>("PointLight");
            light.Serialize = false;

            const float defaultLightAttenuation = 15.0f;
            light.Attenuation.Value = defaultLightAttenuation;

            Transform transform = result.GetOrCreate<Transform>("Transform");
            light.Add(new Binding<Vector3>(light.Position, transform.Position));

            VoxelChaseAI chase = result.GetOrCreate<VoxelChaseAI>("VoxelChaseAI");

            chase.Filter = delegate(Map.CellState state)
            {
                return state.ID == 0 ? VoxelChaseAI.Cell.Empty : VoxelChaseAI.Cell.Filled;
            };

            chase.Add(new TwoWayBinding<Vector3>(transform.Position, chase.Position));
            result.Add(new CommandBinding(chase.Delete, result.Delete));

            Sound sound = result.GetOrCreate<Sound>("LoopSound");
            sound.Serialize = false;
            sound.Cue.Value = "Orb Loop";
            sound.Is3D.Value = true;
            sound.IsPlaying.Value = true;
            sound.Add(new Binding<Vector3>(sound.Position, chase.Position));
            Property<float> volume = sound.GetProperty("Volume");
            Property<float> pitch = sound.GetProperty("Pitch");

            const float defaultVolume = 0.5f;
            volume.Value = defaultVolume;

            AI ai = result.GetOrCreate<AI>();

            Model model = result.GetOrCreate<Model>();
            model.Add(new Binding<Matrix>(model.Transform, transform.Matrix));
            model.Filename.Value = "Models\\sphere";
            model.Editable = false;
            model.Serialize = false;

            const float defaultModelScale = 0.25f;
            model.Scale.Value = new Vector3(defaultModelScale);

            model.Add(new Binding<Vector3, string>(model.Color, delegate(string state)
            {
                switch (state)
                {
                    case "Alert":
                        return new Vector3(1.5f, 1.5f, 0.5f);
                    case "Chase":
                        return new Vector3(1.5f, 0.5f, 0.5f);
                    case "Levitating":
                        return new Vector3(2.0f, 1.0f, 0.5f);
                    case "Idle":
                        return new Vector3(1.0f, 1.0f, 1.0f);
                    default:
                        return new Vector3(0.0f, 0.0f, 0.0f);
                }
            }, ai.CurrentState));

            Random random = new Random();
            result.Add(new Updater
            {
                delegate(float dt)
                {
                    float source = ((float)random.NextDouble() - 0.5f) * 2.0f;
                    model.Scale.Value = new Vector3(defaultModelScale * (1.0f + (source * 0.5f)));
                    light.Attenuation.Value = defaultLightAttenuation * (1.0f + (source * 0.05f));
                }
            });

            model.Add(new Binding<bool, string>(model.Enabled, x => x != "Exploding", ai.CurrentState));

            light.Add(new Binding<Vector3>(light.Color, model.Color));

            Agent agent = result.GetOrCreate<Agent>();
            agent.Add(new Binding<Vector3>(agent.Position, chase.Position));

            Property<int> operationalRadius = result.GetOrMakeProperty<int>("OperationalRadius", true, 100);

            AI.Task checkOperationalRadius = new AI.Task
            {
                Interval = 2.0f,
                Action = delegate()
                {
                    bool shouldBeActive = (chase.Position.Value - main.Camera.Position).Length() < operationalRadius;
                    if (shouldBeActive && ai.CurrentState == "Suspended")
                        ai.CurrentState.Value = "Idle";
                    else if (!shouldBeActive && ai.CurrentState != "Suspended")
                        ai.CurrentState.Value = "Suspended";
                },
            };

            const float sightDistance = 30.0f;
            const float hearingDistance = 15.0f;

            ai.Add(new AI.State
            {
                Name = "Idle",
                Enter = delegate(AI.State previous)
                {
                    chase.Speed.Value = 3.0f;
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action = delegate()
                        {
                            Agent a = Agent.Query(chase.Position, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                            if (a != null)
                                ai.CurrentState.Value = "Alert";
                        },
                    },
                },
            });

            Property<Entity.Handle> targetAgent = result.GetOrMakeProperty<Entity.Handle>("TargetAgent");

            ai.Add(new AI.State
            {
                Name = "Alert",
                Enter = delegate(AI.State previous)
                {
                    chase.Enabled.Value = false;
                },
                Exit = delegate(AI.State next)
                {
                    chase.Enabled.Value = true;
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action = delegate()
                        {
                            if (ai.TimeInCurrentState > 3.0f)
                                ai.CurrentState.Value = "Idle";
                            else
                            {
                                Agent a = Agent.Query(chase.Position, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                                if (a != null)
                                {
                                    targetAgent.Value = a.Entity;
                                    ai.CurrentState.Value = "Chase";
                                }
                            }
                        },
                    },
                },
            });

            AI.Task checkTargetAgent = new AI.Task
            {
                Action = delegate()
                {
                    Entity target = targetAgent.Value.Target;
                    if (target == null || !target.Active)
                    {
                        targetAgent.Value = null;
                        ai.CurrentState.Value = "Idle";
                    }
                },
            };

            // Levitate

            Property<Entity.Handle> levitatingMap = result.GetOrMakeProperty<Entity.Handle>("LevitatingMap");
            Property<Map.Coordinate> grabCoord = result.GetOrMakeProperty<Map.Coordinate>("GrabCoord");

            const int levitateRipRadius = 4;

            Func<bool> tryLevitate = delegate()
            {
                Map map = chase.Map.Value.Target.Get<Map>();
                Map.Coordinate? candidate = map.FindClosestFilledCell(chase.Coord, 3);

                if (!candidate.HasValue)
                    return false;

                Map.Coordinate center = candidate.Value;
                if (!map[center].Permanent)
                {
                    // Break off a chunk of this map into a new DynamicMap.

                    List<Map.Coordinate> edges = new List<Map.Coordinate>();

                    Map.Coordinate ripStart = center.Move(-levitateRipRadius, -levitateRipRadius, -levitateRipRadius);
                    Map.Coordinate ripEnd = center.Move(levitateRipRadius, levitateRipRadius, levitateRipRadius);

                    Dictionary<Map.Box, bool> permanentBoxes = new Dictionary<Map.Box, bool>();
                    foreach (Map.Coordinate c in ripStart.CoordinatesBetween(ripEnd))
                    {
                        Map.Box box = map.GetBox(c);
                        if (box != null && box.Type.Permanent)
                            permanentBoxes[box] = true;
                    }

                    foreach (Map.Box b in permanentBoxes.Keys)
                    {
                        // Top and bottom
                        for (int x = b.X - 1; x <= b.X + b.Width; x++)
                        {
                            for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
                            {
                                Map.Coordinate coord = new Map.Coordinate { X = x, Y = b.Y + b.Height, Z = z };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);

                                coord = new Map.Coordinate { X = x, Y = b.Y - 1, Z = z };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);
                            }
                        }

                        // Outer shell
                        for (int y = b.Y; y < b.Y + b.Height; y++)
                        {
                            // Left and right
                            for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
                            {
                                Map.Coordinate coord = new Map.Coordinate { X = b.X - 1, Y = y, Z = z };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);

                                coord = new Map.Coordinate { X = b.X + b.Width, Y = y, Z = z };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);
                            }

                            // Backward and forward
                            for (int x = b.X; x < b.X + b.Width; x++)
                            {
                                Map.Coordinate coord = new Map.Coordinate { X = x, Y = y, Z = b.Z - 1 };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);

                                coord = new Map.Coordinate { X = x, Y = y, Z = b.Z + b.Depth };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);
                            }
                        }
                    }

                    if (edges.Contains(center))
                        return false;

                    // Top and bottom
                    for (int x = ripStart.X; x <= ripEnd.X; x++)
                    {
                        for (int z = ripStart.Z; z <= ripEnd.Z; z++)
                        {
                            edges.Add(new Map.Coordinate { X = x, Y = ripStart.Y, Z = z });
                            edges.Add(new Map.Coordinate { X = x, Y = ripEnd.Y, Z = z });
                        }
                    }

                    // Sides
                    for (int y = ripStart.Y + 1; y <= ripEnd.Y - 1; y++)
                    {
                        // Left and right
                        for (int z = ripStart.Z; z <= ripEnd.Z; z++)
                        {
                            edges.Add(new Map.Coordinate { X = ripStart.X, Y = y, Z = z });
                            edges.Add(new Map.Coordinate { X = ripEnd.X, Y = y, Z = z });
                        }

                        // Backward and forward
                        for (int x = ripStart.X; x <= ripEnd.X; x++)
                        {
                            edges.Add(new Map.Coordinate { X = x, Y = y, Z = ripStart.Z });
                            edges.Add(new Map.Coordinate { X = x, Y = y, Z = ripEnd.Z });
                        }
                    }

                    map.Empty(edges);
                    map.Regenerate(delegate(List<DynamicMap> spawnedMaps)
                    {
                        foreach (DynamicMap spawnedMap in spawnedMaps)
                        {
                            if (spawnedMap[center].ID != 0)
                            {
                                levitatingMap.Value = spawnedMap.Entity;
                                break;
                            }
                        }
                    });

                    grabCoord.Value = center;
                    return true;
                }
                return false;
            };

            Action delevitateMap = delegate()
            {
                Entity levitatingMapEntity = levitatingMap.Value.Target;
                if (levitatingMapEntity == null || !levitatingMapEntity.Active)
                    return;

                DynamicMap dynamicMap = levitatingMapEntity.Get<DynamicMap>();

                int maxDistance = levitateRipRadius + 7;
                Map closestMap = null;
                Map.Coordinate closestCoord = new Map.Coordinate();
                foreach (Map m in Map.ActivePhysicsMaps)
                {
                    if (m == dynamicMap)
                        continue;

                    Map.Coordinate relativeCoord = m.GetCoordinate(dynamicMap.Transform.Value.Translation);
                    Map.Coordinate? closestFilled = m.FindClosestFilledCell(relativeCoord, maxDistance);
                    if (closestFilled != null)
                    {
                        maxDistance = Math.Min(Math.Abs(relativeCoord.X - closestFilled.Value.X), Math.Min(Math.Abs(relativeCoord.Y - closestFilled.Value.Y), Math.Abs(relativeCoord.Z - closestFilled.Value.Z)));
                        closestMap = m;
                        closestCoord = closestFilled.Value;
                    }
                }
                if (closestMap != null)
                {
                    // Combine this map with the other one

                    Direction x = closestMap.GetRelativeDirection(dynamicMap.GetAbsoluteVector(Vector3.Right));
                    Direction y = closestMap.GetRelativeDirection(dynamicMap.GetAbsoluteVector(Vector3.Up));
                    Direction z = closestMap.GetRelativeDirection(dynamicMap.GetAbsoluteVector(Vector3.Backward));

                    if (x.IsParallel(y))
                        x = y.Cross(z);
                    else if (y.IsParallel(z))
                        y = x.Cross(z);

                    Map.Coordinate offset = new Map.Coordinate();
                    float closestCoordDistance = float.MaxValue;
                    Vector3 closestCoordPosition = closestMap.GetAbsolutePosition(closestCoord);
                    foreach (Map.Coordinate c in dynamicMap.Chunks.SelectMany(c => c.Boxes).SelectMany(b => b.GetCoords()))
                    {
                        float distance = (dynamicMap.GetAbsolutePosition(c) - closestCoordPosition).LengthSquared();
                        if (distance < closestCoordDistance)
                        {
                            closestCoordDistance = distance;
                            offset = c;
                        }
                    }
                    Vector3 toLevitatingMap = dynamicMap.Transform.Value.Translation - closestMap.GetAbsolutePosition(closestCoord);
                    offset = offset.Move(dynamicMap.GetRelativeDirection(-toLevitatingMap));

                    Matrix orientation = dynamicMap.Transform.Value;
                    orientation.Translation = Vector3.Zero;

                    EffectBlockFactory blockFactory = Factory.Get<EffectBlockFactory>();

                    int index = 0;
                    foreach (Map.Coordinate c in dynamicMap.Chunks.SelectMany(c => c.Boxes).SelectMany(b => b.GetCoords()).OrderBy(c2 => new Vector3(c2.X - offset.X, c2.Y - offset.Y, c2.Z - offset.Z).LengthSquared()))
                    {
                        Map.Coordinate offsetFromCenter = c.Move(-offset.X, -offset.Y, -offset.Z);
                        Map.Coordinate targetCoord = new Map.Coordinate();
                        targetCoord.SetComponent(x, offsetFromCenter.GetComponent(Direction.PositiveX));
                        targetCoord.SetComponent(y, offsetFromCenter.GetComponent(Direction.PositiveY));
                        targetCoord.SetComponent(z, offsetFromCenter.GetComponent(Direction.PositiveZ));
                        targetCoord = targetCoord.Move(closestCoord.X, closestCoord.Y, closestCoord.Z);
                        if (closestMap[targetCoord].ID == 0)
                        {
                            Entity block = blockFactory.CreateAndBind(main);
                            c.Data.ApplyToEffectBlock(block.Get<ModelInstance>());
                            block.GetProperty<Vector3>("Offset").Value = closestMap.GetRelativePosition(targetCoord);
                            block.GetProperty<bool>("Scale").Value = false;
                            block.GetProperty<Vector3>("StartPosition").Value = dynamicMap.GetAbsolutePosition(c);
                            block.GetProperty<Matrix>("StartOrientation").Value = orientation;
                            block.GetProperty<float>("TotalLifetime").Value = 0.05f + (index * 0.0075f);
                            blockFactory.Setup(block, closestMap.Entity, targetCoord, c.Data.ID);
                            main.Add(block);
                            index++;
                        }
                    }

                    // Delete the map
                    levitatingMapEntity.Delete.Execute();
                }
            };

            // Chase AI state

            ai.Add(new AI.State
            {
                Name = "Chase",
                Enter = delegate(AI.State previous)
                {
                    chase.Speed.Value = 10.0f;
                    chase.TargetActive.Value = true;
                },
                Exit = delegate(AI.State next)
                {
                    chase.TargetActive.Value = false;
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    checkTargetAgent,
                    new AI.Task
                    {
                        Interval = 0.1f,
                        Action = delegate()
                        {
                            Entity target = targetAgent.Value.Target;
                            Vector3 targetPosition = target.Get<Transform>().Position;
                            chase.Target.Value = targetPosition;
                            Entity levitatingMapEntity = levitatingMap.Value.Target;
                            if ((targetPosition - chase.Position).Length() < 10.0f && (levitatingMapEntity == null || !levitatingMapEntity.Active))
                            {
                                if (tryLevitate())
                                    ai.CurrentState.Value = "Levitating";
                            }
                        }
                    }
                },
            });

            Property<Vector3> lastPosition = result.GetOrMakeProperty<Vector3>("LastPosition");
            Property<Vector3> nextPosition = result.GetOrMakeProperty<Vector3>("NextPosition");
            Property<float> positionBlend = result.GetOrMakeProperty<float>("PositionBlend");

            Action findNextPosition = delegate()
            {
                lastPosition.Value = chase.Position.Value;
                nextPosition.Value = targetAgent.Value.Target.Get<Transform>().Position + new Vector3((float)random.NextDouble() - 0.5f, (float)random.NextDouble(), (float)random.NextDouble() - 0.5f) * 5.0f;
                positionBlend.Value = 0.0f;
            };

            ai.Add(new AI.State
            {
                Name = "Levitating",
                Enter = delegate(AI.State previous)
                {
                    chase.Enabled.Value = false;
                    findNextPosition();
                },
                Exit = delegate(AI.State next)
                {
                    delevitateMap();
                    levitatingMap.Value = null;

                    Map map = chase.Map.Value.Target.Get<Map>();
                    Map.Coordinate currentCoord = map.GetCoordinate(chase.Position);
                    Map.Coordinate? closest = map.FindClosestFilledCell(currentCoord, 10);
                    if (closest.HasValue)
                    {
                        chase.LastCoord.Value = currentCoord;
                        chase.Coord.Value = closest.Value;
                        chase.Blend.Value = 0.0f;
                    }
                    chase.Enabled.Value = true;
                    volume.Value = defaultVolume;
                    pitch.Value = 0.0f;
                },
                Tasks = new[]
                {
                    checkTargetAgent,
                    new AI.Task
                    {
                        Action = delegate()
                        {
                            volume.Value = 1.0f;
                            pitch.Value = 1.0f;
                            Entity levitatingMapEntity = levitatingMap.Value.Target;
                            if (!levitatingMapEntity.Active || ai.TimeInCurrentState.Value > 8.0f)
                            {
                                ai.CurrentState.Value = "Alert";
                                return;
                            }

                            DynamicMap dynamicMap = levitatingMapEntity.Get<DynamicMap>();

                            positionBlend.Value += (main.ElapsedTime.Value / 1.0f);
                            if (positionBlend > 1.0f)
                                findNextPosition();

                            chase.Position.Value = Vector3.Lerp(lastPosition, nextPosition, positionBlend);

                            Vector3 grabPoint = dynamicMap.GetAbsolutePosition(grabCoord);
                            Vector3 diff = chase.Position.Value - grabPoint;
                            if (diff.Length() > 15.0f)
                            {
                                ai.CurrentState.Value = "Chase";
                                return;
                            }

                            diff *= (float)Math.Sqrt(dynamicMap.PhysicsEntity.Mass) * 0.5f;
                            dynamicMap.PhysicsEntity.ApplyImpulse(ref grabPoint, ref diff);
                        },
                    },
                },
            });

            this.SetMain(result, main);
        }
Example #3
0
        public override void InitializeProperties()
        {
            this.Spawn.Action = delegate(string type)
            {
                if (Factory.Get(type) != null)
                {
                    Entity entity = Factory.CreateAndBind(this.main, type);
                    Transform position = entity.Get<Transform>();
                    if (position != null)
                        position.Position.Value = this.Position;
                    this.NeedsSave.Value = true;
                    this.main.Add(entity);
                    this.SelectedEntities.Clear();
                    this.SelectedEntities.Add(entity);
                    this.StartTranslation.Execute();
                }
            };

            this.Save.Action = delegate()
            {
                IO.MapLoader.Save(this.main, null, this.main.MapFile);
                this.NeedsSave.Value = false;
            };

            this.Duplicate.Action = delegate()
            {
                this.NeedsSave.Value = true;

                if (this.TransformMode.Value != TransformModes.None)
                    this.CommitTransform.Execute();

                IEnumerable<Entity> entities = this.SelectedEntities.ToList();
                this.SelectedEntities.Clear();
                foreach (Entity entity in entities)
                {
                    Entity copy = Factory.Duplicate(this.main, entity);
                    this.main.Add(copy);
                    this.SelectedEntities.Add(copy);
                }
                this.StartTranslation.Execute();
            };

            this.Brush.Value = "[Procedural]";

            this.MapEditMode.Set = delegate(bool value)
            {
                bool oldValue = this.MapEditMode.InternalValue;
                this.MapEditMode.InternalValue = value;
                if (value && !oldValue)
                {
                    this.Orientation.Value = this.SelectedEntities[0].Get<Transform>().Orientation;
                    this.lastCoord = this.coord = this.SelectedEntities[0].Get<Map>().GetCoordinate(this.Position);
                }
                else if (!value && oldValue)
                    this.Orientation.Value = Matrix.Identity;
            };

            this.SelectedEntities.ItemAdded += delegate(int index, Entity t)
            {
                Property<bool> selected = t.GetProperty<bool>("EditorSelected");
                if (selected != null)
                    selected.Value = true;
                this.VoxelSelectionEnd.Value = this.VoxelSelectionStart.Value;
                this.SelectedTransform.Value = null;
            };

            this.SelectedEntities.ItemRemoved += delegate(int index, Entity t)
            {
                Property<bool> selected = t.GetProperty<bool>("EditorSelected");
                if (selected != null)
                    selected.Value = false;
                this.VoxelSelectionEnd.Value = this.VoxelSelectionStart.Value;
                this.SelectedTransform.Value = null;
            };

            this.SelectedEntities.Clearing += delegate()
            {
                foreach (Entity e in this.SelectedEntities)
                {
                    Property<bool> selected = e.GetProperty<bool>("EditorSelected");
                    if (selected != null)
                        selected.Value = false;
                }
                this.VoxelSelectionEnd.Value = this.VoxelSelectionStart.Value;
                this.SelectedTransform.Value = null;
            };

            this.EditSelection.Set = delegate(bool value)
            {
                if (value && !this.EditSelection.InternalValue)
                {
                    this.selectionStart = this.coord;
                    this.VoxelSelectionStart.Value = this.coord;
                    this.VoxelSelectionEnd.Value = this.coord.Move(1, 1, 1);
                }
                else if (!value && this.EditSelection.InternalValue)
                {
                    if (this.VoxelSelectionEnd.Value.Equivalent(this.VoxelSelectionStart.Value.Move(1, 1, 1)))
                        this.VoxelSelectionEnd.Value = this.VoxelSelectionStart.Value;
                }
                this.EditSelection.InternalValue = value;
            };

            this.VoxelCopy.Action = delegate()
            {
                if (this.MapEditMode && this.VoxelSelectionActive)
                {
                    Map m = this.SelectedEntities[0].Get<Map>();
                    this.originalSelectionStart = this.VoxelSelectionStart;
                    this.originalSelectionEnd = this.VoxelSelectionEnd;
                    this.originalSelectionCoord = this.coord;
                    this.mapState = new Map.MapState(m.GetChunksBetween(this.originalSelectionStart, this.originalSelectionEnd));
                    this.voxelDuplicate = false;
                }
            };

            this.VoxelPaste.Action = delegate()
            {
                if (this.MapEditMode && this.mapState != null)
                {
                    Map m = this.SelectedEntities[0].Get<Map>();
                    Map.Coordinate newSelectionStart = this.coord.Plus(this.originalSelectionStart.Minus(this.originalSelectionCoord));
                    this.VoxelSelectionStart.Value = newSelectionStart;
                    this.VoxelSelectionEnd.Value = this.coord.Plus(this.originalSelectionEnd.Minus(this.originalSelectionCoord));

                    this.mapState.Add(m.GetChunksBetween(this.VoxelSelectionStart, this.VoxelSelectionEnd));

                    Map.Coordinate offset = this.originalSelectionStart.Minus(newSelectionStart);
                    this.restoreMap(newSelectionStart, this.VoxelSelectionEnd, false, offset.X, offset.Y, offset.Z);
                }
            };

            this.StartVoxelTranslation.Action = delegate()
            {
                if (this.MapEditMode && this.VoxelSelectionActive)
                {
                    this.VoxelCopy.Execute();
                    this.TransformMode.Value = TransformModes.Translate;
                }
            };

            this.VoxelDuplicate.Action = delegate()
            {
                if (this.MapEditMode && this.VoxelSelectionActive)
                {
                    this.StartVoxelTranslation.Execute();
                    this.voxelDuplicate = true;
                }
            };

            this.PropagateMaterial.Action = delegate()
            {
                if (!this.MapEditMode)
                    return;

                Map m = this.SelectedEntities[0].Get<Map>();
                Map.Box selectedBox = m.GetBox(this.coord);
                if (selectedBox == null)
                    return;

                Map.Coordinate startSelection = this.VoxelSelectionStart;
                Map.Coordinate endSelection = this.VoxelSelectionEnd;
                bool selectionActive = this.VoxelSelectionActive;

                Map.CellState material;
                if (WorldFactory.StatesByName.TryGetValue(this.Brush, out material))
                {
                    IEnumerable<Map.Coordinate> coordEnumerable;
                    if (selectionActive)
                        coordEnumerable = m.GetContiguousByType(new Map.Box[] { selectedBox }).SelectMany(x => x.GetCoords().Where(y => y.Between(startSelection, endSelection)));
                    else
                        coordEnumerable = m.GetContiguousByType(new Map.Box[] { selectedBox }).SelectMany(x => x.GetCoords());

                    List<Map.Coordinate> coords = coordEnumerable.ToList();
                    m.Empty(coords);
                    foreach (Map.Coordinate c in coords)
                        m.Fill(c, material);
                    m.Regenerate();
                }
            };

            this.SampleMaterial.Action = delegate()
            {
                if (!this.MapEditMode)
                    return;

                Map m = this.SelectedEntities[0].Get<Map>();
                Map.Box selectedBox = m.GetBox(this.coord);
                if (selectedBox == null)
                    return;

                this.Brush.Value = selectedBox.Type.Name;
            };

            this.DeleteMaterial.Action = delegate()
            {
                if (!this.MapEditMode)
                    return;

                Map m = this.SelectedEntities[0].Get<Map>();
                Map.Box selectedBox = m.GetBox(this.coord);
                if (selectedBox == null)
                    return;

                Map.Coordinate startSelection = this.VoxelSelectionStart;
                Map.Coordinate endSelection = this.VoxelSelectionEnd;
                bool selectionActive = this.VoxelSelectionActive;

                Map.CellState material;
                if (WorldFactory.StatesByName.TryGetValue(this.Brush, out material))
                {
                    IEnumerable<Map.Coordinate> coordEnumerable;
                    if (selectionActive)
                        coordEnumerable = m.GetContiguousByType(new Map.Box[] { selectedBox }).SelectMany(x => x.GetCoords().Where(y => y.Between(startSelection, endSelection)));
                    else
                        coordEnumerable = m.GetContiguousByType(new Map.Box[] { selectedBox }).SelectMany(x => x.GetCoords());

                    List<Map.Coordinate> coords = coordEnumerable.ToList();
                    m.Empty(coords);
                    m.Regenerate();
                }
            };

            Action<TransformModes> startTransform = delegate(TransformModes mode)
            {
                this.TransformMode.Value = mode;
                this.TransformAxis.Value = TransformAxes.All;
                this.originalTransformMouse = this.Mouse;
                this.offsetTransforms.Clear();
                this.transformCenter = Vector3.Zero;
                if (this.SelectedTransform.Value != null)
                {
                    this.offsetTransforms.Add(this.SelectedTransform.Value.Matrix);
                    this.transformCenter = this.SelectedTransform.Value.Position;
                }
                else
                {
                    int entityCount = 0;
                    foreach (Entity entity in this.SelectedEntities)
                    {
                        Transform transform = entity.Get<Transform>();
                        if (transform != null)
                        {
                            this.offsetTransforms.Add(transform.Matrix);
                            this.transformCenter += transform.Position;
                            entityCount++;
                        }
                    }
                    this.transformCenter /= (float)entityCount;
                }
            };

            this.StartTranslation.Action = delegate()
            {
                startTransform(TransformModes.Translate);
            };

            this.StartRotation.Action = delegate()
            {
                startTransform(TransformModes.Rotate);
            };

            this.CommitTransform.Action = delegate()
            {
                this.NeedsSave.Value = true;
                this.TransformMode.Value = TransformModes.None;
                this.TransformAxis.Value = TransformAxes.All;
                if (this.MapEditMode)
                    this.justCommitedOrRevertedVoxelOperation = true;
                this.offsetTransforms.Clear();
            };

            this.RevertTransform.Action = delegate()
            {
                this.TransformMode.Value = TransformModes.None;
                if (this.MapEditMode)
                {
                    this.restoreMap(this.VoxelSelectionStart, this.VoxelSelectionEnd, false);
                    this.VoxelSelectionStart.Value = this.originalSelectionStart;
                    this.VoxelSelectionEnd.Value = this.originalSelectionEnd;
                    this.restoreMap(this.VoxelSelectionStart, this.VoxelSelectionEnd, false);
                    this.justCommitedOrRevertedVoxelOperation = true;
                }
                else
                {
                    this.TransformAxis.Value = TransformAxes.All;
                    if (this.SelectedTransform.Value != null)
                        this.SelectedTransform.Value.Matrix.Value = this.offsetTransforms[0];
                    else
                    {
                        int i = 0;
                        foreach (Entity entity in this.SelectedEntities)
                        {
                            Transform transform = entity.Get<Transform>();
                            if (transform != null)
                            {
                                transform.Matrix.Value = this.offsetTransforms[i];
                                i++;
                            }
                        }
                    }
                    this.offsetTransforms.Clear();
                }
            };

            this.DeleteSelected.Action = delegate()
            {
                this.NeedsSave.Value = true;
                this.TransformMode.Value = TransformModes.None;
                this.TransformAxis.Value = TransformAxes.All;
                this.offsetTransforms.Clear();
                foreach (Entity entity in this.SelectedEntities)
                    entity.Delete.Execute();
                this.SelectedEntities.Clear();
            };

            this.Add(new Binding<bool>(this.VoxelSelectionActive, delegate()
            {
                if (!this.MapEditMode)
                    return false;
                Map.Coordinate start = this.VoxelSelectionStart, end = this.VoxelSelectionEnd;
                return start.X != end.X && start.Y != end.Y && start.Z != end.Z;
            }, this.MapEditMode, this.VoxelSelectionStart, this.VoxelSelectionEnd));
        }
Example #4
0
        // Classic 3D perlin noise
        float noise3d(Vector3 pos)
        {
            Map.Coordinate cell = new Map.Coordinate { X = (int)Math.Floor(pos.X) & 255, Y = (int)Math.Floor(pos.Y) & 255, Z = (int)Math.Floor(pos.Z) & 255 };

            Vector3 withinCell = pos - new Vector3(cell.X, cell.Y, cell.Z);

            // Calculate contribution of gradients from each cell
            float contribution000 = Vector3.Dot(this.gradientAtCell3d(cell), withinCell);
            float contribution001 = Vector3.Dot(this.gradientAtCell3d(cell.Move(0, 0, 1)), withinCell - new Vector3(0, 0, 1));
            float contribution010 = Vector3.Dot(this.gradientAtCell3d(cell.Move(0, 1, 0)), withinCell - new Vector3(0, 1, 0));
            float contribution011 = Vector3.Dot(this.gradientAtCell3d(cell.Move(0, 1, 1)), withinCell - new Vector3(0, 1, 1));
            float contribution100 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 0, 0)), withinCell - new Vector3(1, 0, 0));
            float contribution101 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 0, 1)), withinCell - new Vector3(1, 0, 1));
            float contribution110 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 1, 0)), withinCell - new Vector3(1, 1, 0));
            float contribution111 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 1, 1)), withinCell - new Vector3(1, 1, 1));

            Vector3 blend = new Vector3(blendCurve(withinCell.X), blendCurve(withinCell.Y), blendCurve(withinCell.Z));

            // Interpolate along X
            float contribution00 = lerp(contribution000, contribution100, blend.X);
            float contribution01 = lerp(contribution001, contribution101, blend.X);
            float contribution10 = lerp(contribution010, contribution110, blend.X);
            float contribution11 = lerp(contribution011, contribution111, blend.X);

            // Interpolate along Y
            float contribution0 = lerp(contribution00, contribution10, blend.Y);
            float contribution1 = lerp(contribution01, contribution11, blend.Y);

            // Interpolate along Z
            return lerp(contribution0, contribution1, blend.Z);
        }