[PloobsEngine] Tutorial 2 – Message System and Triggers


This third tutorial will teach you about the PloobsEngine Message System and the Trigger system. (tutorials series here)

The Message System is one of the most important component in the engine, it is responsible for letting entities to communicate exchanging messages.

Message Deliver Component

This component (Component system was introduced in the last tutorial ) is responsible for sending messages to specific entities

Everyone (components, screens, triggers, objects …) can send messages.

To be able to recieve a message you need to implement an interface called IRecieveMessageEntity (like the build in class IObject).

    // Summary:
    //     Entity that can recieve a message
    public interface IRecieveMessageEntity : IEntity
    {
        // Summary:
        //     Handles the message.
        //
        // Parameters:
        //   mes:
        //     The mes.
        void HandleMessage(Message mes);
        //
        // Summary:
        //     Handles a message from determined sender type.
        //
        // Parameters:
        //   type:
        //     Sender type.
        bool HandleThisMessageType(SenderType type);
    }

This Interface extends IEntity (so not all entities can recieve message, just ones that are IRecieveMessageEntity also). The method HandleMessage is the place where you actually handle the incomming messages. The method HandleThisMessageType helps the entity to filter the messages that it will proccess.

The entity interface is:

namespace PloobsEngine.Entity
{
    // Summary:
    //     Represents a generic entity
    public interface IEntity
    {
        // Summary:
        //     return the entity id
        //
        // Returns:
        //     the id
        int GetId();
        //
        // Summary:
        //     sets the id
        //
        // Parameters:
        //   id:
        void SetId(int id);
    }
}

It just has methods for setting and getting the ID.

All entities (and IRecieveMessageEntity also) must be registered in the engine (to fill the ID field and other stuffs). To do this you need to call the following static method. (The build in Entities like IObject already does this internally)

EntityMapper.getInstance().AddEntity(this);

The EntityMapper has method to handle entities like Remove, check if an entity exists, recover an entity by ID, and others stuffs.

Messages can be send directely to a reciever or can be bradcasted in a channel. Classes that extend IRecieveMessagesEntity can “listen” channels. To add an entity to a channel use this:

EntityMapper.getInstance().AddgrouptagRecieveEntity("ChannelName",ENTITY);

Where ChannelName is the name of the channel =P (if the channel does not exist, it is created) and the Entity is the IRecieveMessagesEntity instance. Remember that before registering an entity in a channel you MUST register the entity with the engine.

Sending and Recieving Messages

To send a message use (You can call it everywhere):

Message m = new Message(DESTINY_ID, SENDER_ID, "DestinyChannel", Priority.MEDIUM, TimeToDeliver, SenderType.OBJECT, MessageContent, "MessageTag");
MessageDeliver.SendMessage(m);

DIFERENT from the common components you dont create a Command to the MessageDeliver to send a message, you use a static method. We choose this way cause messages are critical and need speed.

MessageDeliver is a complex system and can handle lots of types of messages and deliver methods. Messages can be scheduled (to be send in the future), can be send in the moment you call the deliver method, can be send when possible (if you choose, MessageDeliver can send a fixed configurable number of messages each frame),  can check if the destiny Entity exists (and if does  not, the MessageDeliver send you a message telling what happened) …. See the MessageDeliver methods for more info.

When a message arrive to an IRecieveMessageEntity, the HandleThisMessageType of the entity is called, and you can decide, looking at the message type, if you will or will not handle this message. if you return true, the method HandleMessage(Message mes) will be called.

The IObject (read the first tutorial if you dont know what it is) has an easy way to handle messages, you can attach a c# event to it that will be called when messes arrives:

object.OnRecieveMessage += new OnRecieveMessage(obj3_OnRecieveMessage);

REMEMBER, the MessageDeliver component is not added by default, you MUST add it in the Init of your screen:

        protected override void InitScreen(PloobsEngine.Engine.GraphicInfo GraphicInfo, PloobsEngine.Engine.EngineStuff engine)
        {
            base.InitScreen(GraphicInfo, engine);

            ///Add Message Deliver Component
            MessageDeliver md = new MessageDeliver();
            engine.AddComponent(md);
        }

When you extend the IRecieveMessagesEntity, you implement the handler in the HandleMessage method. For more info, see the code sample below.

Ploobs Triggers

Triggers are  an invisible shape that when in contact with something, fire an event (throw messages in our case). The Trigger shape must be a TriangleMesh (you load it from a .x model for example).

