Example #1
0
        /// <summary>
        /// Add a child entity to this entity
        /// </summary>
        /// <param name="child">The entity</param>
        public void AddEntity(Entity child)
        {
            if (child.ParentContainer == null)
            {
                child.Init();
            }
            else
            {
                child.ParentContainer.RemoveChild(child);
            }

            if (this is EntityGameView)
            {
                var view = this as EntityGameView;
                child.SetParentView(view);
                child.SetParent(view);
            }
            else if (this is Entity)
            {
                var parent = this as Entity;
                child.SetParentView(parent.GameView);
                child.SetParent(parent);
            }

            AddChild(child);
        }
Example #2
0
        private void OnMovementModeChanged()
        {
            switch (MovementMode)
            {
            case PlayerMovementMode.FirstPerson:
                _playerEntity.IsActive = true;

                _cameraEntity.SetParent(_playerEntity);
                _cameraEntity.EulerAngles = Vector3.Zero;
                _cameraTargetPosition     = new Vector3(0, 0.6f, 0);
                break;

            case PlayerMovementMode.ThirdPerson:
                _playerEntity.IsActive = true;
                _cameraEntity.SetParent(_playerEntity);
                _cameraEntity.EulerAngles = Vector3.Zero;
                _cameraTargetPosition     = new Vector3(0, 1, 3);

                break;

            case PlayerMovementMode.GodMode:
                _cameraEntity.SetParent(null);
                _playerEntity.IsActive = false;
                _cameraEntity.Position = _playerEntity.GlobalPosition + new Vector3(0, 1, 0);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Example #3
0
    void AddNewEntity()
    {
        Vector3 pos;
        UInt16  entKey = GameManager.instance.GetEntityKeyRandomly();
        Entity  ent    = PoolingManager.InstantiateByPooling(entKey);

        if (ent != null)
        {
            ent.SetParent(this);
            ent.transform.localScale = Vector3.one;

            //int cnt = owner.entityList.Count + 1;
            if (squareData.reversal == true)
            {
                pos = new Vector3(0, -GameDatabase.instance.tileHeight, 0);
            }
            else
            {
                pos = new Vector3(0, GameDatabase.instance.tileHeight, 0);
            }

            ent.transform.localPosition = pos;
            ent.gameObject.SetActive(false);
            entityList.Add(ent);
        }
    }
Example #4
0
        private async Task SellTicketAndSetEntityToNextNode(Entity customerEntity)
        {
            IsProcessing = true; // TODO properly synchronize this to prevent threading issues
            var customer = customerEntity.GetBehavior <CustomerBehavior>();

            if (customer == null)
            {
                // not a customer -> ignore
                customerEntity.SetParent(NextNode.Entity, Reasons.NotAllowed);
                ResetIsProcessingAndCheckForNextCustomer();
                return;
            }

            if (!customer.Inventory.TryTakeItem(Items.Money, TicketPrice))
            {
                // not enough money -> set forward
                customer.Entity.SetParent(NextNode.Entity, Reasons.DoesNotHaveRequiredItem);
                ResetIsProcessingAndCheckForNextCustomer();
                return;
            }

            // enough money taken -> wait processing time, give ticket and set forward
            if (MaximumProcessingSeconds > 0)
            {
                var waitTime = TimeSpan.FromSeconds(new Random().Next(MinimumProcessingSeconds, MaximumProcessingSeconds));
                await Timing.Delay(waitTime);
            }
            customer.Inventory.AddItem(Items.SkiTicket, 1);
            customer.Entity.IsEnabled = true;
            customer.Entity.SetParent(NextNode.Entity, Reasons.Processing.Finished, SetParentFlags.SuppressChildEnter);
            ResetIsProcessingAndCheckForNextCustomer();
        }
Example #5
0
        public void DropEquipped()
        {
            Entity drop = Equipped;

            drop.SetParent(null);
            drop.Position             = drop.Position + new Vector2(0.5f, 0);
            drop.transform.localScale = Vector3.one;
        }
Example #6
0
        public Wall(Scene scene, IList<Vector2> vertices)
            : base(scene, vertices)
        {
            SetBodyType(BodyType.Static);
            Entity entity = new Entity(scene);
            entity.AddModel(ModelFactory.CreatePolygon(vertices, new Vector3(0, 0, 1)));
            entity.SetParent(this);

            SetCollisionCategory(Category.All);
        }
Example #7
0
    public void ReplaceEntity()
    {
        if (entityList != null && entityList.Count > 0)
        {
            entity = entityList[entityList.Count - 1];
//			entity.gameObject.SetActive(true);
            entityList.Remove(entity);
            entity.SetParent(this);
        }
    }
Example #8
0
        /// <summary>
        /// Add an entity that has the specified component in it
        /// </summary>
        /// <typeparam name="TComponent">The component</typeparam>
        /// <returns></returns>
        public TComponent Add <TComponent>() where  TComponent : IComponent, new()
        {
            Entity entity = new Entity();

            entity.Name = typeof(TComponent).Name;

            TComponent com = entity.AddComponent <TComponent>();

            entity.SetParent(this);
            return(com);
        }
Example #9
0
 public void AddChild(string key, Entity child)
 {
     if (!childEntities.ContainsKey(key))
     {
         childEntities[key] = new List <Entity>();
         memory[key]        = childEntities[key];
     }
     childEntities[key].Add(child);
     child.SetParent(this);
     child.onEntityDied += RemoveChild;
 }
Example #10
0
        public override void Active()
        {
            base.Active();
            //TODO 更新コンテナに自分を入れる

            overseeEntity.SetParent(entity);

            eagleDirection = (C_Switch3)entity.GetNormalComponent("C_Switch3");

            moveAreaLeft  = entity.transform.Position.X;
            moveAreaRight = moveAreaLeft + 500;
        }
Example #11
0
 public void SetAttachedEntity(Entity entity = null)
 {
     AttachedEntity = entity;
     if (AttachedEntity == null)
     {
         DestroyIcon();
     }
     else
     {
         AttachedEntity.SetParent(PlayerEntity.Player);
         AttachedEntity.Hide();
         CreateIcon();
     }
 }
Example #12
0
        public Bullet(Scene scene, Vector2 position, Vector2 velocity)
            : base(scene, PolygonFactory.CreateNGon(3, 0.1f, new Vector2()), new Transform2(position))
        {
            Entity = new Entity(Scene);
            SetVelocity(Transform2.CreateVelocity(velocity));
            Entity.SetParent(this);

            Model model = ModelFactory.CreatePolygon(Vertices, new Vector3(0, 0, 1));
            //Model model = ModelFactory.CreateArrow(new Vector3(0f, 0f, 1f), velocity.Normalized() * 0.1f, 0.1f, 0.3f, 0.15f);
            model.SetColor(new Vector3(1, 1, 0));
            Entity.AddModel(model);

            OnCollision += Bullet_OnCollision;

            SetCollisionCategory(Category.Cat1);
            SetCollidesWith(~Category.Cat1);
        }
Example #13
0
        public void AddToSlot(Entity entity)
        {
            if (Equipped != null)
            {
                DropEquipped();
            }

            if (entity != null)
            {
                entity.SetParent(Owner);
                entity.transform.SetParent(transform);

                entity.transform.localPosition = Vector3.zero;
                entity.transform.localScale    = Vector3.one;
                entity.transform.localRotation = Quaternion.identity;

                Equipped = entity;
            }
        }
Example #14
0
        public bool TryLoad(Entity entityToLoad)
        {
            if (FreeSlots == 0)
            {
                return(false);
            }

            if (!HasDriver && !EntityCanBeDriver(entityToLoad) && FreeSlots == 1)
            {
                return(false); // cannot load non-driver into last slot
            }

            if (entityToLoad.HasBehavior <MovableBehavior>())
            {
                entityToLoad.GetBehavior <MovableBehavior>().SetTarget(null);
            }
            entityToLoad.SetParent(Entity, TryLoadReason);
            _passengers.Add(entityToLoad);
            return(true);
        }
Example #15
0
        private void OnUpdate(EngineUpdateEventArgs args)
        {
            var thisPosition   = Entity.GetBehavior <TransformBehavior>().Position;
            var targetPosition = Target?.GetBehavior <TransformBehavior>()?.Position ?? Vector3.Zero;

            if (Vector3.Distance(thisPosition, targetPosition) <= float.Epsilon)
            {
                lock (_lock)
                {
                    if (_hasTargetReached)
                    {
                        return;
                    }

                    _hasTargetReached = true;
                    var parentEnterResult = Entity.SetParent(Target, Reasons.TargetReached);
                    _targetReached.OnNext(new TargetReachedEngineEventArgs(Engine.Engine.Current, Target, parentEnterResult));
                }
            }
            else
            {
                if (_hasTargetReached)
                {
                    _hasTargetReached = false;
                    var location =
                        _lastTarget?.GetImplementation <IGraphNode>()?
                        .AdjacentEdges.FirstOrDefault(
                            _ =>
                            (Equals(_.GetImplementation <IGraphEdge>().Start.Entity, _lastTarget) && Equals(_.GetImplementation <IGraphEdge>().End.Entity, Target)) ||
                            (Equals(_.GetImplementation <IGraphEdge>().End.Entity, _lastTarget) && Equals(_.GetImplementation <IGraphEdge>().Start.Entity, Target)));
                    Entity.SetParent(location, Reasons.MovingStarted);
                }
                var movementVector    = Vector3.Normalize(targetPosition - thisPosition);
                var movementFactor    = Speed * (float)args.DeltaTime.TotalSeconds;
                var maxMovementFactor = Vector3.Distance(thisPosition, targetPosition);
                var newPosition       = thisPosition + Math.Min(movementFactor, maxMovementFactor) * movementVector;
                Entity.GetBehavior <TransformBehavior>().Position = newPosition;
            }
        }
Example #16
0
        protected override void OnEnable()
        {
            screenContainer.renderer.isVisible = true;
            screenContainer.material.SetFloat("alpha", 1f);
            CoroutineExecutor.Add(Routine(), true);

            IEnumerator Routine()
            {
                var backBlack = new Entity().CreateComponent <Renderer>();

                backBlack.SetParent(screenContainer.renderer);
                backBlack.Position = new Vector3(0f, 0f, -2f);
                backBlack.size     = screenContainer.renderer.size;
                backBlack.onRender = (_, output) => Graphics.Clear(output, Color4.Black);

                GUIElement[] labelContainers = new GUIElement[data.captions.Length];
                GUIElement[] labels          = new GUIElement[data.captions.Length];

                for (int i = 0; i < data.captions.Length; i++)
                {
                    labelContainers[i] = GUIElement.CreateContainer(screenContainer.renderer, new Vector3(0f, (data.captions.Length - 1 - i * 2 + (i == 0 ? 0.2f : 0f)) * data.fontSize * data.interval, -3f), new Vector2(19.2f, 2f * data.fontSize), "Game/Alpha");
                    labels[i]          = GUIElement.CreateEmpty(labelContainers[i].renderer, new Vector3(0f, 0f, 0f), new Vector2(19.2f, 2f * data.fontSize));

                    {
                        var textBox = labels[i].Entity.CreateComponent <TextBox>();
                        textBox.InitFromRenderer();

                        textBox.CharHeight = i switch
                        {
                            0 => 1f,
                            _ => 0.8f,
                        } *data.fontSize;

                        textBox.Text  = new TextColored(data.captions[i], new SColor(1f, 1f, 1f));
                        textBox.Align = ODEngine.Core.Text.TextAlign.Center;
                    }

                    labelContainers[i].material.SetFloat("alpha", 0f);
                }

                foreach (var i in CoroutineExecutor.ForTime(data.startDelay)) // Start delay
                {
                    if (!isEnable)
                    {
                        Finish2();
                        yield break;
                    }

                    yield return(null);
                }

                if (data.isSimultaneous) // Labels fade in
                {
                    foreach (var i in CoroutineExecutor.ForTime(data.fadeInTime))
                    {
                        if (!isEnable)
                        {
                            Finish2();
                            yield break;
                        }

                        for (int j = 0; j < data.captions.Length; j++)
                        {
                            labelContainers[j].material.SetFloat("alpha", i * i);
                            yield return(null);
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < data.captions.Length; i++)
                    {
                        foreach (var j in CoroutineExecutor.ForTime(data.fadeInTime))
                        {
                            if (!isEnable)
                            {
                                Finish2();
                                yield break;
                            }

                            labelContainers[i].material.SetFloat("alpha", j * j);
                            yield return(null);
                        }
                    }
                }

                foreach (var _ in CoroutineExecutor.ForTime(data.showTime)) // Show
                {
                    if (!isEnable)
                    {
                        Finish2();
                        yield break;
                    }

                    yield return(null);
                }

                foreach (var i in CoroutineExecutor.ForTime(data.captionsFadeOutTime)) // Fade out
                {
                    if (!isEnable)
                    {
                        Finish2();
                        yield break;
                    }

                    for (int j = 0; j < data.captions.Length; j++)
                    {
                        labelContainers[j].material.SetFloat("alpha", (1f - i) * (1f - i));
                    }

                    yield return(null);
                }

                Finish2();

                void Finish2()
                {
                    for (int i = 0; i < data.captions.Length; i++)
                    {
                        labels[i].Entity.Destroy();
                        labelContainers[i].Entity.Destroy();
                    }
                }

                foreach (var i in CoroutineExecutor.ForTime(data.screenFadeOutTime))
                {
                    if (!isEnable)
                    {
                        Finish();
                        yield break;
                    }

                    screenContainer.material.SetFloat("alpha", (1f - i) * (1f - i));
                    yield return(null);
                }

                Finish();

                void Finish()
                {
                    backBlack.Entity.Destroy();
                    Disable();
                }
            }
        }
Example #17
0
        public void StepTest7()
        {
            Scene scene = new Scene();

            Actor actor = new Actor(scene, PolygonFactory.CreateRectangle(2, 2));
            actor.SetTransform(new Transform2(new Vector2(1, 1)));
            actor.SetVelocity(Transform2.CreateVelocity(new Vector2(0, 3)));
            Entity entity = new Entity(scene);
            entity.SetParent(actor);

            FloatPortal enter = new FloatPortal(scene);
            enter.SetTransform(new Transform2(new Vector2(1, 2), 1, (float)Math.PI / 2));
            //enter.SetVelocity(Transform2.CreateVelocity(new Vector2(1, 0)));

            FloatPortal exit = new FloatPortal(scene);
            exit.SetTransform(new Transform2(new Vector2(10, 10)));
            exit.SetVelocity(Transform2.CreateVelocity(new Vector2(10, 0)));

            enter.Linked = exit;
            exit.Linked = enter;

            PortalCommon.UpdateWorldTransform(scene);
            SimulationStep.Step(scene.GetAll().OfType<IPortalCommon>(), scene.GetAll().OfType<IPortal>(), 1, null);

            Assert.IsTrue(entity.GetTransform() == new Transform2());
            Assert.IsTrue(entity.GetVelocity() == Transform2.CreateVelocity());

            Assert.IsTrue(actor.GetTransform() == actor.WorldTransform);
            Assert.IsTrue(actor.GetVelocity() == actor.WorldVelocity);
        }
Example #18
0
        /// <summary>
        /// Creates a Scene from an EditorScene.  Scene is intended for gameplay use.
        /// </summary>
        public static Scene Export(EditorScene level, Controller controller)
        {
            Scene scene = new Scene();
            /*if (level.GetAll().OfType<EditorPlayer>().Count() > 0)
            {
                Camera2 camera = new Camera2(scene);
                camera.SetTransform(new Transform2(new Vector2(), 10, 0));
                scene.SetActiveCamera(camera);
                if (level.ActiveCamera != null)
                {
                    camera.Aspect = level.ActiveCamera.Aspect;
                }
            }
            else*/
            {
                if (level.ActiveCamera != null)
                {
                    ControllerCamera camera = level.ActiveCamera.ShallowClone();
                    camera.Scene = scene;
                    scene.SetActiveCamera(camera);
                }
            }

            #region create background
            Model background = Game.ModelFactory.CreatePlane();
            background.Texture = level.Renderer.GetTexture("grid.png");
            background.SetColor(new Vector3(1, 1, 0.5f));
            background.Transform.Position = new Vector3(0, 0, -5f);
            float size = 50;
            background.Transform.Scale = new Vector3(size, size, size);
            background.TransformUv.Size = size;
            Entity back = new Entity(scene, new Vector2(0f, 0f));
            back.Name = "Background";
            back.AddModel(background);
            back.IsPortalable = false;
            #endregion

            Dictionary<EditorObject, SceneNode> dictionary = new Dictionary<EditorObject, SceneNode>();
            AnimationDriver animation = new AnimationDriver();
            scene.SceneObjectList.Add(animation);

            List<EditorObject> editorObjects = level.GetAll().OfType<EditorObject>().ToList();
            foreach (EditorObject e in editorObjects)
            {
                if (e is EditorPortal)
                {
                    EditorPortal cast = (EditorPortal)e;

                    Entity entity = new Entity(scene);
                    entity.IsPortalable = false;
                    entity.AddModel(ModelFactory.CreatePortal());
                    entity.ModelList[0].Transform.Position += new Vector3(0, 0, -2);

                    if (cast.OnEdge)
                    {
                        FixturePortal portal = new FixturePortal(scene);
                        portal.Name = cast.Name;
                        dictionary.Add(cast, portal);

                        entity.SetParent(portal);
                    }
                    else
                    {
                        FloatPortal portal = new FloatPortal(scene);
                        portal.Name = cast.Name;
                        portal.SetTransform(cast.GetTransform());
                        dictionary.Add(cast, portal);

                        entity.SetParent(portal);

                        if (cast.AnimatedTransform != null)
                        {
                            animation.Add(portal, cast.AnimatedTransform);
                            portal.SetTransform(cast.AnimatedTransform.GetTransform(0));
                        }
                        else
                        {
                            portal.SetTransform(cast.GetTransform());
                        }
                    }
                }
                else if (e is EditorEntity)
                {
                    EditorEntity cast = (EditorEntity)e;
                    Entity clone = new Entity(scene);
                    clone.Name = cast.Name;
                    clone.AddModelRange(cast.Models);

                    dictionary.Add(cast, clone);

                    if (cast.AnimatedTransform != null)
                    {
                        animation.Add(clone, cast.AnimatedTransform);
                        clone.SetTransform(cast.AnimatedTransform.GetTransform(0));
                    }
                    else
                    {
                        clone.SetTransform(cast.GetTransform());
                    }
                }
                else if (e is IWall)
                {
                    EditorObject cast = e;

                    Transform2 t = cast.GetTransform();
                    Actor actor = new Actor(scene, ((IWall)e).Vertices, t);
                    actor.Name = cast.Name;
                    Transform2 tEntity = new Transform2();
                    Entity entity = new Entity(scene, tEntity);
                    entity.Name = cast.Name;
                    entity.SetParent(actor);
                    if (e is EditorWall)
                    {
                        EditorWall castWall = (EditorWall)e;
                        actor.SetBodyType(BodyType.Static);
                        //actor.Vertices = castWall.Vertices;
                        entity.AddModel(Game.ModelFactory.CreatePolygon(castWall.Vertices));
                        //entity.AddModel(Game.ModelFactory.CreateActorDebug(actor));
                        dictionary.Add(castWall, actor);
                    }
                    else if (e is EditorActor)
                    {
                        //actor.SetVelocity(new Transform2(new Vector2(0.2f, 0)));
                        EditorActor castActor = (EditorActor)e;
                        //actor.Vertices = castActor.Vertices;
                        entity.AddModel(castActor.GetActorModel(castActor));
                        //entity.AddModel(Game.ModelFactory.CreateActorDebug(actor));
                        dictionary.Add(castActor, actor);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    if (cast.AnimatedTransform != null)
                    {
                        animation.Add(actor, cast.AnimatedTransform);
                        actor.SetTransform(cast.AnimatedTransform.GetTransform(0));
                        actor.SetBodyType(BodyType.Kinematic);
                    }
                    else
                    {
                        actor.SetTransform(cast.GetTransform());
                    }
                }
                else if (e is EditorPlayer)
                {
                    EditorPlayer cast = (EditorPlayer)e;
                    Player player = new Player(controller);
                    Vector2[] polygon = PolygonFactory.CreateNGon(6, 0.5f, new Vector2());
                    Actor actor = new Actor(scene, polygon);
                    player.SetActor(actor);
                    actor.SetTransform(new Transform2(cast.GetWorldTransform().Position));

                    //player.Camera = (Camera2)scene.ActiveCamera;

                    Entity entity = new Entity(scene, new Transform2());
                    entity.Name = cast.Name;
                    entity.SetParent(actor);
                    entity.AddModel(Game.ModelFactory.CreatePolygon(polygon));

                    scene.SceneObjectList.Add(player);
                    dictionary.Add(cast, player.Actor);
                }
                else
                {
                    Debug.Assert(false);
                }
            }

            foreach (EditorObject e in editorObjects)
            {
                SceneNode parent = e.Parent == null ? null : dictionary[e.Parent];
                SceneNode clone = dictionary[e];
                clone.SetParent(parent);
                if (clone is IPortal)
                {
                    if (clone is FixturePortal)
                    {
                        FixturePortal cast = (FixturePortal)clone;

                        cast.SetPosition((IWall)parent, ((EditorPortal)e).PolygonTransform, e.GetTransform().Size, e.GetTransform().MirrorX);
                        Debug.Assert(((IWall)parent).Vertices.Count > 0);

                        IPortal portalEditor = (IPortal)e;
                        if (portalEditor.Linked != null)
                        {
                            cast.Linked = (IPortal)dictionary[(EditorPortal)portalEditor.Linked];
                        }
                    }
                    else if (clone is FloatPortal)
                    {
                        FloatPortal cast = (FloatPortal)clone;

                        IPortal portalEditor = (IPortal)e;
                        if (portalEditor.Linked != null)
                        {
                            cast.Linked = (IPortal)dictionary[(EditorPortal)portalEditor.Linked];
                        }
                    }
                }
            }

            PortalCommon.UpdateWorldTransform(scene);

            return scene;
        }
Example #19
0
        public Player(World world)
        {
            _inputSystem  = GameInstance.GetService <InputSystem>();
            _playerEntity = world.EntitySystem.CreateEntity(true);

            var mesh           = new Mesh(GameInstance.GraphicsDevice, Primitives.GenerateQuadForYBillboard());
            var diffuseTexture = GameInstance.Content.Load <Texture2D>(ResourceNames.Textures.DefaultGuy);
            var material       = new Material
            {
                DiffuseTexture  = diffuseTexture,
                UseTransparency = true,
                TexcoordScale   = diffuseTexture.GetTexcoordsFromPixelCoords(32, 32),
                IsUnlit         = true
            };

            _modelEntityComponent = _playerEntity.AddComponent(new ModelEntityComponent(_playerEntity, mesh, material, true));

            _cameraEntity = world.EntitySystem.CreateEntity();
            _cameraEntity.SetParent(_playerEntity);

            var cameraComponent = _cameraEntity.AddComponent(new CameraEntityComponent(_cameraEntity, new Skybox(GameInstance)
            {
                Scale   = 50,
                Texture = GameInstance.Content.Load <Texture2D>(ResourceNames.Textures.skybox_texture)
            }));

            cameraComponent.FarClipDistance = 50.0f;
            Camera = cameraComponent.Camera;

            Speed         = 2.0f;
            RotationSpeed = 2f;

            var forward = Animation.CreateDiscrete(0.65f, new[]
            {
                diffuseTexture.GetTexcoordsFromPixelCoords(0, 0),
                diffuseTexture.GetTexcoordsFromPixelCoords(32, 0),
                diffuseTexture.GetTexcoordsFromPixelCoords(0, 0),
                diffuseTexture.GetTexcoordsFromPixelCoords(64, 0),
            }, t => _modelEntityComponent.Material.TexcoordOffset = t, true);
            var left = Animation.CreateDiscrete(0.65f, new[]
            {
                diffuseTexture.GetTexcoordsFromPixelCoords(0, 32),
                diffuseTexture.GetTexcoordsFromPixelCoords(32, 32),
                diffuseTexture.GetTexcoordsFromPixelCoords(0, 32),
                diffuseTexture.GetTexcoordsFromPixelCoords(64, 32),
            }, t => _modelEntityComponent.Material.TexcoordOffset = t, true);
            var right = Animation.CreateDiscrete(0.65f, new[]
            {
                diffuseTexture.GetTexcoordsFromPixelCoords(0, 96),
                diffuseTexture.GetTexcoordsFromPixelCoords(32, 96),
                diffuseTexture.GetTexcoordsFromPixelCoords(0, 96),
                diffuseTexture.GetTexcoordsFromPixelCoords(64, 96),
            }, t => _modelEntityComponent.Material.TexcoordOffset = t, true);
            var backward = Animation.CreateDiscrete(0.65f, new[]
            {
                diffuseTexture.GetTexcoordsFromPixelCoords(0, 64),
                diffuseTexture.GetTexcoordsFromPixelCoords(32, 64),
                diffuseTexture.GetTexcoordsFromPixelCoords(0, 64),
                diffuseTexture.GetTexcoordsFromPixelCoords(64, 64),
            }, t => _modelEntityComponent.Material.TexcoordOffset = t, true);

            _playerEntity.AddComponent(new FigureMovementAnimationComponent(_playerEntity, forward, backward, left, right));

            _movementMode          = PlayerMovementMode.ThirdPerson;
            _cameraEntity.Position = _cameraTargetPosition;

            var colliderComponent = new CollisionEntityComponent(_playerEntity, new Vector3(0.35f, 0.6f, 0.35f),
                                                                 new Vector3(0.0f, 0.3f, 0.0f), "Player")
            {
                ResolvesPosition = true,
            };

            _playerEntity.AddComponent(colliderComponent);

            _playerEntity.Position = new Vector3(5, 0, 8);
        }
Example #20
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream, IEnumerable <string> modelDirs, out Image[] lightmaps)
        {
            BinaryReader reader = new BinaryReader(stream);

            if (reader.ReadFixedLengthString(Encoding.ASCII, 3) != "CBR")
            {
                throw new ProviderException("CBR file is corrupted/invalid!");
            }
            uint revision = reader.ReadUInt32();

            // Lightmaps
            bool lightmapped = reader.ReadByte() > (byte)Lightmapped.No;

            if (lightmapped)
            {
                lightmaps = new Image[4];
                for (int i = 0; i < 4; i++)
                {
                    lightmaps[i] = Image.FromStream(new MemoryStream(reader.ReadBytes(reader.ReadInt32())));
                }
            }
            else
            {
                lightmaps = null;
            }

            // Texture dictionary
            int texSize = reader.ReadInt32();

            string[] textures = new string[texSize];
            for (int i = 0; i < texSize; i++)
            {
                textures[i] = reader.ReadNullTerminatedString();
            }

            DataStructures.MapObjects.Map map = new DataStructures.MapObjects.Map();
            map.WorldSpawn = new World(map.IDGenerator.GetNextObjectID());

            // Solids
            List <MapObject> solids = new List <MapObject>();
            int solidCount          = reader.ReadInt32();

            for (int i = 0; i < solidCount; i++)
            {
                Solid s = new Solid(map.IDGenerator.GetNextObjectID());
                s.Colour = Colour.GetRandomBrushColour();
                int faceCount = reader.ReadInt32();
                for (int j = 0; j < faceCount; j++)
                {
                    Face f = new Face(map.IDGenerator.GetNextFaceID());
                    f.Colour           = s.Colour;
                    f.Texture.Name     = textures[reader.ReadInt32()];
                    f.Texture.UAxis    = reader.ReadCoordinate();
                    f.Texture.VAxis    = reader.ReadCoordinate();
                    f.Texture.XShift   = reader.ReadDecimal();
                    f.Texture.YShift   = reader.ReadDecimal();
                    f.Texture.XScale   = reader.ReadDecimal();
                    f.Texture.YScale   = reader.ReadDecimal();
                    f.Texture.Rotation = reader.ReadDecimal();
                    int vertexCount = reader.ReadInt32();
                    for (int k = 0; k < vertexCount; k++)
                    {
                        Vertex v = new Vertex(reader.ReadCoordinate(), f);
                        if (lightmapped)
                        {
                            v.LMU      = reader.ReadSingle();
                            v.LMV      = reader.ReadSingle();
                            v.TextureU = (decimal)reader.ReadSingle();
                            v.TextureV = (decimal)reader.ReadSingle();
                        }
                        f.Vertices.Add(v);
                    }
                    f.Plane  = new Plane(f.Vertices[0].Location, f.Vertices[1].Location, f.Vertices[2].Location);
                    f.Parent = s;
                    s.Faces.Add(f);
                    f.UpdateBoundingBox();
                }
                s.SetParent(map.WorldSpawn, false);
                s.UpdateBoundingBox(false);
                solids.Add(s);
            }

            // Entities
            List <MapObject> entities = new List <MapObject>(0);
            string           read;
            bool             isStillSolid = true;

            for (int i = 0; i < 2; i++)
            {
                while ((read = reader.ReadNullTerminatedString()) != "")
                {
                    List <Property> properties = new List <Property>();
                    byte            propertyType;
                    while ((propertyType = reader.ReadByte()) != 255)
                    {
                        properties.Add(new Property()
                        {
                            name = reader.ReadNullTerminatedString(),
                            type = (VariableType)propertyType
                        });
                    }

                    // Entries
                    int entitiesOfType = reader.ReadInt32();
                    entities.Capacity += entitiesOfType;
                    for (int j = 0; j < entitiesOfType; j++)
                    {
                        Entity e = new Entity(map.IDGenerator.GetNextObjectID());
                        e.Colour          = Colour.GetDefaultEntityColour();
                        e.ClassName       = read;
                        e.EntityData.Name = read;
                        if (isStillSolid)
                        {
                            int entitySolids = reader.ReadInt32();
                            for (int k = 0; k < entitySolids; k++)
                            {
                                solids[reader.ReadInt32()].SetParent(e);
                            }
                        }
                        e.SetParent(map.WorldSpawn);
                        foreach (Property property in properties)
                        {
                            string propertyVal;
                            switch (property.type)
                            {
                            case VariableType.Bool:
                                propertyVal = reader.ReadBoolean() ? "Yes" : "No";
                                break;

                            case VariableType.Color255:
                                propertyVal = DataStructures.MapObjects.Property.FromColor(reader.ReadRGBAColour());
                                break;

                            case VariableType.Float:
                                propertyVal = reader.ReadSingle().ToString();
                                break;

                            case VariableType.Integer:
                                propertyVal = reader.ReadInt32().ToString();
                                break;

                            case VariableType.String:
                                propertyVal = reader.ReadNullTerminatedString();
                                break;

                            case VariableType.Vector:
                                propertyVal = DataStructures.MapObjects.Property.FromCoordinate(reader.ReadCoordinate());
                                break;

                            case VariableType.Choices:
                                // TODO: Bullshit
                                throw new NotImplementedException();

                            default:
                                propertyVal = "";
                                break;
                            }
                            e.EntityData.SetPropertyValue(property.name, propertyVal);
                        }
                        e.UpdateBoundingBox();
                        entities.Add(e);
                    }
                }
                isStillSolid = false;
            }

            // CBRE ONLY

            // Visgroup dictionary
            Visgroup currentParentVisgroup = null;

            while (true)
            {
                byte     hierarchyControl;
                Visgroup newGroup = null;
                while ((hierarchyControl = reader.ReadByte()) == HIERARCHY_PROCCEED)
                {
                    newGroup        = new Visgroup();
                    newGroup.Colour = Colour.GetRandomBrushColour();
                    newGroup.ID     = reader.ReadInt32();
                    newGroup.Name   = reader.ReadNullTerminatedString();
                    if (currentParentVisgroup != null)
                    {
                        newGroup.Parent = currentParentVisgroup;
                        currentParentVisgroup.Children.Add(newGroup);
                    }
                    else
                    {
                        map.Visgroups.Add(newGroup);
                    }
                }
                if (hierarchyControl == HIERARCHY_DOWN)
                {
                    currentParentVisgroup = newGroup;
                }
                else if (currentParentVisgroup != null)
                {
                    currentParentVisgroup = currentParentVisgroup.Parent;
                }
                else
                {
                    break;
                }
            }

            // Solid visgroups
            foreach (Solid mo in solids)
            {
                ReadVisgroups(reader, mo);
            }

            // Entity visgroups
            foreach (Entity e in entities)
            {
                ReadVisgroups(reader, e);
            }

            // Groups
            int directWorldGroups = reader.ReadInt32();

            for (int i = 0; i < directWorldGroups; i++)
            {
                Group currentParentGroup = new Group(map.IDGenerator.GetNextObjectID());
                currentParentGroup.SetParent(map.WorldSpawn);
                while (true)
                {
                    byte hierarchyControl;
                    while ((hierarchyControl = reader.ReadByte()) > HIERARCHY_UP)
                    {
                        if (hierarchyControl == IDENTIFIER_ENTITY)
                        {
                            entities[reader.ReadInt32()].SetParent(currentParentGroup);
                        }
                        else
                        {
                            solids[reader.ReadInt32()].SetParent(currentParentGroup);
                        }
                    }
                    if (hierarchyControl == HIERARCHY_DOWN)
                    {
                        Group newGroup = new Group(map.IDGenerator.GetNextObjectID());
                        newGroup.SetParent(currentParentGroup);
                        currentParentGroup = newGroup;
                    }
                    else if (currentParentGroup.Parent != map.WorldSpawn)
                    {
                        currentParentGroup = (Group)currentParentGroup.Parent;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            stream.Close();
            return(map);
        }
Example #21
0
    protected override NodeStatus Act(Entity entity, Memory memory)
    {
        // Count children
        List <Entity> children   = memory[childrenKey] as List <Entity>;
        int           childCount = children != null ? children.Count : 0;

        // Set job availability tags
        string tag = JOB_TAG + jobTitle;

        if (childCount < capacity)
        {
            if (!entity.tags.Contains(tag))
            {
                entity.tags.Add(tag);
            }
            if (!entity.tags.Contains(HAS_JOB_TAG))
            {
                entity.tags.Add(HAS_JOB_TAG);
            }
        }
        else
        {
            if (entity.tags.Contains(tag))
            {
                entity.tags.Remove(tag);
            }
            if (entity.tags.Contains(HAS_JOB_TAG))
            {
                entity.tags.Remove(HAS_JOB_TAG);
            }
        }

        // Go thru applicants and process them
        List <Entity> applicants = entity.childEntities.ContainsKey(jobTitle + APPLICANTS_TAG) ? entity.childEntities[jobTitle + APPLICANTS_TAG] : null;

        if (applicants == null || applicants.Count <= 0)
        {
            return(NodeStatus.Success);
        }
        else
        {
            int i = 0;
            while (i < applicants.Count)
            {
                Entity applicant = applicants[i];
                if (childCount < capacity)
                {
                    entity.AddChild(childrenKey, applicant);
                    applicant.SetParent(entity);
                    applicant.memory[Leaf_AcceptJob.GetApplicantStateKey(entity)] = Leaf_AcceptJob.ACCEPTED;
                    applicant.TransformTo(data);
                    childCount++;
                }
                else
                {
                    applicant.memory[Leaf_AcceptJob.GetApplicantStateKey(entity)] = Leaf_AcceptJob.REJECTED;
                }
                i++;
            }
            applicants.Clear();
        }
        return(NodeStatus.Success);
    }
Example #22
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream, IEnumerable <string> modelDirs, out Image[] lightmaps)
        {
            lightmaps = null;
            var map = new DataStructures.MapObjects.Map();

            map.CordonBounds = new Box(Coordinate.One * -16384, Coordinate.One * 16384);
            BinaryReader br = new BinaryReader(stream);

            //header
            UInt16 mapVersion   = br.ReadUInt16();
            byte   mapFlags     = br.ReadByte();
            Int32  nameCount    = br.ReadInt32();
            Int32  nameOffset   = br.ReadInt32();
            Int32  objectCount  = br.ReadInt32();
            Int32  objectOffset = br.ReadInt32();

            //get names, needed to understand the objects
            List <string> names = new List <string>();

            br.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
            for (int i = 0; i < nameCount; i++)
            {
                string name = br.ReadNullTerminatedString();
                names.Add(name);
            }

            //now we can parse the object table
            List <string> materials = new List <string>();
            List <Tuple <int, string> > meshReferences = new List <Tuple <int, string> >();
            Dictionary <int, Group>     groups         = new Dictionary <int, Group>();
            Dictionary <int, int>       visgroups      = new Dictionary <int, int>();

            br.BaseStream.Seek(objectOffset, SeekOrigin.Begin);
            long objectStartPos = br.BaseStream.Position;

            for (int i = 0; i < objectCount; i++)
            {
                int    index = br.ReadInt32() - 1;
                int    size  = br.ReadInt32();
                string name  = null;
                if (index >= 0 && index < names.Count)
                {
                    name = names[index];
                }

                if (name == "group")
                {
                    byte  flags      = br.ReadByte();
                    Int32 groupIndex = br.ReadInt32();

                    Group newGroup = new Group(map.IDGenerator.GetNextObjectID());
                    newGroup.SetParent(map.WorldSpawn);

                    groups.Add(i, newGroup);
                }
                else if (name == "visgroup")
                {
                    byte   flags = br.ReadByte();
                    string groupName = names[br.ReadInt32() - 1];
                    byte   colorR = br.ReadByte(); byte colorG = br.ReadByte(); byte colorB = br.ReadByte();

                    Visgroup newGroup = new Visgroup()
                    {
                        Name = groupName, ID = visgroups.Count + 1
                    };
                    newGroup.Colour = System.Drawing.Color.FromArgb(colorR, colorG, colorB);
                    map.Visgroups.Add(newGroup);
                    visgroups.Add(i, newGroup.ID);
                }
                else if (name == "meshreference")
                {
                    byte flags = br.ReadByte();

                    Int32 groupNameInd  = br.ReadInt32() - 1;
                    Int32 objectNameInd = br.ReadInt32() - 1;

                    byte limbCount = br.ReadByte();

                    meshReferences.Add(new Tuple <int, string>(i, names[objectNameInd]));
                }
                else if (name == "material")
                {
                    byte   materialFlags      = br.ReadByte();
                    Int32  groupIndex         = br.ReadInt32();
                    string objectName         = names[br.ReadInt32() - 1];
                    Int32  extensionNameIndex = -1;
                    if ((materialFlags & 2) != 0)
                    {
                        extensionNameIndex = br.ReadInt32(); //TODO: what the heck is this
                    }
                    materials.Add(objectName);
                }
                else
                {
                    br.BaseStream.Seek(size, SeekOrigin.Current);
                }
            }
            br.BaseStream.Position = objectStartPos;
            for (int i = 0; i < objectCount; i++)
            {
                int    index = br.ReadInt32() - 1;
                int    size  = br.ReadInt32();
                string name  = null;
                if (index >= 0 && index < names.Count)
                {
                    name = names[index];
                }

                if (name == "mesh")
                {
                    Property newProperty;

                    long startPos = br.BaseStream.Position;

                    byte flags = br.ReadByte();

                    Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                    entity.ClassName       = "model";
                    entity.EntityData.Name = "model";
                    entity.Colour          = Colour.GetDefaultEntityColour();

                    Int32 keyCount = br.ReadInt32();
                    for (int j = 0; j < keyCount; j++)
                    {
                        Int32 keyNameInd  = br.ReadInt32() - 1;
                        Int32 keyValueInd = br.ReadInt32() - 1;
                        if (names[keyNameInd] != "classname")
                        {
                            newProperty       = new Property();
                            newProperty.Key   = names[keyNameInd];
                            newProperty.Value = names[keyValueInd];

                            if (newProperty.Key == "file")
                            {
                                newProperty.Value = System.IO.Path.GetFileNameWithoutExtension(newProperty.Value);
                            }

                            entity.EntityData.Properties.Add(newProperty);
                        }
                    }

                    Int32 groupIndex    = br.ReadInt32() - 1;
                    Int32 visgroupIndex = br.ReadInt32() - 1;
                    if (visgroups.ContainsKey(visgroupIndex))
                    {
                        entity.Visgroups.Add(visgroups[visgroupIndex]);
                    }

                    byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte();

                    Int32 meshRefIndex = br.ReadInt32() - 1;

                    float x = br.ReadSingle();
                    float z = br.ReadSingle();
                    float y = br.ReadSingle();
                    if (entity != null)
                    {
                        entity.Origin = new Coordinate((decimal)x, (decimal)y, (decimal)z);
                    }

                    if (entity.EntityData.GetPropertyValue("file") == null)
                    {
                        newProperty       = new Property();
                        newProperty.Key   = "file";
                        newProperty.Value = meshReferences.Find(q => q.Item1 == meshRefIndex).Item2;

                        entity.EntityData.Properties.Add(newProperty);
                    }

                    float pitch = br.ReadSingle();
                    float yaw   = br.ReadSingle();
                    float roll  = br.ReadSingle();
                    newProperty       = new Property();
                    newProperty.Key   = "angles";
                    newProperty.Value = pitch.ToString() + " " + yaw.ToString() + " " + roll.ToString();

                    entity.EntityData.Properties.Add(newProperty);

                    float xScale = 1.0f;
                    float yScale = 1.0f;
                    float zScale = 1.0f;

                    if ((flags & 1) == 0)
                    {
                        xScale = br.ReadSingle();
                        yScale = br.ReadSingle();
                        zScale = br.ReadSingle();
                    }

                    newProperty       = new Property();
                    newProperty.Key   = "scale";
                    newProperty.Value = xScale.ToString() + " " + yScale.ToString() + " " + zScale.ToString();

                    entity.EntityData.Properties.Add(newProperty);

                    br.BaseStream.Position += size - (br.BaseStream.Position - startPos);

                    entity.UpdateBoundingBox();

                    if (groups.ContainsKey(groupIndex))
                    {
                        entity.SetParent(groups[groupIndex]);
                    }
                    else
                    {
                        entity.SetParent(map.WorldSpawn);
                    }
                }
                else if (name == "entity")
                {
                    byte  flags = br.ReadByte();
                    float x     = br.ReadSingle();
                    float z     = br.ReadSingle();
                    float y     = br.ReadSingle();

                    Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                    entity.Colour = Colour.GetDefaultEntityColour();
                    entity.Origin = new Coordinate((decimal)x, (decimal)y, (decimal)z);

                    Int32 keyCount = br.ReadInt32();
                    for (int j = 0; j < keyCount; j++)
                    {
                        Int32 keyNameInd  = br.ReadInt32() - 1;
                        Int32 keyValueInd = br.ReadInt32() - 1;
                        if (names[keyNameInd] == "classname")
                        {
                            entity.ClassName       = names[keyValueInd];
                            entity.EntityData.Name = names[keyValueInd];
                        }
                        else
                        {
                            Property newProperty = new Property();
                            newProperty.Key   = names[keyNameInd];
                            newProperty.Value = names[keyValueInd];
                            entity.EntityData.Properties.Add(newProperty);
                        }
                    }

                    Int32 groupIndex    = br.ReadInt32() - 1;
                    Int32 visgroupIndex = br.ReadInt32() - 1;
                    if (visgroups.ContainsKey(visgroupIndex))
                    {
                        entity.Visgroups.Add(visgroups[visgroupIndex]);
                    }

                    entity.UpdateBoundingBox();
                    if (groups.ContainsKey(groupIndex))
                    {
                        entity.SetParent(groups[groupIndex]);
                    }
                    else
                    {
                        entity.SetParent(map.WorldSpawn);
                    }
                }
                else if (name == "brush")
                {
                    bool invisibleCollision = false;

                    byte  brushFlags = br.ReadByte(); //TODO: ???
                    Int32 keys       = br.ReadInt32();
                    for (int j = 0; j < keys; j++)
                    {
                        Int32  keyNameInd  = br.ReadInt32();
                        Int32  keyValueInd = br.ReadInt32();
                        string keyName     = names[keyNameInd - 1];
                        if (keyName.Equals("classname", StringComparison.OrdinalIgnoreCase))
                        {
                            string keyValue = names[keyValueInd - 1];
                            if (keyValue.Equals("field_hit", StringComparison.OrdinalIgnoreCase))
                            {
                                invisibleCollision = true;
                            }
                        }
                    }
                    Int32 groupIndex    = br.ReadInt32() - 1;
                    Int32 visgroupIndex = br.ReadInt32() - 1;

                    byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte();

                    List <Coordinate> vertices = new List <Coordinate>();
                    byte vertexCount           = br.ReadByte();
                    for (int j = 0; j < vertexCount; j++)
                    {
                        decimal x = (decimal)br.ReadSingle(); decimal z = (decimal)br.ReadSingle(); decimal y = (decimal)br.ReadSingle();
                        vertices.Add(new Coordinate(x, y, z));
                    }
                    List <Face> faces     = new List <Face>();
                    byte        faceCount = br.ReadByte();
                    for (int j = 0; j < faceCount; j++)
                    {
                        byte faceFlags = br.ReadByte();

                        //TODO: maybe we need these unused bits for something idk
                        decimal planeEq0 = (decimal)br.ReadSingle(); decimal planeEq1 = (decimal)br.ReadSingle(); decimal planeEq2 = (decimal)br.ReadSingle(); decimal planeEq3 = (decimal)br.ReadSingle();

                        decimal texPosX = (decimal)br.ReadSingle(); decimal texPosY = (decimal)br.ReadSingle();
                        decimal texScaleX = (decimal)br.ReadSingle(); decimal texScaleY = (decimal)br.ReadSingle();
                        float   texRotX = br.ReadSingle(); float texRotY = br.ReadSingle();

                        decimal uTexPlane0 = (decimal)br.ReadSingle(); decimal uTexPlane1 = (decimal)br.ReadSingle(); decimal uTexPlane2 = (decimal)br.ReadSingle(); decimal uTexPlane3 = (decimal)br.ReadSingle();
                        decimal vTexPlane0 = (decimal)br.ReadSingle(); decimal vTexPlane1 = (decimal)br.ReadSingle(); decimal vTexPlane2 = (decimal)br.ReadSingle(); decimal vTexPlane3 = (decimal)br.ReadSingle();

                        float luxelSize = br.ReadSingle();

                        Int32 smoothGroupInd = br.ReadInt32();
                        Int32 materialInd    = br.ReadInt32() - 1;

                        Int32 lightmapInd = -1;
                        if ((faceFlags & 16) != 0)
                        {
                            lightmapInd = br.ReadInt32();
                        }

                        byte        indexCount  = br.ReadByte();
                        List <byte> vertsInFace = new List <byte>();
                        for (int k = 0; k < indexCount; k++)
                        {
                            byte vertIndex = br.ReadByte();
                            vertsInFace.Add(vertIndex);

                            float texCoordX = br.ReadSingle(); float texCoordY = br.ReadSingle();

                            float lmCoordX = 0.0f; float lmCoordY = 0.0f;
                            if ((faceFlags & 16) != 0)
                            {
                                lmCoordX = br.ReadSingle(); lmCoordY = br.ReadSingle();
                            }
                        }

                        Coordinate norm = new Coordinate(planeEq0, planeEq2, planeEq1);

                        if (Math.Abs((float)norm.LengthSquared()) > 0.001f)
                        {
                            if (Math.Abs((double)norm.LengthSquared() - 1) > 0.001)
                            {
                                throw new Exception(norm.LengthSquared().ToString());
                            }

                            Face newFace = new Face(map.IDGenerator.GetNextFaceID());

                            foreach (byte vertInd in vertsInFace)
                            {
                                newFace.Vertices.Insert(0, new Vertex(vertices[vertInd], newFace));
                            }

                            newFace.Plane = new Plane(newFace.Vertices[0].Location, newFace.Vertices[1].Location, newFace.Vertices[2].Location);

                            newFace.UpdateBoundingBox();

                            Coordinate uNorm = new Coordinate(uTexPlane0, uTexPlane2, uTexPlane1).Normalise();
                            Coordinate vNorm = new Coordinate(vTexPlane0, vTexPlane2, vTexPlane1).Normalise();
                            if (Math.Abs((double)(uNorm.LengthSquared() - vNorm.LengthSquared())) > 0.001)
                            {
                                throw new Exception(uNorm.LengthSquared().ToString() + " " + vNorm.LengthSquared().ToString());
                            }

                            newFace.Texture.Name = (faceFlags & 4) != 0 ? "tooltextures/remove_face" :
                                                   invisibleCollision ? "tooltextures/invisible_collision" :
                                                   materials[materialInd];
                            newFace.AlignTextureToWorld();

                            newFace.Texture.UAxis = uNorm * (decimal)Math.Cos(-texRotX * Math.PI / 180.0) + vNorm * (decimal)Math.Sin(-texRotX * Math.PI / 180.0);
                            newFace.Texture.VAxis = vNorm * (decimal)Math.Cos(-texRotX * Math.PI / 180.0) - uNorm * (decimal)Math.Sin(-texRotX * Math.PI / 180.0);

                            //huh?????
                            if (Math.Abs(texScaleX) < 0.0001m)
                            {
                                if (Math.Abs(texScaleY) < 0.0001m)
                                {
                                    texScaleX = 1m;
                                    texScaleY = 1m;
                                }
                                else
                                {
                                    texScaleX = texScaleY;
                                }
                            }
                            else if (Math.Abs(texScaleY) < 0.0001m)
                            {
                                texScaleY = texScaleX;
                            }
                            newFace.Texture.XScale   = texScaleX / 2;
                            newFace.Texture.YScale   = texScaleY / 2;
                            newFace.Texture.XShift   = -texPosX * 2 / texScaleX;
                            newFace.Texture.YShift   = texPosY * 2 / texScaleY;
                            newFace.Texture.Rotation = (decimal)texRotX;

                            //seriously, what the F**K???????????
                            if ((texRotX - texRotY) > 120.0f)
                            {
                                newFace.Texture.XScale   *= -1m;
                                newFace.Texture.YScale   *= -1m;
                                newFace.Texture.Rotation -= 180m;
                                newFace.Texture.UAxis     = -newFace.Texture.UAxis;
                            }
                            else if ((texRotY - texRotX) > 120.0f)
                            {
                                newFace.Texture.XScale   *= -1m;
                                newFace.Texture.YScale   *= -1m;
                                newFace.Texture.Rotation -= 180m;
                                newFace.Texture.VAxis     = -newFace.Texture.VAxis;
                            }

                            newFace.Transform(new UnitScale(Coordinate.One, newFace.BoundingBox.Center), TransformFlags.None);

                            faces.Add(newFace);
                        }
                    }

                    Solid newSolid = new Solid(map.IDGenerator.GetNextObjectID());
                    foreach (Face face in faces)
                    {
                        face.Parent = newSolid;
                        newSolid.Faces.Add(face);
                    }
                    if (visgroups.ContainsKey(visgroupIndex))
                    {
                        newSolid.Visgroups.Add(visgroups[visgroupIndex]);
                    }
                    newSolid.Colour = Colour.GetRandomBrushColour();
                    newSolid.UpdateBoundingBox();

                    MapObject parent = map.WorldSpawn;
                    if (groups.ContainsKey(groupIndex))
                    {
                        parent = groups[groupIndex];
                    }

                    if (newSolid.IsValid())
                    {
                        newSolid.SetParent(parent);

                        newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                    }
                    else
                    {
                        var offset = newSolid.BoundingBox.Center;
                        // Not a valid solid, decompose into tetrahedrons/etc
                        foreach (var face in faces)
                        {
                            var polygon = new Polygon(face.Vertices.Select(x => x.Location));
                            if (!polygon.IsValid() || !polygon.IsConvex())
                            {
                                // tetrahedrons
                                foreach (var triangle in face.GetTrianglesReversed())
                                {
                                    var tf = new Face(map.IDGenerator.GetNextFaceID());
                                    tf.Plane = new Plane(triangle[0].Location, triangle[1].Location, triangle[2].Location);
                                    tf.Vertices.AddRange(triangle.Select(x => new Vertex(x.Location, tf)));
                                    tf.Texture = face.Texture.Clone();
                                    tf.UpdateBoundingBox();
                                    newSolid = SolidifyFace(map, tf, offset);
                                    newSolid.SetParent(parent);
                                    newSolid.UpdateBoundingBox();

                                    newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                                }
                            }
                            else
                            {
                                // cone/pyramid/whatever
                                newSolid = SolidifyFace(map, face, offset);
                                newSolid.SetParent(parent);
                                newSolid.UpdateBoundingBox();

                                newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                            }
                        }
                    }
                }
                else
                {
                    if (name == "terrain")
                    {
                        MapProvider.warnings = "This map contains displacements, which are currently not supported. The map will appear incomplete.";
                    }
                    br.BaseStream.Seek(size, SeekOrigin.Current);
                }
            }

            return(map);
        }
Example #23
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream)
        {
            var map = new DataStructures.MapObjects.Map();

            map.CordonBounds = new Box(Coordinate.One * -16384, Coordinate.One * 16384);
            BinaryReader br = new BinaryReader(stream);

            //header
            UInt16 mapVersion   = br.ReadUInt16();
            byte   mapFlags     = br.ReadByte();
            Int32  nameCount    = br.ReadInt32();
            Int32  nameOffset   = br.ReadInt32();
            Int32  objectCount  = br.ReadInt32();
            Int32  objectOffset = br.ReadInt32();

            //get names, needed to understand the objects
            List <string> names = new List <string>();

            br.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
            for (int i = 0; i < nameCount; i++)
            {
                string name = br.ReadNullTerminatedString();
                names.Add(name);
            }

            //now we can parse the object table
            List <string> materials = new List <string>();
            List <Tuple <int, string> > meshReferences = new List <Tuple <int, string> >();

            br.BaseStream.Seek(objectOffset, SeekOrigin.Begin);
            long objectStartPos = br.BaseStream.Position;

            for (int i = 0; i < objectCount; i++)
            {
                int index = br.ReadInt32() - 1;
                int size  = br.ReadInt32();
                if (index < 0 || index >= names.Count)
                {
                    throw new Exception(i.ToString() + " " + index.ToString());
                }
                string name = names[index];

                if (name == "meshreference")
                {
                    byte flags = br.ReadByte();

                    Int32 groupNameInd  = br.ReadInt32() - 1;
                    Int32 objectNameInd = br.ReadInt32() - 1;

                    byte limbCount = br.ReadByte();

                    meshReferences.Add(new Tuple <int, string>(i, names[objectNameInd]));
                }
                else if (name == "material")
                {
                    byte   materialFlags      = br.ReadByte();
                    Int32  groupIndex         = br.ReadInt32();
                    string objectName         = names[br.ReadInt32() - 1];
                    Int32  extensionNameIndex = -1;
                    if ((materialFlags & 2) != 0)
                    {
                        extensionNameIndex = br.ReadInt32(); //TODO: what the heck is this
                    }
                    materials.Add(objectName);
                }
                else
                {
                    br.BaseStream.Seek(size, SeekOrigin.Current);
                }
            }
            br.BaseStream.Position = objectStartPos;
            for (int i = 0; i < objectCount; i++)
            {
                int index = br.ReadInt32() - 1;
                int size  = br.ReadInt32();
                if (index < 0 || index >= names.Count)
                {
                    throw new Exception(i.ToString() + " " + index.ToString());
                }
                string name = names[index];
                if (name == "mesh")
                {
                    Property newProperty;

                    long startPos = br.BaseStream.Position;

                    byte flags = br.ReadByte();

                    Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                    entity.ClassName       = "model";
                    entity.EntityData.Name = "model";
                    entity.Colour          = Colour.GetDefaultEntityColour();

                    Int32 keyCount = br.ReadInt32();
                    for (int j = 0; j < keyCount; j++)
                    {
                        Int32 keyNameInd  = br.ReadInt32() - 1;
                        Int32 keyValueInd = br.ReadInt32() - 1;
                        if (names[keyNameInd] == "classname")
                        {
                            //entity.ClassName = names[keyValueInd];
                            //entity.EntityData.Name = names[keyValueInd];
                        }
                        else
                        {
                            newProperty       = new Property();
                            newProperty.Key   = names[keyNameInd];
                            newProperty.Value = names[keyValueInd];

                            if (newProperty.Key == "file")
                            {
                                newProperty.Value = System.IO.Path.GetFileNameWithoutExtension(newProperty.Value);
                            }

                            entity.EntityData.Properties.Add(newProperty);
                        }
                    }
                    Int32 group    = br.ReadInt32();
                    Int32 visgroup = br.ReadInt32();

                    byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte();

                    Int32 meshRefIndex = br.ReadInt32() - 1;

                    float x = br.ReadSingle();
                    float z = br.ReadSingle();
                    float y = br.ReadSingle();
                    if (entity != null)
                    {
                        entity.Origin = new Coordinate((decimal)x, (decimal)y, (decimal)z);
                    }

                    if (entity.EntityData.GetPropertyValue("file") == null)
                    {
                        newProperty       = new Property();
                        newProperty.Key   = "file";
                        newProperty.Value = meshReferences.Find(q => q.Item1 == meshRefIndex).Item2;

                        entity.EntityData.Properties.Add(newProperty);
                    }

                    float pitch = br.ReadSingle();
                    float yaw   = br.ReadSingle();
                    float roll  = br.ReadSingle();
                    newProperty       = new Property();
                    newProperty.Key   = "angles";
                    newProperty.Value = pitch.ToString(CultureInfo.InvariantCulture) + " " + yaw.ToString(CultureInfo.InvariantCulture) + " " + roll.ToString(CultureInfo.InvariantCulture);

                    entity.EntityData.Properties.Add(newProperty);

                    float xScale = 1.0f;
                    float yScale = 1.0f;
                    float zScale = 1.0f;

                    if ((flags & 1) == 0)
                    {
                        xScale = br.ReadSingle();
                        yScale = br.ReadSingle();
                        zScale = br.ReadSingle();
                    }

                    newProperty       = new Property();
                    newProperty.Key   = "scale";
                    newProperty.Value = xScale.ToString(CultureInfo.InvariantCulture) + " " + yScale.ToString(CultureInfo.InvariantCulture) + " " + zScale.ToString(CultureInfo.InvariantCulture);

                    entity.EntityData.Properties.Add(newProperty);

                    br.BaseStream.Position += size - (br.BaseStream.Position - startPos);

                    if (entity != null)
                    {
                        entity.UpdateBoundingBox();
                        entity.SetParent(map.WorldSpawn);
                    }
                }
                else if (name == "entity")
                {
                    byte  flags = br.ReadByte();
                    float x     = br.ReadSingle();
                    float z     = br.ReadSingle();
                    float y     = br.ReadSingle();

                    Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                    entity.Colour = Colour.GetDefaultEntityColour();
                    entity.Origin = new Coordinate((decimal)x, (decimal)y, (decimal)z);

                    Int32 keyCount = br.ReadInt32();
                    for (int j = 0; j < keyCount; j++)
                    {
                        Int32 keyNameInd  = br.ReadInt32() - 1;
                        Int32 keyValueInd = br.ReadInt32() - 1;
                        if (names[keyNameInd] == "classname")
                        {
                            entity.ClassName       = names[keyValueInd];
                            entity.EntityData.Name = names[keyValueInd];
                        }
                        else
                        {
                            Property newProperty = new Property();
                            newProperty.Key   = names[keyNameInd];
                            newProperty.Value = names[keyValueInd];
                            entity.EntityData.Properties.Add(newProperty);
                        }
                    }
                    Int32 group    = br.ReadInt32();
                    Int32 visgroup = br.ReadInt32();

                    entity.UpdateBoundingBox();
                    entity.SetParent(map.WorldSpawn);
                }
                else if (name == "brush")
                {
                    bool invisibleCollision = false;

                    byte  brushFlags = br.ReadByte(); //TODO: ???
                    Int32 keys       = br.ReadInt32();
                    for (int j = 0; j < keys; j++)
                    {
                        Int32  keyNameInd  = br.ReadInt32();
                        Int32  keyValueInd = br.ReadInt32();
                        string keyName     = names[keyNameInd - 1];
                        if (keyName.Equals("classname", StringComparison.InvariantCultureIgnoreCase))
                        {
                            string keyValue = names[keyValueInd - 1];
                            if (keyValue.Equals("field_hit", StringComparison.InvariantCultureIgnoreCase))
                            {
                                invisibleCollision = true;
                            }
                        }
                    }
                    Int32 groupIndex    = br.ReadInt32();
                    Int32 visgroupIndex = br.ReadInt32();

                    byte red = br.ReadByte(); byte green = br.ReadByte(); byte blue = br.ReadByte();

                    List <Coordinate> vertices = new List <Coordinate>();
                    byte vertexCount           = br.ReadByte();
                    for (int j = 0; j < vertexCount; j++)
                    {
                        decimal x = (decimal)br.ReadSingle(); decimal z = (decimal)br.ReadSingle(); decimal y = (decimal)br.ReadSingle();
                        vertices.Add(new Coordinate(x, y, z));
                    }
                    List <Face> faces     = new List <Face>();
                    byte        faceCount = br.ReadByte();
                    for (int j = 0; j < faceCount; j++)
                    {
                        byte faceFlags = br.ReadByte();

                        //TODO: maybe we need these unused bits for something idk
                        decimal planeEq0 = (decimal)br.ReadSingle(); decimal planeEq1 = (decimal)br.ReadSingle(); decimal planeEq2 = (decimal)br.ReadSingle(); decimal planeEq3 = (decimal)br.ReadSingle();

                        decimal texPosX = (decimal)br.ReadSingle(); decimal texPosY = (decimal)br.ReadSingle();
                        decimal texScaleX = (decimal)br.ReadSingle(); decimal texScaleY = (decimal)br.ReadSingle();
                        float   texRotX = br.ReadSingle(); float texRotY = br.ReadSingle();

                        decimal uTexPlane0 = (decimal)br.ReadSingle(); decimal uTexPlane1 = (decimal)br.ReadSingle(); decimal uTexPlane2 = (decimal)br.ReadSingle(); decimal uTexPlane3 = (decimal)br.ReadSingle();
                        decimal vTexPlane0 = (decimal)br.ReadSingle(); decimal vTexPlane1 = (decimal)br.ReadSingle(); decimal vTexPlane2 = (decimal)br.ReadSingle(); decimal vTexPlane3 = (decimal)br.ReadSingle();

                        float luxelSize = br.ReadSingle();

                        Int32 smoothGroupInd = br.ReadInt32();
                        Int32 materialInd    = br.ReadInt32() - 1;

                        Int32 lightmapInd = -1;
                        if ((faceFlags & 16) != 0)
                        {
                            lightmapInd = br.ReadInt32();
                        }

                        byte        indexCount  = br.ReadByte();
                        List <byte> vertsInFace = new List <byte>();
                        for (int k = 0; k < indexCount; k++)
                        {
                            byte vertIndex = br.ReadByte();
                            vertsInFace.Add(vertIndex);

                            float texCoordX = br.ReadSingle(); float texCoordY = br.ReadSingle();

                            float lmCoordX = 0.0f; float lmCoordY = 0.0f;
                            if ((faceFlags & 16) != 0)
                            {
                                lmCoordX = br.ReadSingle(); lmCoordY = br.ReadSingle();
                            }
                        }

                        Coordinate norm = new Coordinate(planeEq0, planeEq2, planeEq1);

                        if (Math.Abs((float)norm.LengthSquared()) > 0.001f)
                        {
                            if (Math.Abs((double)norm.LengthSquared() - 1) > 0.001)
                            {
                                throw new Exception(norm.LengthSquared().ToString());
                            }

                            Face newFace = new Face(map.IDGenerator.GetNextFaceID());

                            foreach (byte vertInd in vertsInFace)
                            {
                                newFace.Vertices.Insert(0, new Vertex(vertices[vertInd], newFace));
                            }

                            newFace.Plane = new Plane(newFace.Vertices[0].Location, newFace.Vertices[1].Location, newFace.Vertices[2].Location);

                            newFace.UpdateBoundingBox();

                            /*if ((faceFlags & 4) == 0)
                             * {
                             *  Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                             *  entity.Colour = Color.Lime;
                             *  entity.Origin = newFace.BoundingBox.Center;
                             *  entity.UpdateBoundingBox();
                             *  entity.SetParent(map.WorldSpawn);
                             *
                             *  Property newProperty = new Property();
                             *  newProperty.Key = "normal";
                             *  newProperty.Value = newFace.Plane.Normal.ToString();
                             *  entity.EntityData.Properties.Add(newProperty);
                             *
                             *  var direction = newFace.Plane.GetClosestAxisToNormal();
                             *  var tempV = direction == Coordinate.UnitZ ? -Coordinate.UnitY : -Coordinate.UnitZ;
                             *  var uAxis = newFace.Plane.Normal.Cross(tempV).Normalise();
                             *  var vAxis = uAxis.Cross(newFace.Plane.Normal).Normalise();
                             *
                             *  newProperty = new Property();
                             *  newProperty.Key = "uaxis";
                             *  newProperty.Value = uAxis.ToString();
                             *  entity.EntityData.Properties.Add(newProperty);
                             *
                             *  newProperty = new Property();
                             *  newProperty.Key = "vaxis";
                             *  newProperty.Value = vAxis.ToString();
                             *  entity.EntityData.Properties.Add(newProperty);
                             * }*/

                            Coordinate uNorm = new Coordinate(uTexPlane0, uTexPlane2, uTexPlane1).Normalise();
                            Coordinate vNorm = new Coordinate(vTexPlane0, vTexPlane2, vTexPlane1).Normalise();
                            if (Math.Abs((double)(uNorm.LengthSquared() - vNorm.LengthSquared())) > 0.001)
                            {
                                throw new Exception(uNorm.LengthSquared().ToString() + " " + vNorm.LengthSquared().ToString());
                            }

                            newFace.Texture.Name = (faceFlags & 4) != 0 ? "tooltextures/remove_face" :
                                                   invisibleCollision  ? "tooltextures/invisible_collision" :
                                                   materials[materialInd];
                            newFace.AlignTextureToWorld();
                            //TODO: add warning?
                            //if (texRotY != texRotX) throw new Exception((texRotX - texRotY).ToString());

                            newFace.Texture.UAxis    = uNorm * (decimal)Math.Cos(-texRotY * Math.PI / 180.0) + vNorm * (decimal)Math.Sin(-texRotY * Math.PI / 180.0);
                            newFace.Texture.VAxis    = vNorm * (decimal)Math.Cos(-texRotY * Math.PI / 180.0) - uNorm * (decimal)Math.Sin(-texRotY * Math.PI / 180.0);
                            newFace.Texture.XScale   = texScaleX / 2;
                            newFace.Texture.YScale   = texScaleY / 2;
                            newFace.Texture.XShift   = -texPosX * 2 / texScaleX;
                            newFace.Texture.YShift   = texPosY * 2 / texScaleY;
                            newFace.Texture.Rotation = (decimal)texRotY;

                            newFace.Transform(new UnitScale(Coordinate.One, newFace.BoundingBox.Center), TransformFlags.None);

                            faces.Add(newFace);
                        }
                    }

                    Solid newSolid = new Solid(map.IDGenerator.GetNextObjectID());
                    foreach (Face face in faces)
                    {
                        face.Parent = newSolid;
                        newSolid.Faces.Add(face);
                    }
                    newSolid.Colour = Colour.GetRandomBrushColour();
                    newSolid.UpdateBoundingBox();

                    if (newSolid.IsValid())
                    {
                        newSolid.SetParent(map.WorldSpawn);

                        newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                    }
                    else
                    {
                        var offset = newSolid.BoundingBox.Center;
                        // Not a valid solid, decompose into tetrahedrons/etc
                        foreach (var face in faces)
                        {
                            var polygon = new Polygon(face.Vertices.Select(x => x.Location));
                            if (!polygon.IsValid() || !polygon.IsConvex())
                            {
                                // tetrahedrons
                                foreach (var triangle in face.GetTrianglesReversed())
                                {
                                    var tf = new Face(map.IDGenerator.GetNextFaceID());
                                    tf.Plane = new Plane(triangle[0].Location, triangle[1].Location, triangle[2].Location);
                                    tf.Vertices.AddRange(triangle.Select(x => new Vertex(x.Location, tf)));
                                    tf.Texture = face.Texture.Clone();
                                    tf.UpdateBoundingBox();
                                    newSolid = SolidifyFace(map, tf, offset);
                                    newSolid.SetParent(map.WorldSpawn);
                                    newSolid.UpdateBoundingBox();

                                    newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                                }
                            }
                            else
                            {
                                // cone/pyramid/whatever
                                newSolid = SolidifyFace(map, face, offset);
                                newSolid.SetParent(map.WorldSpawn);
                                newSolid.UpdateBoundingBox();

                                newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                            }
                        }
                    }
                }
                else
                {
                    br.BaseStream.Seek(size, SeekOrigin.Current);
                }
            }

            return(map);
        }
Example #24
0
        protected override DataStructures.MapObjects.Map GetFromStream(Stream stream, IEnumerable <string> modelDirs, out Image[] lightmaps)
        {
            lightmaps = null;
            var map = new DataStructures.MapObjects.Map();

            map.CordonBounds = new Box(Coordinate.One * -16384, Coordinate.One * 16384);
            BinaryReader br = new BinaryReader(stream);

            List <ModelReference> models = null;

            //header
            bool hasLightmap = Math.Abs(br.ReadSingle()) > 0.01f;

            if (hasLightmap)
            {
                UInt32 lightmapSize = br.ReadUInt32();
                stream.Position += lightmapSize;
            }
            int entityCount = (int)br.ReadSingle() - 2;

            for (int i = 0; i < entityCount; i++)
            {
                int         meshCount         = (int)br.ReadSingle();
                List <long> memblockLocations = new List <long>();
                for (int j = 0; j < meshCount; j++)
                {
                    stream.Position += 4;
                    memblockLocations.Add(stream.Position);
                    SkipMemblock(br);
                }

                bool isBrush = Math.Abs(br.ReadSingle()) > 0.01f;
                if (isBrush)
                {
                    Dictionary <int, List <Face> > faces = new Dictionary <int, List <Face> >();
                    long returnPosition = stream.Position;
                    for (int j = 0; j < meshCount; j++)
                    {
                        stream.Position = memblockLocations[j];
                        faces.Add(j, new List <Face>());
                        ReadMemblockMesh(br, map, faces[j]);
                    }
                    stream.Position = returnPosition;
                    SkipMemblock(br);
                    for (int j = 0; j < 2; j++)
                    {
                        stream.Position += 4;
                    }

                    float xTranslate = br.ReadSingle();
                    float zTranslate = br.ReadSingle();
                    float yTranslate = br.ReadSingle();

                    float xScale = br.ReadSingle();
                    float zScale = br.ReadSingle();
                    float yScale = br.ReadSingle();

                    for (int j = 8; j < 25; j++)
                    {
                        stream.Position += 4;
                    }
                    List <SubmeshTextureInfo> textures = new List <SubmeshTextureInfo>();
                    for (int j = 0; j < meshCount; j++)
                    {
                        SubmeshTextureInfo submeshTextureInfo = new SubmeshTextureInfo();

                        submeshTextureInfo.TextureName = System.IO.Path.GetFileNameWithoutExtension(br.ReadLine());
                        float flags        = br.ReadSingle();
                        bool  faceIsHidden = Math.Abs(flags - 1) < 0.01f;
                        bool  faceIsLit    = Math.Abs(flags - 800) < 0.01f;
                        if (faceIsLit)
                        {
                            br.ReadSingle();
                        }
                        for (int k = 0; k < 4; k++)
                        {
                            stream.Position += 4;
                        }

                        submeshTextureInfo.ScaleU   = br.ReadSingle();
                        submeshTextureInfo.ScaleV   = br.ReadSingle();
                        submeshTextureInfo.ShiftU   = br.ReadSingle();
                        submeshTextureInfo.ShiftV   = br.ReadSingle();
                        submeshTextureInfo.Rotation = br.ReadSingle();

                        if (faceIsHidden)
                        {
                            submeshTextureInfo.TextureName = "tooltextures/remove_face";
                        }
                        textures.Add(submeshTextureInfo);
                    }

                    if (faces.Any())
                    {
                        Solid newSolid = new Solid(map.IDGenerator.GetNextObjectID());
                        foreach (int key in faces.Keys)
                        {
                            foreach (Face face in faces[key])
                            {
                                face.Parent = newSolid;
                                newSolid.Faces.Add(face);
                            }
                        }
                        newSolid.Colour = Colour.GetRandomBrushColour();
                        newSolid.UpdateBoundingBox();

                        MapObject parent = map.WorldSpawn;

                        newSolid.SetParent(parent);

                        newSolid.Transform(new UnitScale(Coordinate.One, newSolid.BoundingBox.Center), TransformFlags.None);
                        newSolid.Transform(new UnitScale(new Coordinate(
                                                             (decimal)xScale / newSolid.BoundingBox.Width,
                                                             (decimal)yScale / newSolid.BoundingBox.Length,
                                                             (decimal)zScale / newSolid.BoundingBox.Height), Coordinate.Zero), TransformFlags.None);
                        newSolid.UpdateBoundingBox();
                        newSolid.Transform(new UnitTranslate(new Coordinate(
                                                                 (decimal)xTranslate,
                                                                 (decimal)yTranslate,
                                                                 (decimal)zTranslate)), TransformFlags.None);
                        newSolid.UpdateBoundingBox();

                        foreach (int key in faces.Keys)
                        {
                            foreach (Face face in faces[key])
                            {
                                face.Texture.Name = textures[key].TextureName;
                                face.AlignTextureToWorld();
                                face.Texture.XScale = (decimal)textures[key].ScaleU * 0.25m;
                                face.Texture.YScale = (decimal)textures[key].ScaleV * 0.25m;
                                face.Texture.XShift = (decimal)textures[key].ShiftU;
                                face.Texture.YShift = (decimal)textures[key].ShiftV;
                                face.SetTextureRotation((decimal)textures[key].Rotation);
                            }
                        }
                    }
                }
                else
                {
                    int entitySubType = (int)br.ReadSingle();

                    for (int j = 1; j < 2; j++)
                    {
                        stream.Position += 4;
                    }
                    float xTranslate = br.ReadSingle();
                    float zTranslate = br.ReadSingle();
                    float yTranslate = br.ReadSingle();
                    float xScale     = br.ReadSingle();
                    float zScale     = br.ReadSingle();
                    float yScale     = br.ReadSingle();
                    if (Math.Abs(entitySubType - 3.0f) < 0.01f)
                    {
                        for (int j = 8; j < 35; j++)
                        {
                            stream.Position += 4;
                        }
                        string entityName    = br.ReadLine();
                        string entityIcon    = br.ReadLine();
                        int    propertyCount = (int)br.ReadSingle() + 1;
                        Dictionary <string, string> properties = new Dictionary <string, string>();
                        for (int j = 0; j < propertyCount; j++)
                        {
                            string propertyName  = br.ReadLine().ToLowerInvariant();
                            string propertyValue = br.ReadLine();
                            properties.Add(propertyName, propertyValue);
                        }

                        Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                        entity.Colour = Colour.GetDefaultEntityColour();
                        Property newProperty = null;
                        switch (entityName.ToLowerInvariant())
                        {
                        case "pointlight":
                            entity.ClassName       = "light";
                            entity.EntityData.Name = "light";

                            newProperty       = new Property();
                            newProperty.Key   = "range";
                            newProperty.Value = properties["range"];
                            entity.EntityData.Properties.Add(newProperty);

                            newProperty       = new Property();
                            newProperty.Key   = "color";
                            newProperty.Value = properties["color"].Replace(',', ' ').Trim();
                            entity.EntityData.Properties.Add(newProperty);
                            break;

                        case "spotlight":
                            entity.ClassName       = "spotlight";
                            entity.EntityData.Name = "spotlight";

                            newProperty       = new Property();
                            newProperty.Key   = "range";
                            newProperty.Value = properties["range"];
                            entity.EntityData.Properties.Add(newProperty);

                            newProperty       = new Property();
                            newProperty.Key   = "color";
                            newProperty.Value = properties["color"].Replace(',', ' ').Trim();
                            entity.EntityData.Properties.Add(newProperty);

                            newProperty       = new Property();
                            newProperty.Key   = "innerconeangle";
                            newProperty.Value = "45";
                            if (decimal.TryParse(properties["innerang"], out decimal innerAngle))
                            {
                                newProperty.Value = (innerAngle * 0.5m).ToString();
                            }
                            entity.EntityData.Properties.Add(newProperty);

                            newProperty       = new Property();
                            newProperty.Key   = "outerconeangle";
                            newProperty.Value = "90";
                            if (decimal.TryParse(properties["outerang"], out decimal outerAngle))
                            {
                                newProperty.Value = (outerAngle * 0.5m).ToString();
                            }
                            entity.EntityData.Properties.Add(newProperty);

                            newProperty       = new Property();
                            newProperty.Key   = "angles";
                            newProperty.Value = "0 0 0";
                            string[] dirParts = properties["direction"].Split(',');
                            if (decimal.TryParse(dirParts[0], out decimal dirX) &&
                                decimal.TryParse(dirParts[1], out decimal dirY) &&
                                decimal.TryParse(dirParts[2], out decimal dirZ))
                            {
                                Coordinate dir   = new Coordinate(dirX, dirY, dirZ).Normalise();
                                decimal    pitch = DMath.RadiansToDegrees(DMath.Asin(-dir.Y));
                                dir.Y = 0;
                                decimal yaw = 0m;
                                if (dir.LengthSquared() > 0.01m)
                                {
                                    dir = dir.Normalise();
                                    yaw = DMath.RadiansToDegrees(DMath.Atan2(-dir.X, dir.Z));
                                }

                                newProperty.Value = $"{pitch} {yaw} 0";
                            }
                            entity.EntityData.Properties.Add(newProperty);
                            break;

                        default:
                            entity.ClassName       = entityName;
                            entity.EntityData.Name = entityName;

                            foreach (var key in properties.Keys)
                            {
                                newProperty       = new Property();
                                newProperty.Key   = key;
                                newProperty.Value = properties[key];
                                entity.EntityData.Properties.Add(newProperty);
                            }
                            break;
                        }

                        entity.Origin = new Coordinate((decimal)xTranslate, (decimal)yTranslate, (decimal)zTranslate);
                        entity.SetParent(map.WorldSpawn);
                    }
                    else if (Math.Abs(entitySubType - 2.0f) < 0.01f)
                    {
                        if (models == null)
                        {
                            models = LoadAllModels(modelDirs);
                        }
                        ModelReference model          = null;
                        Coordinate     angles         = null;
                        Coordinate     scale          = null;
                        long           returnPosition = stream.Position;
                        for (int j = 0; j < meshCount; j++)
                        {
                            stream.Position = memblockLocations[j];

                            UInt32 memblockSize = br.ReadUInt32();
                            UInt32 dwFVF        = br.ReadUInt32();
                            UInt32 dwFVFSize    = br.ReadUInt32();
                            UInt32 dwVertMax    = br.ReadUInt32();

                            for (int k = 0; k < models.Count; k++)
                            {
                                DataStructures.Models.Mesh currMesh = models[k].Model.BodyParts[0].Meshes.Values.First()[0];

                                if (dwVertMax == currMesh.Vertices.Count)
                                {
                                    List <Pair <Coordinate, Coordinate> > points = new List <Pair <Coordinate, Coordinate> >();
                                    List <Coordinate> loadedPoints = new List <Coordinate>();
                                    Coordinate        loadedCenter = new Coordinate(0, 0, 0);
                                    Coordinate        knownCenter  = new Coordinate(0, 0, 0);
                                    for (int l = 0; l < dwVertMax; l++)
                                    {
                                        float      x     = br.ReadSingle();
                                        float      z     = br.ReadSingle();
                                        float      y     = br.ReadSingle();
                                        Coordinate point = new Coordinate((decimal)x, (decimal)y, (decimal)z);
                                        loadedPoints.Add(point);
                                        loadedCenter += point;
                                        knownCenter  += new Coordinate(currMesh.Vertices[l].Location);
                                        for (int m = 12; m < dwFVFSize; m += 4)
                                        {
                                            stream.Position += 4;
                                        }

                                        if (points.Count < 3)
                                        {
                                            int        nativeIndex = (l / 3) * 3 + ((l % 3) + 1) % 3;
                                            Coordinate vertexLoc   = new Coordinate(currMesh.Vertices[nativeIndex].Location);
                                            if (!points.Any(p => Math.Abs(p.Item1.Normalise().Dot(vertexLoc.Normalise())) > 0.95m))
                                            {
                                                points.Add(new Pair <Coordinate, Coordinate>(vertexLoc, point));
                                            }
                                        }
                                    }

                                    loadedCenter /= dwVertMax;
                                    knownCenter  /= dwVertMax;

                                    if (points.Count >= 3)
                                    {
                                        model = models[k];

                                        for (int l = 0; l < 3; l++)
                                        {
                                            points[l].Item1 -= knownCenter; points[l].Item1 = points[l].Item1.Normalise();
                                            points[l].Item2 -= loadedCenter; points[l].Item2 = points[l].Item2.Normalise();
                                        }

                                        points[2].Item1 = points[0].Item1.Cross(points[1].Item1).Normalise();
                                        points[2].Item2 = points[0].Item2.Cross(points[1].Item2).Normalise();

                                        points[1].Item1 = points[0].Item1.Cross(points[2].Item1).Normalise();
                                        points[1].Item2 = points[0].Item2.Cross(points[2].Item2).Normalise();

                                        decimal dotX0 = Coordinate.UnitX.Dot(points[0].Item1);
                                        decimal dotX1 = Coordinate.UnitX.Dot(points[1].Item1);
                                        decimal dotX2 = Coordinate.UnitX.Dot(points[2].Item1);

                                        decimal dotY0 = Coordinate.UnitY.Dot(points[0].Item1);
                                        decimal dotY1 = Coordinate.UnitY.Dot(points[1].Item1);
                                        decimal dotY2 = Coordinate.UnitY.Dot(points[2].Item1);

                                        decimal dotZ0 = Coordinate.UnitZ.Dot(points[0].Item1);
                                        decimal dotZ1 = Coordinate.UnitZ.Dot(points[1].Item1);
                                        decimal dotZ2 = Coordinate.UnitZ.Dot(points[2].Item1);

                                        Coordinate newX = (dotX0 * points[0].Item2 + dotX1 * points[1].Item2 + dotX2 * points[2].Item2);
                                        Coordinate newY = (dotY0 * points[0].Item2 + dotY1 * points[1].Item2 + dotY2 * points[2].Item2);
                                        Coordinate newZ = (dotZ0 * points[0].Item2 + dotZ1 * points[1].Item2 + dotZ2 * points[2].Item2);

                                        Coordinate unTransformedMin = new Coordinate(
                                            loadedPoints.Select(p => p.X).Min(),
                                            loadedPoints.Select(p => p.Y).Min(),
                                            loadedPoints.Select(p => p.Z).Min()
                                            );

                                        Coordinate unTransformedBounds = new Coordinate(
                                            loadedPoints.Select(p => p.X).Max(),
                                            loadedPoints.Select(p => p.Y).Max(),
                                            loadedPoints.Select(p => p.Z).Max()) - unTransformedMin;

                                        Coordinate propScale(Coordinate p)
                                        {
                                            Coordinate retVal = p.Clone();

                                            retVal.X *= (decimal)xScale / unTransformedBounds.X;
                                            retVal.Y *= (decimal)yScale / unTransformedBounds.Y;
                                            retVal.Z *= (decimal)zScale / unTransformedBounds.Z;
                                            return(retVal);
                                        }

                                        Coordinate centerDiff = propScale(loadedCenter - knownCenter);

                                        xTranslate += (float)centerDiff.X;
                                        yTranslate += (float)centerDiff.Y;
                                        zTranslate += (float)centerDiff.Z;

                                        Coordinate newBounds = new Coordinate(
                                            loadedPoints.Select(p => propScale(p).Dot(newX)).Max() - loadedPoints.Select(p => propScale(p).Dot(newX)).Min(),
                                            loadedPoints.Select(p => propScale(p).Dot(newY)).Max() - loadedPoints.Select(p => propScale(p).Dot(newY)).Min(),
                                            loadedPoints.Select(p => propScale(p).Dot(newZ)).Max() - loadedPoints.Select(p => propScale(p).Dot(newZ)).Min());

                                        Coordinate newBounds2 = new Coordinate(
                                            loadedPoints.Select(p => p.Dot(newX)).Max() - loadedPoints.Select(p => p.Dot(newX)).Min(),
                                            loadedPoints.Select(p => p.Dot(newY)).Max() - loadedPoints.Select(p => p.Dot(newY)).Min(),
                                            loadedPoints.Select(p => p.Dot(newZ)).Max() - loadedPoints.Select(p => p.Dot(newZ)).Min());

                                        scale = new Coordinate(newBounds.X / newBounds2.X, newBounds.Z / newBounds2.Z, newBounds.Y / newBounds2.Y);

                                        angles = Entity.ToEuler(newX, newY, newZ);

                                        break;
                                    }
                                }
                            }
                        }
                        stream.Position = returnPosition;
                        for (int j = 8; j < 24; j++)
                        {
                            stream.Position += 4;
                        }
                        int materialCount = (int)br.ReadSingle() + 1;
                        for (int j = 0; j < materialCount; j++)
                        {
                            string materialName = br.ReadLine();
                            for (int k = 0; k < 10; k++)
                            {
                                stream.Position += 4;
                            }
                        }

                        Entity entity = new Entity(map.IDGenerator.GetNextObjectID());
                        entity.ClassName       = "model";
                        entity.EntityData.Name = "model";
                        entity.Colour          = Colour.GetDefaultEntityColour();

                        Property newProperty;

                        if (model != null)
                        {
                            newProperty       = new Property();
                            newProperty.Key   = "file";
                            newProperty.Value = System.IO.Path.GetFileNameWithoutExtension(model.Path);
                            entity.EntityData.Properties.Add(newProperty);

                            if (angles != null)
                            {
                                newProperty       = new Property();
                                newProperty.Key   = "angles";
                                newProperty.Value = angles.ToDataString();
                                entity.EntityData.Properties.Add(newProperty);
                            }

                            if (scale != null)
                            {
                                newProperty       = new Property();
                                newProperty.Key   = "scale";
                                newProperty.Value = scale.ToDataString();
                                entity.EntityData.Properties.Add(newProperty);
                            }
                        }

                        entity.Origin = new Coordinate((decimal)xTranslate, (decimal)yTranslate, (decimal)zTranslate);
                        entity.SetParent(map.WorldSpawn);
                    }
                }
            }

            if (models != null)
            {
                models.ForEach(m => ModelProvider.DeleteModelReference(m));
            }

            return(map);
        }