Each trigger has a channel associated, when contact is detected, messages are send to it.

When you create a trigger you can choose when it will send messages (when contact begins, when contact ends ….) and what channel it will use..

The following code shows how to create a trigger.

          ///Model used as base the for the trigger
          SimpleModel sm = new SimpleModel(factory,"..\\Content\\Model\\cubo" );                

          ///Create the triangle mesh from the model
          TriangleMeshObject tm = new TriangleMeshObject(sm,new Vector3(200, 5, 0),Matrix.Identity,Vector3.One * 10,MaterialDescription.DefaultBepuMaterial());
          ///Create the event that the trigger will fire
          ///TriggerEvent is the name of the CHANNEL (SEE CHANGINGMESSAGESSCREEN.CS) where the trigger will send the messages. (you can change the name at your will, change also the channel that the other objects are listening)
          TriggerEvent te = new TriggerEvent("TriggerEvent","TriggerTest1");
          ///Creating and adding the trigger to the physic world
          BepuPhysicWorld physicWorld = this.World.PhysicWorld as BepuPhysicWorld;
          System.Diagnostics.Debug.Assert(physicWorld != null);
          ///Setting triggers configuration, IT RECIEVES A TRIANGLE MESH
          ///TRIGGERS ARE ALWAYS TRIANGLE MESHES !!!!
          BepuTrigger bt = new BepuTrigger(physicWorld, tm, te, true, true, true, true);
          ///Adiciona o trigger ao mundo
          this.World.AddTrigger(bt);

In the beggining we just created a model anda triangle mesh (trigger shape).

The first new thing here is the TriggerEvent. It describes the name of the trigger (usefull to recover it from the world and the channel name where messages will be sent).

Then we create the trigger itself, note that we had to recover the physic world (cause the BepuTrigger need an instance of the BepuPhysicWorld).

The engine always let you to recover the low level objects used internally. For example, we have our interface IPhysicWorld (the engine just see ithis), but you always can cast it to the right physic world implementation if you need specific features (physic engine works diferent, we cant make an interface that fill all of them, sometimes you have to cast to use specific features).

Code Sample

The following code sample shows how to use the Message System and the Triggers.

We have a box object with the same shape and in the same position of our trigger. We set this box to use a GhostPhysicObject (we did not talk about physic yet in the tutorials series, you only need to know that the specific GhostPhysicObject is an physic object that does not exist in physic world, so it does not collide, not interact and is not detected by the trigger).

If you press the left mouse buttom you will throw a ball to the scene, if this ball hits the trigger (the ghost box =P) then a message will sent to registered channel. We have another box that is “listening” to this channel and it will change its color when trigger messages arrives.

We also created one object that extends the IRecieveMessageEntity that also listen the trigger channel, just to show how to do this.

The sample code follows (very commented):

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Entity;
using PloobsEngine.Input;
using PloobsEngine.Light;
using PloobsEngine.Material;
using PloobsEngine.Modelo;
using PloobsEngine.Physics;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.SceneControl;
using PloobsEngine.Trigger;
using PloobsEngine.MessageSystem;
using PloobsEngine.Utils;
using PloobsEngine.Engine;

namespace IntroductionDemo4._0
{
    ///
    /// Trigger Screen
    ///
    public class TriggerBepuScreen : IScene
    {
        ICamera cam;
        LightThrowBepu lt;
        ReciveMessage rmessage;

        protected override void SetWorldAndRenderTechnich(out IRenderTechnic renderTech, out IWorld world)
        {
            world = new IWorld(new BepuPhysicWorld(-0.98f, true), new SimpleCuller());

            DeferredRenderTechnicInitDescription desc = DeferredRenderTechnicInitDescription.Default();
            desc.UseFloatingBufferForLightMap = true;
            desc.BackGroundColor = Color.CornflowerBlue;
            renderTech = new DeferredRenderTechnic(desc);
        }

        protected override void InitScreen(PloobsEngine.Engine.GraphicInfo GraphicInfo, PloobsEngine.Engine.EngineStuff engine)
        {
            base.InitScreen(GraphicInfo, engine);

            ///Adicionando Componente de Mensagens
            ///Utilizado pelo Trigger
            ///Triggers uses this component
            MessageDeliver md = new MessageDeliver();
            engine.AddComponent(md);
        }

        protected override void LoadContent(PloobsEngine.Engine.GraphicInfo GraphicInfo, PloobsEngine.Engine.GraphicFactory factory, IContentManager contentManager)
        {
            base.LoadContent(GraphicInfo, factory, contentManager);                        

            #region Trigger
            ///Criacao de um Trigger
            ///Create a trigger
            {
                ///Modelo cujo formato sera utilizado para disparar o trigger
                ///Model used as base the for the trigger
                SimpleModel sm = new SimpleModel(factory,"..\\Content\\Model\\cubo" );
                sm.SetTexture(factory.CreateTexture2DColor(1,1, Color.Red), TextureType.DIFFUSE); ///VERMELHO

                ///Criacao do Triangle Mesh
                ///Create the triangle mesh from the model
                TriangleMeshObject tm = new TriangleMeshObject(sm,new Vector3(200, 5, 0),Matrix.Identity,Vector3.One * 10,MaterialDescription.DefaultBepuMaterial());
                ///Criacao do Evento q sera disparado qd o trigger for acionado
                ///Pode-se criar outros tipos de eventos, basta extender a classe  IEvent
                ///O parametro passado eh o canal em que o trigger enviara suas mensagens
                ///Qualquer Entidade que extende IRecieveMessageEntity pode receber mensagens
                ///Create the eventr that the trigger will fire
                ///TriggerEvent is the name of the CHANNEL (SEE CHANGINGMESSAGESSCREEN.CS) where the trigger will send the messages. (you can change the name at your will, change also the channel that the other objects are listening)
                TriggerEvent te = new TriggerEvent("TriggerEvent","TriggerTest1");
                ///Criacao do Trigger
                ///Creating and adding the trigger to the physic world
                BepuPhysicWorld physicWorld = this.World.PhysicWorld as BepuPhysicWorld;
                System.Diagnostics.Debug.Assert(physicWorld != null);
                ///Setting triggers configuration, IT RECIEVES A TRIANGLE MESH
                ///TRIGGERS ARE ALWAYS TRIANGLE MESHES !!!!
                BepuTrigger bt = new BepuTrigger(physicWorld, tm, te, true, true, true, true);
                ///Adiciona o trigger ao mundo
                this.World.AddTrigger(bt);

                ///Adicona um objeto na posicao do trigger (Objeto FANTASMA, nao sera detectado pelo trigger)
                ///Facilita na localizacao do Trigger
                ///CREATE A VISUAL OBJECT FOR THE TRIGGER (SO WE CAN SEE IT)
                ///GHOST OBJECT (NO COLLISION)
                GhostObject ghost = new GhostObject(new Vector3(200, 5, 0), Matrix.Identity,Vector3.One * 10);
                ///material and shader
                DeferredNormalShader shader = new DeferredNormalShader();
                IMaterial mat = new DeferredMaterial(shader);
                /// add the visual object (DONT NEED, WE ADDED JUST TO SEE THE TRIGGER)
                IObject obj3 = new IObject(mat, sm, ghost);
                this.World.AddObject(obj3);
            }

            #endregion

            ///Criacao de um Objeto q recebera mensagens do trigger
            ///THIS OBJECT THAT WILL RECIEVE MESSAGE FROM the trigger
            #region Models
            {
                SimpleModel sm = new SimpleModel(factory,"..\\Content\\Model\\cubo");
                sm.SetTexture(factory.CreateTexture2DColor(1,1, Color.White), TextureType.DIFFUSE); ///BRANCO
                IPhysicObject pi = new TriangleMeshObject( sm,new Vector3(20,50,50), Matrix.Identity,Vector3.One * 10,MaterialDescription.DefaultBepuMaterial());
                DeferredNormalShader shader = new DeferredNormalShader();
                IMaterial mat = new DeferredMaterial(shader);
                IObject obj3 = new IObject(mat, sm, pi);
                ///Cadastra uma funcao para tratar das mensagens recebidas
                ///existem outras maneiras de fazer isso, como Extender a classe IObject e sobrescrever o metodo HandleMessage
                ///MESSAGE HANDLER
                obj3.OnRecieveMessage += new OnRecieveMessage(obj3_OnRecieveMessage);
                this.World.AddObject(obj3);
                ///Adiciona o Objeto criado ao grupo "TriggerEvent" que recebera as mensagens do trigger
                ///Register to recieve TriggerEvent Messages (registering to the channel)
                EntityMapper.getInstance().AddgrouptagRecieveEntity("TriggerEvent", obj3);
            }

            ///Cenario de sempre
            {
                SimpleModel sm = new SimpleModel(factory, "..\\Content\\Model\\cenario");
                IPhysicObject pi = new TriangleMeshObject(sm,Vector3.Zero,Matrix.Identity,Vector3.One,MaterialDescription.DefaultBepuMaterial());
                DeferredNormalShader shader = new DeferredNormalShader();
                IMaterial mat = new DeferredMaterial(shader);
                IObject obj3 = new IObject(mat, sm, pi);
                this.World.AddObject(obj3);
            }

            #endregion        

            ///Demonstracao de que qualquer entidade pode receber mensagens
            ///Olhar a implementacao desta classe, esta no fim deste arquivo
            ///Creating an entity to recieve the trigger message also
            ///JUST to show that everyone can recieve messages
            rmessage = new ReciveMessage();

            cam = new CameraFirstPerson(GraphicInfo.Viewport);
            cam.FarPlane = 2000;

            lt = new LightThrowBepu(this.World, factory);

            #region NormalLight
            ///Conjunto de luzes direcionais
            DirectionalLightPE ld1 = new DirectionalLightPE(Vector3.Left, Color.White);
            DirectionalLightPE ld2 = new DirectionalLightPE(Vector3.Right, Color.White);
            DirectionalLightPE ld3 = new DirectionalLightPE(Vector3.Backward, Color.White);
            DirectionalLightPE ld4 = new DirectionalLightPE(Vector3.Forward, Color.White);
            DirectionalLightPE ld5 = new DirectionalLightPE(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            this.World.AddLight(ld1);
            this.World.AddLight(ld2);
            this.World.AddLight(ld3);
            this.World.AddLight(ld4);
            this.World.AddLight(ld5);
            #endregion

            this.World.CameraManager.AddCamera(cam);

        }

        protected override void Draw(GameTime gameTime, RenderHelper render)
        {
            base.Draw(gameTime, render);
            render.RenderTextComplete("Demo: Trigger (BEPU)", new Vector2(GraphicInfo.Viewport.Width - 515, 15), Color.White, Matrix.Identity);
            render.RenderTextComplete("Launch balls (Left Mouse buttom) at the red box", new Vector2(GraphicInfo.Viewport.Width - 515, 40), Color.White, Matrix.Identity);

            if (shouldDraw)
            {
                render.RenderTextComplete("Object: Trigger Activated " + mesSend.Cod + " Objeto " + triggerSend.ContactEntity.Name, new Vector2(20, 60), Color.White, Matrix.Identity);
                render.RenderTextComplete("RecieveMessage: Trigger Artivated " + rmessage.mesRec.Cod + " Objeto " + triggerSend.ContactEntity.Name, new Vector2(20, 85), Color.White, Matrix.Identity);
            }
        }

        bool shouldDraw;
        Message mesSend = null;
        BepuTrigger triggerSend = null;
        ///
        /// Chamado qd uma mensagem chega
        /// Handle message
        ///
        ///

        ///

        void obj3_OnRecieveMessage(IObject Reciever, PloobsEngine.MessageSystem.Message mes)
        {
            ///Checa se eh a mensagem correta
            if (mes.SenderType == PloobsEngine.MessageSystem.SenderType.EVENT && mes.Tag == "TriggerEvent")
            {
                BepuTrigger trigger = (BepuTrigger)mes.Content;
                mesSend = mes;
                triggerSend = trigger;
                shouldDraw = true;
            }
        }

        protected override void CleanUp(EngineStuff engine)
        {
            EntityMapper.getInstance().ClearAllEntries();
            engine.RemoveComponent("MessageDeliver");
            lt.CleanUp();
        }
    }

    ///
    /// Entity that recieves message
    /// NEED TO EXTEND IRecieveMessageEntity
    ///
    public class ReciveMessage : IRecieveMessageEntity
    {
        public ReciveMessage()
        {
            ///REGISTER THE ENTITY
            EntityMapper.getInstance().AddEntity(this);
            ///ADD TO THE TRIGGER CHANNEL
            EntityMapper.getInstance().AddgrouptagRecieveEntity("TriggerEvent",this);
        }
        ~ReciveMessage()
        {
            ///Remove this entity registration.
            EntityMapper.getInstance().RemoveEntity(this);
        }

        #region IRecieveMessageEntity Members

        public bool HandleThisMessageType(SenderType type)
        {
            return true;
        }

        public Message mesRec = null;
        ///
        /// handle the message
        ///
        ///

        public void HandleMessage(Message mes)
        {
            if (mes.SenderType == PloobsEngine.MessageSystem.SenderType.EVENT && mes.Tag == "TriggerEvent")
            {
                BepuTrigger trigger = (BepuTrigger)mes.Content;
                mesRec = mes;
            }
        }

        #endregion

        #region IEntity Members
        int id;
        public int GetId()
        {
            return id;
        }

        public void SetId(int id)
        {
            this.id = id;
        }

        #endregion
    }
}

Summarizing:

  • IRecieveMessagesEntity interface defines an Entity that can recieve messages
  • Entities need to be registered with engine
  • IRecieveMessagesEntity can listen Channels
  • Everyone can calls MessageDeliver.SendMessage to send a message
  • Triggers are invisible triangle mesh that detects collision and send messages to channels describing what happened (entities colliding are included in the message =P)

The code for this demo can be found in our Introduction Demos package (called TriggerBepuScreen.cs), you can download it here. (there are lots of others demos in this package, we will explain each of them in the next tutorials). The package also has another sample about exchanging messages check the ChangingMessagesScreen.cs (it shows some extra features about messages like forcing entities ID, sending direct messages ….)

Any doubts, critics, suggestions, pls go to our forum or leave a comment here.

See you guys =P

Links

, , , , , , , , , ,

  1. #1 by 123movie on 23 de julho de 2017 - 5:15 pm

    Hurrah, that’s what I was seeking for, what a data!
    present here at this web site, thanks admin of this
    web page.

  2. #2 by the last five years on 23 de julho de 2017 - 5:19 pm

    This is a good tip especially to those new to the blogosphere.
    Short but very precise info… Many thanks for sharing this one.
    A must read post!

  3. #3 by match.com on 23 de julho de 2017 - 5:30 pm

    Great Web-site, Maintain the useful job. Thank you.

  4. #4 by Military Biloxi Rentals on 23 de julho de 2017 - 5:36 pm

    check beneath, are some entirely unrelated sites to ours, even so, they are most trustworthy sources that we use

  5. #5 by album jul je ne me vois pas briller on 23 de julho de 2017 - 6:04 pm

    That’s why they see no issue in staying unproductive or even with stealing from
    you. This computer software installs discreetly and
    no matter who is working with the cell phone they will not detect the cell
    phone monitoring software installed. Right after all, it really is your corporation that feeds and outfits your relatives and
    puts a ceiling over their mind.

  6. #6 by Biloxi Property Management on 23 de julho de 2017 - 6:11 pm

    although internet websites we backlink to beneath are considerably not related to ours, we really feel they are in fact really worth a go by means of, so possess a look

  7. #7 by garage door fitters on 23 de julho de 2017 - 6:16 pm

    Do you have any video of that? I’d love to find out some additional information.

  8. #8 by cheap Callaway Golf on 23 de julho de 2017 - 6:22 pm

    If you are like a lot of people you can simply overlook this. The best thing you can do is become relevant with yourself and faithful with your own morals. Generally this will lead to a mistaken and unproductive life.
    cheap Callaway Golf http://www.callawaygolf.online

  9. #9 by Jason spencer student loan on 23 de julho de 2017 - 6:26 pm

    Very nice post. I simply stumbled upon your weblog and wanted to say that I’ve really enjoyed browsing your blog posts.
    After all I’ll be subscribing for your rss feed and I’m hoping
    you write again very soon!

  10. #10 by 2017 Christian Louboutin Outlet Online on 23 de julho de 2017 - 6:32 pm

    It supplement is in such a awesome price tag I never ever idea that the high quality would be so that exceptional. It’s striking. That mama will love this in Christmas early morning anytime she opens gifts therefore looks as though I devoted even more, however prices was really awesome!!

  11. #11 by hermes belt replica on 23 de julho de 2017 - 6:33 pm

    The product or service ended up being in such a very good rates I never considered that the high quality would be therefore excellent. It is breathtaking. Our mama will likely adore it at Christmas early morning where she opens up gifts therefore seems as though I spent far more, still pricing is just great!!

  12. #12 by Original louis vuitton outlet on 23 de julho de 2017 - 6:33 pm

    How do you make this blog look this sick! Email me if you get the chance and share your wisdom. Id be thankful!
    Original louis vuitton outlet http://www.bagsfashion.online

  13. #13 by authentic chanel bags outlet on 23 de julho de 2017 - 6:39 pm

    Interesting article. Were did you got all the information from
    authentic chanel bags outlet http://www.tmearegion26.com/chanel/

  14. #14 by north face store on 23 de julho de 2017 - 6:39 pm

    To find that thing in your life you may need backup and the capacity to sustain yourself has many advantages. Keep in mind that if you can come up with someone else in order to really encourage, backup and keep you motivated to keep proceeding then that would be worthwhile.
    north face store http://www.northfacesale.online

  15. #15 by vibram five fingers sale uk on 23 de julho de 2017 - 6:39 pm

    mistime tollgate sessio Selia vennera bobsleigh technomancer florus crippled
    vibram five fingers sale uk http://www.vibramfivefingersoutlet.online

  16. #16 by cheap uggs on 23 de julho de 2017 - 6:40 pm

    Thanks so much for your post. I love this site. If you are ever looking to drive in more visitors to your website, come check us out.
    cheap uggs http://www.uggoutletstore.online

  17. #17 by arcteryx outlet seattle on 23 de julho de 2017 - 6:40 pm

    I think that is an interesting point, it made me think a bit. Thanks for sparking my thinking cap. Sometimes I get so much in a rut that I just feel like a record.
    arcteryx outlet seattle http://www.arcteryxoutletonlineu.com

  18. #18 by michael kors factory outlet on 23 de julho de 2017 - 6:40 pm

    Hello,i must tell your my phonenumeber: 607064931 It means: tanie pokoje w pobierowie, nawet bardzo tanie mam w ofercie.
    michael kors factory outlet http://www.factorymichaelkorsoutletstore.com

  19. #19 by michael kors promo code canada on 23 de julho de 2017 - 6:40 pm

    Wonderful post. I learn new stuff on different blogs everyday. It is always stimulating to see content from other writers and learn a little something from their site. Let me apply certain of their content on my blog holistic acne mind. Natually Ill present you with a link to a site. Thanks sharing.
    michael kors promo code canada http://www.michaelkorsoutletcoupons.com

  20. #20 by jimmy choo miami sale on 23 de julho de 2017 - 6:41 pm

    ohhh nice info VRy interesting to read it。
    jimmy choo miami sale http://www.jimmychoooutlet.online

  21. #21 by Shop Golden Goose Cheap DB Francy Sneakers In Calf Suede Upper White Leather Star on 23 de julho de 2017 - 6:46 pm

    I’ve learn some just right stuff here. Certainly value bookmarking for revisiting. I wonder how much effort you set to make one of these excellent informative website.

  22. #22 by codigos de barras on 23 de julho de 2017 - 6:53 pm

    Yes! Finally someone writes about brokerage account.

  23. #23 by Coach Bags Outlet store on 23 de julho de 2017 - 7:06 pm

    Im totally confused after reading information on this site, and other websites and blogs. Which supplement, or nutritional supplements, should you actually be taking? One site says x is good for you, the other says it wastes your muscles, dont listen to them. Can anyone sort through the marketing hype and deliver actual honest feedback on good supplements to use?
    Coach Bags Outlet store http://www.coachbagsfactoryoutletstore.com

  24. #24 by moncler outlet store on 23 de julho de 2017 - 7:25 pm

    Definitely believe that which you stated. Your favorite justification appeared to be on the internet the simplest thing to be aware of. I say to you, I certainly get annoyed while people think about worries that they plainly dont know about. You managed to hit the nail upon the top and also defined out the whole thing without having side-effects , people could take a signal. Will probably be back to get more. Thanks!
    moncler outlet store http://www.moncleroutletstore.online

  25. #25 by women healthier than men on 23 de julho de 2017 - 7:28 pm

    It’s in fact very difficult in this full of activity
    life to listen news on Television, thus I only use internet
    for that purpose, and get the most up-to-date information.

  26. #26 by 123 movies on 23 de julho de 2017 - 7:36 pm

    Very nice post. I just stumbled upon your weblog and wanted to say that I
    have truly enjoyed browsing your blog posts. After all I’ll be subscribing to your
    rss feed and I hope you write again soon!

  27. #27 by prada outlet store on 23 de julho de 2017 - 7:36 pm

    workingman vala nope passe galdy duangphorn oberdorff Yuji travelling
    prada outlet store http://www.shopstylestore.online

1 2.029 2.030 2.031
(não será publicado)