Browse Source

Adding Mods folder for feature examples, factoring physics rag doll 2D HUD into a mod

Josh Engebretson 9 years ago
parent
commit
19743bd091
42 changed files with 2456 additions and 778 deletions
  1. 1 45
      FeatureExamples/CPlusPlus/Source/CreateRagdoll.cpp
  2. 0 1
      FeatureExamples/CPlusPlus/Source/CreateRagdoll.h
  3. 59 332
      FeatureExamples/CPlusPlus/Source/Ragdolls.cpp
  4. 0 24
      FeatureExamples/CPlusPlus/Source/Ragdolls.h
  5. 8 12
      FeatureExamples/CPlusPlus/Source/Sample.cpp
  6. 1 7
      FeatureExamples/CPlusPlus/Source/Sample.h
  7. 0 41
      FeatureExamples/CSharp/Resources/Components/Ragdoll.cs
  8. 22 308
      FeatureExamples/CSharp/Resources/Scripts/13_Ragdolls.cs
  9. 1 8
      FeatureExamples/CSharp/Resources/Scripts/Sample.cs
  10. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/NinjaSnowWar/Sight.png
  11. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/PostProcess/FrontPath.xml
  12. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill1.png
  13. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill2.png
  14. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill3.png
  15. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill4.png
  16. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill5.png
  17. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill6.png
  18. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudmass.png
  19. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudsize.png
  20. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudspeed.png
  21. 219 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/CreateRagdoll.cpp
  22. 52 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/CreateRagdoll.h
  23. 568 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/Ragdolls.cpp
  24. 98 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/Ragdolls.h
  25. 268 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/Sample.cpp
  26. 125 0
      FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/Sample.h
  27. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Components/.gitkeep
  28. 215 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Components/Ragdoll.cs
  29. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/PostProcess/FrontPath.xml
  30. 498 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Scripts/13_Ragdolls.cs
  31. 303 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Scripts/Sample.cs
  32. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill1.png
  33. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill2.png
  34. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill3.png
  35. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill4.png
  36. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill5.png
  37. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill6.png
  38. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudmass.png
  39. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudsize.png
  40. 0 0
      FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudspeed.png
  41. 6 0
      FeatureExamples/Mods/Ragdoll2DHud/README.md
  42. 12 0
      FeatureExamples/README.md

+ 1 - 45
FeatureExamples/CPlusPlus/Source/CreateRagdoll.cpp

@@ -25,11 +25,6 @@
 #include <Atomic/IO/Log.h>
 #include <Atomic/IO/Log.h>
 #include <Atomic/Physics/PhysicsEvents.h>
 #include <Atomic/Physics/PhysicsEvents.h>
 #include <Atomic/Physics/RigidBody.h>
 #include <Atomic/Physics/RigidBody.h>
-#include <Atomic/Scene/Scene.h>
-#include <Atomic/Resource/ResourceCache.h>
-#include <Atomic/Graphics/Material.h>
-#include <Atomic/Graphics/ParticleEmitter.h>
-#include <Atomic/Graphics/ParticleEffect.h>
 
 
 #include "CreateRagdoll.h"
 #include "CreateRagdoll.h"
 
 
@@ -57,9 +52,7 @@ void CreateRagdoll::HandleNodeCollision(StringHash eventType, VariantMap& eventD
 
 
     if (otherBody->GetMass() > 0.0f)
     if (otherBody->GetMass() > 0.0f)
     {
     {
-        HitEffect (node_); // bam!
-
-       // We do not need the physics components in the AnimatedModel's root scene node anymore
+        // We do not need the physics components in the AnimatedModel's root scene node anymore
         node_->RemoveComponent<RigidBody>();
         node_->RemoveComponent<RigidBody>();
         node_->RemoveComponent<CollisionShape>();
         node_->RemoveComponent<CollisionShape>();
 
 
@@ -180,40 +173,3 @@ void CreateRagdoll::CreateRagdollConstraint(const String& boneName, const String
     constraint->SetHighLimit(highLimit);
     constraint->SetHighLimit(highLimit);
     constraint->SetLowLimit(lowLimit);
     constraint->SetLowLimit(lowLimit);
 }
 }
-
-void CreateRagdoll::HitEffect ( Node* parent ) // ragdoll gets the donuts blown out of him
-{
-    ResourceCache* cache = GetSubsystem<ResourceCache>();
-    Scene* myscene = parent->GetScene ();
-    Vector3 where = parent->GetWorldPosition ();
-    
-    for (int mm=0; mm<5; mm++)
-    {
-        Node* xNode = myscene->CreateChild("Stuffing");
-        xNode->SetPosition( Vector3( Random(1), Random(4), Random(15)) + where );
-        xNode->SetRotation( Quaternion(Random(360), 0, Random(360)));
-        xNode->SetScale(0.3f);
-
-        ParticleEmitter* pEmitter = xNode->CreateComponent<ParticleEmitter>();
-        pEmitter->SetEffect(cache->GetResource<ParticleEffect>("Particle/Fire.xml"));
-        pEmitter->SetEnabled(true);  // sparkle donuts
-
-        //create obj
-        StaticModel* boxObject = xNode->CreateComponent<StaticModel>();
-        boxObject->SetModel(cache->GetResource<Model>("Models/Torus.mdl"));
-        boxObject->SetMaterial(cache->GetResource<Material>("Materials/Mushroom.xml"));
-        boxObject->SetCastShadows(true);
-        RigidBody* body = xNode->CreateComponent<RigidBody>();
-        body->SetMass( 0.45f);
-        body->SetRollingFriction(0.15f);
-        body->SetFriction( 0.75f);
-        body->SetUseGravity (true);
-        // Disable collision event signaling to reduce CPU load of the physics simulation a111
-        body->SetCollisionEventMode( COLLISION_NEVER );
-        CollisionShape* shape = xNode->CreateComponent<CollisionShape>();
-        shape->SetSphere(1.0f, Vector3(0,0,0), Quaternion(1,0,0,0));
-        float objectVelocity = 22.0f;
-        //Node.Rotation
-        body->SetLinearVelocity( Quaternion(Random(360), 0, Random(360))* Vector3(0.0f, 0.02f, 1.0f) * objectVelocity);
-    }
-}

+ 0 - 1
FeatureExamples/CPlusPlus/Source/CreateRagdoll.h

@@ -40,7 +40,6 @@ public:
 protected:
 protected:
     /// Handle node being assigned.
     /// Handle node being assigned.
     virtual void OnNodeSet(Node* node);
     virtual void OnNodeSet(Node* node);
-    void HitEffect ( Node* parent ); // ragdoll gets the donuts blown out of him
     
     
 private:
 private:
     /// Handle scene node's physics collision.
     /// Handle scene node's physics collision.

+ 59 - 332
FeatureExamples/CPlusPlus/Source/Ragdolls.cpp

@@ -41,12 +41,6 @@
 #include <Atomic/Resource/ResourceCache.h>
 #include <Atomic/Resource/ResourceCache.h>
 #include <Atomic/Scene/Scene.h>
 #include <Atomic/Scene/Scene.h>
 #include <Atomic/UI/UI.h>
 #include <Atomic/UI/UI.h>
-#include <Atomic/Atomic2D/StaticSprite2D.h>
-#include <Atomic/Atomic2D/AnimationSet2D.h>
-#include <Atomic/Atomic2D/AnimatedSprite2D.h>
-#include <Atomic/Atomic2D/Sprite2D.h>
-#include <Atomic/Graphics/RenderPath.h>
-#include <Atomic/Resource/XMLFile.h>
 
 
 #include "CreateRagdoll.h"
 #include "CreateRagdoll.h"
 #include "Ragdolls.h"
 #include "Ragdolls.h"
@@ -59,36 +53,6 @@ Ragdolls::Ragdolls(Context* context) :
 {
 {
     // Register an object factory for our custom CreateRagdoll component so that we can create them to scene nodes
     // Register an object factory for our custom CreateRagdoll component so that we can create them to scene nodes
     context->RegisterFactory<CreateRagdoll>();
     context->RegisterFactory<CreateRagdoll>();
-    
-    massCount = 2;
-    speedCount = 2;
-    sizeCount = 2;
-
-    bulletMass.Push(1.0f);
-    bulletMass.Push(10.0f);
-    bulletMass.Push(50.0f);
-    bulletMass.Push(100.0f);
-    bulletMass.Push(300.0f);
-    bulletMass.Push(666.0f);
-    bulletMass.Push(1000.0f);
-    bulletSpeed.Push(10.0f);
-    bulletSpeed.Push(22.0f);
-    bulletSpeed.Push(41.0f);
-    bulletSpeed.Push(72.0f);
-    bulletSpeed.Push(116.0f);
-    bulletSpeed.Push(200.0f);
-    bulletSpeed.Push(450.0f);
-    bulletSize.Push(0.25f);
-    bulletSize.Push(0.5f);
-    bulletSize.Push(1.25f);
-    bulletSize.Push(3.25f);
-    bulletSize.Push(5.25f);
-    bulletSize.Push(7.25f);
-    bulletSize.Push(11.25f);
-    bulletSize.Push(16.25f);
-
-    bulletArc = 0.25f;
-
 }
 }
 
 
 void Ragdolls::Start()
 void Ragdolls::Start()
@@ -99,9 +63,6 @@ void Ragdolls::Start()
     // Create the scene content
     // Create the scene content
     CreateScene();
     CreateScene();
 
 
-    // add an overlay HUD that tells you settings
-    CreateHUD();
-
     // Create the UI content
     // Create the UI content
     CreateInstructions();
     CreateInstructions();
 
 
@@ -113,15 +74,6 @@ void Ragdolls::Start()
 
 
     // Set the mouse mode to use in the sample
     // Set the mouse mode to use in the sample
     Sample::InitMouseMode(MM_ABSOLUTE);
     Sample::InitMouseMode(MM_ABSOLUTE);
-    
-    RestartJacks ();
-
-    UpdateSpeedHud (speedCount);
-    UpdateMassHud (massCount);
-    UpdateSizeHud (sizeCount);
-
-    GetSubsystem<Input>()->SetMouseVisible (false);
-
 }
 }
 
 
 void Ragdolls::CreateScene()
 void Ragdolls::CreateScene()
@@ -157,23 +109,57 @@ void Ragdolls::CreateScene()
     // Set cascade splits at 10, 50 and 200 world units, fade shadows out at 80% of maximum shadow distance
     // Set cascade splits at 10, 50 and 200 world units, fade shadows out at 80% of maximum shadow distance
     light->SetShadowCascade(CascadeParameters(10.0f, 50.0f, 200.0f, 0.0f, 0.8f));
     light->SetShadowCascade(CascadeParameters(10.0f, 50.0f, 200.0f, 0.0f, 0.8f));
 
 
-    // Create a floor object, 500 x 500 world units. Adjust position so that the ground is at zero Y
-    Node* floorNode = scene_->CreateChild("Floor");
-    floorNode->SetPosition(Vector3(0.0f, -0.5f, 0.0f));
-    floorNode->SetScale(Vector3(500.0f, 1.0f, 500.0f));
-    StaticModel* floorObject = floorNode->CreateComponent<StaticModel>();
-    floorObject->SetModel(cache->GetResource<Model>("Models/Box.mdl"));
-    floorObject->SetMaterial(cache->GetResource<Material>("Materials/StoneTiled.xml"));
-
-    // Make the floor physical by adding RigidBody and CollisionShape components
-    RigidBody* body = floorNode->CreateComponent<RigidBody>();
-    // We will be spawning spherical objects in this sample. The ground also needs non-zero rolling friction so that
-    // the spheres will eventually come to rest
-    body->SetRollingFriction(0.15f);
-    CollisionShape* shape = floorNode->CreateComponent<CollisionShape>();
-    // Set a box shape of size 1 x 1 x 1 for collision. The shape will be scaled with the scene node scale, so the
-    // rendering and physics representation sizes should match (the box model is also 1 x 1 x 1.)
-    shape->SetBox(Vector3::ONE);
+    {
+        // Create a floor object, 500 x 500 world units. Adjust position so that the ground is at zero Y
+        Node* floorNode = scene_->CreateChild("Floor");
+        floorNode->SetPosition(Vector3(0.0f, -0.5f, 0.0f));
+        floorNode->SetScale(Vector3(500.0f, 1.0f, 500.0f));
+        StaticModel* floorObject = floorNode->CreateComponent<StaticModel>();
+        floorObject->SetModel(cache->GetResource<Model>("Models/Box.mdl"));
+        floorObject->SetMaterial(cache->GetResource<Material>("Materials/StoneTiled.xml"));
+
+        // Make the floor physical by adding RigidBody and CollisionShape components
+        RigidBody* body = floorNode->CreateComponent<RigidBody>();
+        // We will be spawning spherical objects in this sample. The ground also needs non-zero rolling friction so that
+        // the spheres will eventually come to rest
+        body->SetRollingFriction(0.15f);
+        CollisionShape* shape = floorNode->CreateComponent<CollisionShape>();
+        // Set a box shape of size 1 x 1 x 1 for collision. The shape will be scaled with the scene node scale, so the
+        // rendering and physics representation sizes should match (the box model is also 1 x 1 x 1.)
+        shape->SetBox(Vector3::ONE);
+    }
+
+    // Create animated models
+    for (int z = -1; z <= 1; ++z)
+    {
+        for (int x = -4; x <= 4; ++x)
+        {
+            Node* modelNode = scene_->CreateChild("Jack");
+            modelNode->SetPosition(Vector3(x * 5.0f, 0.0f, z * 5.0f));
+            modelNode->SetRotation(Quaternion(0.0f, 180.0f, 0.0f));
+            AnimatedModel* modelObject = modelNode->CreateComponent<AnimatedModel>();
+            modelObject->SetModel(cache->GetResource<Model>("Models/Jack.mdl"));
+            modelObject->SetMaterial(cache->GetResource<Material>("Materials/Jack.xml"));
+            modelObject->SetCastShadows(true);
+            // Set the model to also update when invisible to avoid staying invisible when the model should come into
+            // view, but does not as the bounding box is not updated
+            modelObject->SetUpdateInvisible(true);
+
+            // Create a rigid body and a collision shape. These will act as a trigger for transforming the
+            // model into a ragdoll when hit by a moving object
+            RigidBody* body = modelNode->CreateComponent<RigidBody>();
+            // The Trigger mode makes the rigid body only detect collisions, but impart no forces on the
+            // colliding objects
+            body->SetTrigger(true);
+            CollisionShape* shape = modelNode->CreateComponent<CollisionShape>();
+            // Create the capsule shape with an offset so that it is correctly aligned with the model, which
+            // has its origin at the feet
+            shape->SetCapsule(0.7f, 2.0f, Vector3(0.0f, 1.0f, 0.0f));
+
+            // Create a custom component that reacts to collisions and creates the ragdoll
+            modelNode->CreateComponent<CreateRagdoll>();
+        }
+    }
 
 
     // Create the camera. Limit far clip distance to match the fog. Note: now we actually create the camera node outside
     // Create the camera. Limit far clip distance to match the fog. Note: now we actually create the camera node outside
     // the scene, because we want it to be unaffected by scene load / save
     // the scene, because we want it to be unaffected by scene load / save
@@ -198,15 +184,10 @@ void Ragdolls::CreateInstructions()
 void Ragdolls::SetupViewport()
 void Ragdolls::SetupViewport()
 {
 {
     Renderer* renderer = GetSubsystem<Renderer>();
     Renderer* renderer = GetSubsystem<Renderer>();
-    ResourceCache* cache = GetSubsystem<ResourceCache>();
-   
-    renderer->SetNumViewports(2);  // use 2 viewports, 1 for 3d and 1 for the 2d hud
-    Viewport* viewport2_ = new Viewport(context_, hudScene, hudCamera );  // hud orthographic viewport, scene and camera
-    RenderPath *overlayRenderPath = new RenderPath(); 
-    overlayRenderPath->Load(cache->GetResource<XMLFile>("PostProcess/FrontPath.xml"));  //special renderpath that does not clear
-    viewport2_->SetRenderPath(overlayRenderPath);  // apply to hud viewport, so the background is transparent
-    renderer->SetViewport(0, new Viewport(context_, scene_, cameraNode_->GetComponent<Camera>())); // perspective viewport, scene and camera
-    renderer->SetViewport(1, viewport2_);  // and add in the HUD viewport
+
+    // Set up a viewport to the Renderer subsystem so that the 3D scene can be seen
+    SharedPtr<Viewport> viewport(new Viewport(context_, scene_, cameraNode_->GetComponent<Camera>()));
+    renderer->SetViewport(0, viewport);
 }
 }
 
 
 void Ragdolls::MoveCamera(float timeStep)
 void Ragdolls::MoveCamera(float timeStep)
@@ -257,42 +238,6 @@ void Ragdolls::MoveCamera(float timeStep)
     // Toggle physics debug geometry with space
     // Toggle physics debug geometry with space
     if (input->GetKeyPress(KEY_SPACE))
     if (input->GetKeyPress(KEY_SPACE))
         drawDebug_ = !drawDebug_;
         drawDebug_ = !drawDebug_;
-        
-    if (input->GetKeyPress (KEY_U)) {
-        massCount++;
-        if ( massCount > 5 )
-            massCount = 0;
-        UpdateMassHud (massCount);
-    }
-
-    if (input->GetKeyPress (KEY_I)) {
-        speedCount++;
-        if ( speedCount> 5 )
-            speedCount = 0;
-        UpdateSpeedHud (speedCount);
-    }
-
-    if (input->GetKeyPress (KEY_O)) {
-        sizeCount++;
-        if ( sizeCount > 5 )
-            sizeCount = 0;
-        UpdateSizeHud (sizeCount);
-    }
-
-    if (input->GetKeyPress (KEY_P)) {
-        if ( bulletArc == 0.0 )
-            bulletArc = 0.25f;
-        else if ( bulletArc > 0.0 )
-            bulletArc = 0.0f;
-    }
-
-    if (input->GetKeyPress (KEY_R)) {
-        RestartJacks ();
-    }
-
-    UpdateFps ();
-    CleanUpSome ();
-
 }
 }
 
 
 void Ragdolls::SpawnObject()
 void Ragdolls::SpawnObject()
@@ -302,23 +247,23 @@ void Ragdolls::SpawnObject()
     Node* boxNode = scene_->CreateChild("Sphere");
     Node* boxNode = scene_->CreateChild("Sphere");
     boxNode->SetPosition(cameraNode_->GetPosition());
     boxNode->SetPosition(cameraNode_->GetPosition());
     boxNode->SetRotation(cameraNode_->GetRotation());
     boxNode->SetRotation(cameraNode_->GetRotation());
-    boxNode->SetScale(bulletSize[sizeCount]);
+    boxNode->SetScale(0.25f);
     StaticModel* boxObject = boxNode->CreateComponent<StaticModel>();
     StaticModel* boxObject = boxNode->CreateComponent<StaticModel>();
     boxObject->SetModel(cache->GetResource<Model>("Models/Sphere.mdl"));
     boxObject->SetModel(cache->GetResource<Model>("Models/Sphere.mdl"));
     boxObject->SetMaterial(cache->GetResource<Material>("Materials/StoneSmall.xml"));
     boxObject->SetMaterial(cache->GetResource<Material>("Materials/StoneSmall.xml"));
     boxObject->SetCastShadows(true);
     boxObject->SetCastShadows(true);
 
 
     RigidBody* body = boxNode->CreateComponent<RigidBody>();
     RigidBody* body = boxNode->CreateComponent<RigidBody>();
-    body->SetMass(bulletMass[massCount]);
+    body->SetMass(1.0f);
     body->SetRollingFriction(0.15f);
     body->SetRollingFriction(0.15f);
     CollisionShape* shape = boxNode->CreateComponent<CollisionShape>();
     CollisionShape* shape = boxNode->CreateComponent<CollisionShape>();
     shape->SetSphere(1.0f);
     shape->SetSphere(1.0f);
 
 
-    const float OBJECT_VELOCITY = bulletSpeed[speedCount];
+    const float OBJECT_VELOCITY = 10.0f;
 
 
     // Set initial velocity for the RigidBody based on camera forward vector. Add also a slight up component
     // Set initial velocity for the RigidBody based on camera forward vector. Add also a slight up component
     // to overcome gravity better
     // to overcome gravity better
-    body->SetLinearVelocity(cameraNode_->GetRotation() * Vector3(0.0f, bulletArc, 1.0f) * OBJECT_VELOCITY);
+    body->SetLinearVelocity(cameraNode_->GetRotation() * Vector3(0.0f, 0.25f, 1.0f) * OBJECT_VELOCITY);
 }
 }
 
 
 void Ragdolls::SubscribeToEvents()
 void Ragdolls::SubscribeToEvents()
@@ -348,221 +293,3 @@ void Ragdolls::HandlePostRenderUpdate(StringHash eventType, VariantMap& eventDat
     if (drawDebug_)
     if (drawDebug_)
         scene_->GetComponent<PhysicsWorld>()->DrawDebugGeometry(true);
         scene_->GetComponent<PhysicsWorld>()->DrawDebugGeometry(true);
 }
 }
-
-    // support for 2D hud and new features
-void Ragdolls::CreateHUD()
-{
-     float hscal = 0.4f;
-    //
-    // create a 2nd viewport and scene for a hud with sprites.
-    //
-    hudScene = new Scene(context_);
-    hudScene->CreateComponent<Octree>();
-    // Create camera node
-    Node* hudCam = hudScene->CreateChild("HudCamera");
-    // Set camera's position
-    hudCam->SetPosition( Vector3(0.0f, 0.0f, -10.0f));
-    hudCamera = hudCam->CreateComponent<Camera>();
-    hudCamera->SetOrthographic(true);
-    Graphics* graphics = GetSubsystem<Graphics>();
-    hudCamera->SetOrthoSize ((float)graphics->GetHeight () * 0.01f ); //PIXEL_SIZE
-
-    ResourceCache *cache = GetSubsystem<ResourceCache>();
-
-    // add a crosshair in the center of the screen
-    Sprite2D* sprite = cache->GetResource<Sprite2D>("Textures/NinjaSnowWar/Sight.png");
-    Node* targetSprite_ = hudScene->CreateChild("targetSprite");
-    targetSprite_->SetPosition2D(Vector2(0,0));
-    targetSprite_->SetScale2D(Vector2(0.75f, 0.75f));
-    StaticSprite2D* staticSprite = targetSprite_->CreateComponent<StaticSprite2D>();
-    staticSprite->SetSprite(sprite);   // Set sprite
-    staticSprite->SetBlendMode( BLEND_ALPHA ); // Set blend mode
-    staticSprite->SetAlpha(0.3f);  
-
-    // borrow the spinning coin from the 2DSprite example to show what the possibilities are
-    float halfWidth = graphics->GetWidth() * 0.5f * 0.01;
-    float halfHeight = graphics->GetHeight() * 0.5f * 0.01;
-    // Get animation set
-    AnimationSet2D* animationSet = cache->GetResource<AnimationSet2D>("Urho2D/GoldIcon.scml");
-    if (animationSet == NULL) return;
-    Node* spriteNode2 = hudScene->CreateChild("AnimatedSprite2D");
-    AnimatedSprite2D* animatedSprite = spriteNode2->CreateComponent<AnimatedSprite2D>();
-    animatedSprite->SetAnimationSet(animationSet);         // Set animation
-    animatedSprite->SetAnimation("idle", LM_DEFAULT);
-    spriteNode2->SetPosition2D( Vector2(halfWidth - 0.4f, halfHeight - 0.4f));
-
-    // (bullet) mass, speed size feature huds
-    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill1.png") );
-    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill2.png") );
-    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill3.png") );
-    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill4.png") );
-    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill5.png") );
-    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill6.png") );
-
-    Sprite2D* spritem = cache->GetResource<Sprite2D>("Textures/hudmass.png");
-    Node* hudm = hudScene->CreateChild("hudMass");
-    hudm->SetScale2D( Vector2(hscal,hscal));
-    hudm->SetPosition2D( Vector2( 0 - (halfWidth/3.0), halfHeight - 0.4)); 
-    StaticSprite2D* hudSpritem = hudm->CreateComponent<StaticSprite2D>();
-    hudSpritem->SetSprite(spritem);
-    hudSpritem->SetAlpha(0.9);
-    hudSpritem->SetBlendMode( BLEND_ALPHA);
-    hudSpritem->SetOrderInLayer(3); 
-    Node* hudfm = hudm->CreateChild("hudMassFill");
-    hudfm->SetScale2D( Vector2(1,1));
-    hudfm->SetPosition2D(  Vector2( 0, 0)); 
-    StaticSprite2D* hudSpritefm = hudfm->CreateComponent<StaticSprite2D>();
-    hudSpritefm->SetSprite(filler[0]);
-    hudSpritefm->SetAlpha(0.9);
-    hudSpritefm->SetBlendMode( BLEND_ALPHA);
-    hudSpritefm->SetOrderInLayer(-3); 
-
-    Sprite2D* sprites = cache->GetResource<Sprite2D>("Textures/hudspeed.png");
-    Node* huds = hudScene->CreateChild("hudSpeed");
-    huds->SetScale2D( Vector2(hscal,hscal));
-    huds->SetPosition2D(  Vector2( 0, halfHeight - 0.4)); 
-    StaticSprite2D* hudSprites = huds->CreateComponent<StaticSprite2D>();
-    hudSprites->SetSprite(sprites);
-    hudSprites->SetAlpha(0.9);
-    hudSprites->SetBlendMode( BLEND_ALPHA);
-    hudSprites->SetOrderInLayer(3); 
-    Node* hudsm = huds->CreateChild("hudSpeedFill");
-    hudsm->SetScale2D( Vector2(1,1));
-    hudsm->SetPosition2D( Vector2( 0, 0)); 
-    StaticSprite2D* hudSpritesm = hudsm->CreateComponent<StaticSprite2D>();
-    hudSpritesm->SetSprite(filler[0]);
-    hudSpritesm->SetAlpha(0.9);
-    hudSpritesm->SetBlendMode( BLEND_ALPHA);
-    hudSpritesm->SetOrderInLayer(-3); 
-
-    Sprite2D* spritez = cache->GetResource<Sprite2D>("Textures/hudsize.png");
-    Node* hudz = hudScene->CreateChild("hudSize");
-    hudz->SetScale2D( Vector2(hscal,hscal));
-    hudz->SetPosition2D(  Vector2( 0 + (halfWidth/3.0), halfHeight - 0.4)); 
-    StaticSprite2D* hudSpritez = hudz->CreateComponent<StaticSprite2D>();
-    hudSpritez->SetSprite(spritez);
-    hudSpritez->SetAlpha(0.9);
-    hudSpritez->SetBlendMode( BLEND_ALPHA);
-    hudSpritez->SetOrderInLayer(3); 
-    Node* hudzm = hudz->CreateChild("hudSizeFill");
-    hudzm->SetScale2D( Vector2(1,1));
-    hudzm->SetPosition2D( Vector2( 0, 0)); 
-    StaticSprite2D* hudSpritezm = hudzm->CreateComponent<StaticSprite2D>();
-    hudSpritezm->SetSprite(filler[0]);
-    hudSpritezm->SetAlpha(0.9);
-    hudSpritezm->SetBlendMode( BLEND_ALPHA);
-    hudSpritezm->SetOrderInLayer(-3);
-}
-
-void Ragdolls::RestartJacks()
-{
-    PODVector< Node * >allnodes;
-    scene_->GetChildren (allnodes, true);
-
-    for ( int ii=0; ii<allnodes.Size() ; ii++ ) 
-    { 
-        if ( allnodes[ii]->GetName().Compare ("Sphere") == 0) allnodes[ii]->Remove ();
-        else if ( allnodes[ii]->GetName().Compare ("Stuffing") == 0 ) allnodes[ii]->Remove ();
-        else if ( allnodes[ii]->GetName().Compare ("Jack") == 0 ) allnodes[ii]->Remove ();
-    }
-
-    ResourceCache *cache = GetSubsystem<ResourceCache>();
-    // Create animated models, you dont know ... jack
-   for (int z = -1; z <= 1; ++z)
-    {
-        for (int x = -4; x <= 4; ++x)
-        {
-            Node* modelNode = scene_->CreateChild("Jack");
-            modelNode->SetPosition(Vector3(x * 5.0f, 0.0f, z * 5.0f));
-            modelNode->SetRotation(Quaternion(0.0f, 180.0f, 0.0f));
-            AnimatedModel* modelObject = modelNode->CreateComponent<AnimatedModel>();
-            modelObject->SetModel(cache->GetResource<Model>("Models/Jack.mdl"));
-            modelObject->SetMaterial(cache->GetResource<Material>("Materials/Jack.xml"));
-            modelObject->SetCastShadows(true);
-            // Set the model to also update when invisible to avoid staying invisible when the model should come into
-            // view, but does not as the bounding box is not updated
-            modelObject->SetUpdateInvisible(true);
-
-            // Create a rigid body and a collision shape. These will act as a trigger for transforming the
-            // model into a ragdoll when hit by a moving object
-            RigidBody* body = modelNode->CreateComponent<RigidBody>();
-            // The Trigger mode makes the rigid body only detect collisions, but impart no forces on the
-            // colliding objects
-            body->SetTrigger(true);
-            CollisionShape* shape = modelNode->CreateComponent<CollisionShape>();
-            // Create the capsule shape with an offset so that it is correctly aligned with the model, which
-            // has its origin at the feet
-            shape->SetCapsule(0.7f, 2.0f, Vector3(0.0f, 1.0f, 0.0f));
-
-            // Create a custom component that reacts to collisions and creates the ragdoll
-            modelNode->CreateComponent<CreateRagdoll>();
-        }
-    }    
-}
-
-void Ragdolls::CleanUpSome()
-{
-    Node* cam = cameraNode_; // note - the camera isnt in the scene
-    if ( cam == NULL )
-        return;
-
-    PODVector< Node * >allnodes;
-    scene_->GetChildren (allnodes, true);
-    for ( int ii=0; ii<allnodes.Size() ; ii++ ) 
-    { 
-        if ( allnodes[ii]->GetName().Compare ("Sphere") == 0 ) 
-        {
-            if (( allnodes[ii]->GetWorldPosition() - cam->GetWorldPosition() ).Length() > 270.0f)
-            {
-                allnodes[ii]->Remove ();
-            }
-        }
-    }    
-}
-
-void Ragdolls::UpdateFps ()
-{
-    Engine* eng = GetSubsystem<Engine>();
-    String mystr = "FPS: " + String(eng->GetFps());
-    mystr += "\nUse WASD keys and mouse/touch to move\n";
-    mystr += "LMB to spawn physics objects\n";
-    mystr += "U=Mass, I=Speed, O=Size, R=Restart\n";
-    mystr += "Space to toggle physics debug geometry";
-    SetInstructions ( mystr );
-}
-
-void Ragdolls::UpdateMassHud ( int value )
-{
-    Node* xNode = hudScene->GetChild("hudMass", true);
-    if (xNode) {
-        Node* fillx = xNode->GetChild("hudMassFill");
-        if (fillx) {
-            StaticSprite2D* hudSprite = fillx->GetComponent<StaticSprite2D>();
-            hudSprite->SetSprite(filler[value]);
-        }
-    }
-}
-
-void Ragdolls::UpdateSpeedHud ( int value )
-{
-    Node* xNode = hudScene->GetChild("hudSpeed", true);
-    if (xNode) {
-        Node* fillx = xNode->GetChild("hudSpeedFill");
-        if (fillx) {
-            StaticSprite2D* hudSprite = fillx->GetComponent<StaticSprite2D>();
-            hudSprite->SetSprite(filler[value]);
-        }
-    }
-}
-
-void Ragdolls::UpdateSizeHud ( int value )
-{
-    Node* xNode = hudScene->GetChild("hudSize", true);
-    if (xNode) {
-        Node* fillx = xNode->GetChild("hudSizeFill");
-        if (fillx) {
-            StaticSprite2D* hudSprite = fillx->GetComponent<StaticSprite2D>();
-            hudSprite->SetSprite(filler[value]);
-        }
-    }
-}

+ 0 - 24
FeatureExamples/CPlusPlus/Source/Ragdolls.h

@@ -30,7 +30,6 @@ namespace Atomic
 
 
 class Node;
 class Node;
 class Scene;
 class Scene;
-class Sprite2D;
 
 
 }
 }
 
 
@@ -72,27 +71,4 @@ private:
 
 
     /// Flag for drawing debug geometry.
     /// Flag for drawing debug geometry.
     bool drawDebug_;
     bool drawDebug_;
-    
-    // support for 2D hud and new features
-    void CreateHUD();
-    void RestartJacks();
-    void CleanUpSome();
-    void UpdateFps ();
-    void UpdateMassHud ( int value );
-    void UpdateSpeedHud ( int value );
-    void UpdateSizeHud ( int value );
-    
-    // the  2nd scene for the hud "overlay"
-    SharedPtr<Scene> hudScene;    // the hud scene
-    SharedPtr<Camera> hudCamera;  // ortho cam for the (pixel perfect) hud
-    Vector <Sprite2D*> filler;    // for bargraph display
-
-    // more fun features...
-    PODVector <float> bulletMass;   // how heavy the bullet is
-    PODVector <float> bulletSpeed;  // how fast the bullet is
-    PODVector <float> bulletSize;   // how big the bullet is
-    int massCount, speedCount, sizeCount; // counters
-
-    float bulletArc;    // shooting inclination
-
 };
 };

+ 8 - 12
FeatureExamples/CPlusPlus/Source/Sample.cpp

@@ -33,6 +33,7 @@
 #include <Atomic/UI/UIFontDescription.h>
 #include <Atomic/UI/UIFontDescription.h>
 #include <Atomic/UI/UIView.h>
 #include <Atomic/UI/UIView.h>
 #include <Atomic/UI/UILayout.h>
 #include <Atomic/UI/UILayout.h>
+#include <Atomic/UI/UIEditField.h>
 
 
 #include "Sample.h"
 #include "Sample.h"
 #include "SampleSelector.h"
 #include "SampleSelector.h"
@@ -221,23 +222,18 @@ void Sample::SimpleCreateInstructions(const String& text)
 
 
     msgText += "Press ESC for menu";
     msgText += "Press ESC for menu";
 
 
-    label_ = new UIEditField(context_);
-    label_->SetFontDescription(fontDesc);
-    label_->SetReadOnly(true);
-    label_->SetMultiline(true);
-    label_->SetAdaptToContentSize(true);
-    label_->SetText(msgText);
-    layout->AddChild(label_);
+    UIEditField* label = new UIEditField(context_);
+    label->SetFontDescription(fontDesc);
+    label->SetReadOnly(true);
+    label->SetMultiline(true);
+    label->SetAdaptToContentSize(true);
+    label->SetText(msgText);
+    layout->AddChild(label);
 
 
     FeatureExamples::GetUIView()->AddChild(layout);
     FeatureExamples::GetUIView()->AddChild(layout);
 
 
 }
 }
 
 
-void Sample::SetInstructions(const String& text)
-{
-    if ( label_ != NULL )
-        label_->SetText(text);
-}
 
 
 // If the user clicks the canvas, attempt to switch to relative mouse mode on web platform
 // If the user clicks the canvas, attempt to switch to relative mouse mode on web platform
 void Sample::HandleMouseModeRequest(StringHash eventType, VariantMap& eventData)
 void Sample::HandleMouseModeRequest(StringHash eventType, VariantMap& eventData)

+ 1 - 7
FeatureExamples/CPlusPlus/Source/Sample.h

@@ -26,14 +26,12 @@
 #include <Atomic/Core/Object.h>
 #include <Atomic/Core/Object.h>
 #include <Atomic/Core/StringUtils.h>
 #include <Atomic/Core/StringUtils.h>
 #include <Atomic/Input/Input.h>
 #include <Atomic/Input/Input.h>
-#include <Atomic/UI/UIEditField.h>
 
 
 namespace Atomic
 namespace Atomic
 {
 {
 
 
 class Node;
 class Node;
 class Scene;
 class Scene;
-class UIEditField;
 
 
 }
 }
 
 
@@ -76,8 +74,6 @@ protected:
 
 
     void SimpleCreateInstructions(const String& text = String::EMPTY);
     void SimpleCreateInstructions(const String& text = String::EMPTY);
 
 
-    void SetInstructions(const String& text = String::EMPTY);
-
     void BackToSelector();
     void BackToSelector();
 
 
     /// Logo sprite.
     /// Logo sprite.
@@ -94,9 +90,7 @@ protected:
     bool touchEnabled_;
     bool touchEnabled_;
     /// Mouse mode option to use in the sample.
     /// Mouse mode option to use in the sample.
     MouseMode useMouseMode_;
     MouseMode useMouseMode_;
-    /// for making the instructions writable
-    SharedPtr<UIEditField> label_;
-    
+
 private:
 private:
 
 
     /// Create logo.
     /// Create logo.

+ 0 - 41
FeatureExamples/CSharp/Resources/Components/Ragdoll.cs

@@ -42,8 +42,6 @@ namespace FeatureExamples
 
 
             if (otherBody.Mass > 0.0f)
             if (otherBody.Mass > 0.0f)
             {
             {
-                HitEffect (Node); // bam!
-
                 // We do not need the physics components in the AnimatedModel's root scene node anymore
                 // We do not need the physics components in the AnimatedModel's root scene node anymore
                 Node.RemoveComponent<RigidBody>();
                 Node.RemoveComponent<RigidBody>();
                 Node.RemoveComponent<CollisionShape>();
                 Node.RemoveComponent<CollisionShape>();
@@ -172,44 +170,5 @@ namespace FeatureExamples
             constraint.HighLimit = highLimit;
             constraint.HighLimit = highLimit;
             constraint.LowLimit = lowLimit;
             constraint.LowLimit = lowLimit;
         }
         }
-
-        void HitEffect ( Node parent ) // ragdoll gets the donuts blown out of him
-        {
-            Random rand = new Random();
-            var cache = GetSubsystem<ResourceCache>();
-            Scene myscene = parent.GetScene ();
-            Vector3 where = parent.GetWorldPosition ();
-    
-            for (int mm=0; mm<5; mm++)
-            {
-                Node xNode = myscene.CreateChild("Stuffing");
-                xNode.SetPosition( new Vector3( (float)rand.Next(0,1), (float)rand.Next(0,4), (float)rand.Next(0,15)) + where );
-                xNode.SetRotation( new Quaternion((float)rand.Next(0,360), 0, (float)rand.Next(0,360)));
-                xNode.SetScale(0.3f);
-
-                ParticleEmitter pEmitter = xNode.CreateComponent<ParticleEmitter>();
-................pEmitter.SetEffect(cache.GetResource<ParticleEffect>("Particle/Fire.xml"));
-................pEmitter.SetEnabled(true);  // sparkle donuts.
-
-                //create obj
-                StaticModel boxObject = xNode.CreateComponent<StaticModel>();
-                boxObject.Model = cache.Get<Model>("Models/Torus.mdl");
-                boxObject.SetMaterial(cache.Get<Material>("Materials/Mushroom.xml"));
-                boxObject.CastShadows = true;
-                RigidBody body = xNode.CreateComponent<RigidBody>();
-                body.Mass = 0.45f;
-                body.RollingFriction = 0.15f;
-                body.Friction = 0.75f;
-                body.UseGravity = true;
-                // Disable collision event signaling to reduce CPU load of the physics simulation a111
-                body.SetCollisionEventMode( CollisionEventMode.COLLISION_NEVER );
-                CollisionShape shape = xNode.CreateComponent<CollisionShape>();
-                shape.SetSphere(1.0f, Vector3.Zero, Quaternion.Identity );
-                float objectVelocity = 22.0f;
-                //Node.Rotation
-                body.SetLinearVelocity( new Quaternion((float)rand.Next(0,360), 0, (float)rand.Next(0,360))* new Vector3(0.0f, 0.02f, 1.0f) * objectVelocity);
-            }
-        }
-
     }
     }
 }
 }

+ 22 - 308
FeatureExamples/CSharp/Resources/Scripts/13_Ragdolls.cs

@@ -22,86 +22,28 @@
 // THE SOFTWARE.
 // THE SOFTWARE.
 //
 //
 
 
-using System.Collections.Generic;
 using AtomicEngine;
 using AtomicEngine;
 
 
 namespace FeatureExamples
 namespace FeatureExamples
 {
 {
     public class RagdollSample : Sample
     public class RagdollSample : Sample
     {
     {
-        Scene scene;     // perspective (3d) scene, you know, where the ragdolls are.
-        Camera camera;   // the regular camera
-        bool drawDebug;  // bool to turn on/off debug hud.
-
-        // the  2nd scene for the hud "overlay"
-        Scene hudScene;   // the hud scene
-        Camera hudCamera;  // ortho cam for the (pixel perfect) hud
-        Vector <Sprite2D> filler;  // for bargraph display
-
-        // more fun features...
-        List <float> bulletMass;   // how heavy the bullet is
-        List <float> bulletSpeed;  // how fast the bullet is
-        List <float> bulletSize;   // how big the bullet is
-        int massCount, speedCount, sizeCount; // counters
-
-        float bulletArc;    // shooting inclination
+        Scene scene;
+        bool drawDebug;
+        Camera camera;
 
 
         public RagdollSample() : base() { }
         public RagdollSample() : base() { }
 
 
         public override void Start()
         public override void Start()
         {
         {
-            massCount = 2;
-            speedCount = 2;
-            sizeCount = 2;
-
-            bulletMass = new List<float>();
-            bulletSpeed = new List<float>();
-            bulletSize = new List<float>();
-
-            filler = new Vector <Sprite2D>();
-
-            bulletMass.Add(1.0f);
-            bulletMass.Add(10.0f);
-            bulletMass.Add(50.0f);
-            bulletMass.Add(100.0f);
-            bulletMass.Add(300.0f);
-            bulletMass.Add(666.0f);
-            bulletMass.Add(1000.0f);
-            bulletSpeed.Add(10.0f);
-            bulletSpeed.Add(22.0f);
-            bulletSpeed.Add(41.0f);
-            bulletSpeed.Add(72.0f);
-            bulletSpeed.Add(116.0f);
-            bulletSpeed.Add(200.0f);
-            bulletSpeed.Add(450.0f);
-            bulletSize.Add(0.25f);
-            bulletSize.Add(0.5f);
-            bulletSize.Add(1.25f);
-            bulletSize.Add(3.25f);
-            bulletSize.Add(5.25f);
-            bulletSize.Add(7.25f);
-            bulletSize.Add(11.25f);
-            bulletSize.Add(16.25f);
-
-            bulletArc = 0.25f;
-
             base.Start();
             base.Start();
             CreateScene();
             CreateScene();
-            CreateHUD(); // add an overlay HUD that tells you settings
             SimpleCreateInstructionsWithWasd(
             SimpleCreateInstructionsWithWasd(
-                "LMB to spawn physics objects\n" +
-                "U=Mass, I=Speed, O=Size, R=Restart\n" +
-                "Space to toggle physics debug geometry\n");
+                "\nLMB to spawn physics objects\n" +
+                "F5 to save scene, F7 to load\n" +
+                "Space to toggle physics debug geometry");
             SetupViewport();
             SetupViewport();
             SubscribeToEvents();
             SubscribeToEvents();
-
-            RestartJacks ();
-
-            UpdateSpeedHud (speedCount);
-            UpdateMassHud (massCount);
-            UpdateSizeHud (sizeCount);
-
-            GetSubsystem<Input>().SetMouseVisible (false);
         }
         }
 
 
         void SubscribeToEvents()
         void SubscribeToEvents()
@@ -128,74 +70,23 @@ namespace FeatureExamples
                 SpawnObject();
                 SpawnObject();
 
 
             /* TODO: Scene.SaveXML/Scene.LoadXML
             /* TODO: Scene.SaveXML/Scene.LoadXML
+
             if (input.GetKeyPress(Constants.KEY_F5))
             if (input.GetKeyPress(Constants.KEY_F5))
                 scene.SaveXml(fileSystem.UserDocumentsDir + "/Scenes/Physics.xml");
                 scene.SaveXml(fileSystem.UserDocumentsDir + "/Scenes/Physics.xml");
+
             if (input.GetKeyPress(Constants.KEY_F7))
             if (input.GetKeyPress(Constants.KEY_F7))
                 scene.LoadXml(fileSystem.UserDocumentsDir + "/Scenes/Physics.xml");
                 scene.LoadXml(fileSystem.UserDocumentsDir + "/Scenes/Physics.xml");
-            */
-
-            if (input.GetKeyPress (Constants.KEY_U)) {
-                massCount++;
-                if ( massCount > 5 )
-                    massCount = 0;
-                UpdateMassHud (massCount);
-            }
 
 
-            if (input.GetKeyPress (Constants.KEY_I)) {
-                speedCount++;
-                if ( speedCount> 5 )
-                    speedCount = 0;
-                UpdateSpeedHud (speedCount);
-            }
-
-            if (input.GetKeyPress (Constants.KEY_O)) {
-                sizeCount++;
-                if ( sizeCount > 5 )
-                    sizeCount = 0;
-                UpdateSizeHud (sizeCount);
-            }
-
-            if (input.GetKeyPress (Constants.KEY_P)) {
-                if ( bulletArc == 0.0 )
-                    bulletArc = 0.25f;
-                else if ( bulletArc > 0.0 )
-                    bulletArc = 0.0f;
-            }
-
-            if (input.GetKeyPress (Constants.KEY_R)) {
-                RestartJacks ();
-            }
+            */
 
 
             if (input.GetKeyPress(Constants.KEY_SPACE))
             if (input.GetKeyPress(Constants.KEY_SPACE))
                 drawDebug = !drawDebug;
                 drawDebug = !drawDebug;
-
-            UpdateFps ();
-            CleanUpSome ();
-        }
-
-        void UpdateFps ()
-        {
-            var eng = GetSubsystem<Engine>();
-            string mystr = "FPS: " + eng.GetFps ().ToString ();
-            mystr += "\nUse WASD keys and mouse/touch to move\n"
-                + "LMB to spawn physics objects\n" 
-                + "U=Mass, I=Speed, O=Size, R=Restart\n" 
-                + "Space to toggle physics debug geometry";
-            SetInstructions ( mystr );
         }
         }
 
 
         void SetupViewport()
         void SetupViewport()
         {
         {
             var renderer = GetSubsystem<Renderer>();
             var renderer = GetSubsystem<Renderer>();
-            var cache = GetSubsystem<ResourceCache>();
-
-            renderer.SetNumViewports(2);  // use 2 viewports, 1 for 3d and 1 for the 2d hud
-            var viewport2_ = new Viewport(hudScene, hudCamera );  // hud orthographic viewport, scene and camera
-            var overlayRenderPath = new RenderPath(); 
-            overlayRenderPath.Load(cache.GetResource<XMLFile>("PostProcess/FrontPath.xml"));  //special renderpath that does not clear
-            viewport2_.SetRenderPath(overlayRenderPath);  // apply to hud viewport, so the background is transparent
-            renderer.SetViewport(0, new Viewport(scene, camera)); // perspective viewport, scene and camera
-            renderer.SetViewport(1, viewport2_);  // and add in the HUD viewport
+            renderer.SetViewport(0, new Viewport(scene, CameraNode.GetComponent<Camera>()));
         }
         }
 
 
         void CreateScene()
         void CreateScene()
@@ -250,37 +141,7 @@ namespace FeatureExamples
                 shape.SetBox(Vector3.One, Vector3.Zero, Quaternion.Identity);
                 shape.SetBox(Vector3.One, Vector3.Zero, Quaternion.Identity);
             }
             }
 
 
-            // Create the camera. Limit far clip distance to match the fog
-            CameraNode = new Node();
-            CameraNode.SetName("Camera");
-            camera = CameraNode.CreateComponent<Camera>();
-            camera.FarClip = 300.0f;
-            // Set an initial position for the camera scene node above the plane
-            CameraNode.Position = new Vector3(0.0f, 3.0f, -20.0f);
-        }
-
-        void RestartJacks()
-        {
-            var ll = new Vector <Node>();  //get rid of some old objects
-            scene.GetChildrenWithName ( ll, "Sphere", true); 
-            for ( int ii=0; ii<ll.Size; ii++ ) { 
-                ll[ii].Remove ();
-            }
-
-            var nn = new Vector <Node>();
-            scene.GetChildrenWithName ( nn, "Stuffing", true);
-            for ( int ii=0; ii<nn.Size; ii++ ) { 
-                nn[ii].Remove ();
-            }
-
-            var mm = new Vector <Node>();
-            scene.GetChildrenWithName ( mm, "Jack", true); 
-            for ( int ii=0; ii<mm.Size; ii++ ) { 
-                    mm[ii].Remove ();
-                }
-
-            // Create animated models, you dont know ... jack
-            var cache = GetSubsystem<ResourceCache>();
+            // Create animated models
             for (int z = -1; z <= 1; ++z)
             for (int z = -1; z <= 1; ++z)
             {
             {
                 for (int x = -4; x <= 4; ++x)
                 for (int x = -4; x <= 4; ++x)
@@ -311,146 +172,13 @@ namespace FeatureExamples
                     modelNode.AddComponent(new Ragdoll());
                     modelNode.AddComponent(new Ragdoll());
                 }
                 }
             }
             }
-        }
-
-        void CreateHUD()
-        {
-            float hscal = 0.4f;
-            //
-            // create a 2nd viewport and scene for a hud with sprites.
-            //
-            hudScene = new Scene();
-            hudScene.CreateComponent<Octree>();
-            // Create camera node
-            var hudCam = hudScene.CreateChild("HudCamera");
-            // Set camera's position
-            hudCam.SetPosition(new Vector3(0.0f, 0.0f, -10.0f));
-            hudCamera = hudCam.CreateComponent<Camera>();
-            hudCamera.SetOrthographic(true);
-            var graphics = GetSubsystem<Graphics>();
-            hudCamera.SetOrthoSize ((float)graphics.GetHeight () * PixelSize ); //PIXEL_SIZE
-
-            var cache = GetSubsystem<ResourceCache>();
-
-            // add a crosshair in the center of the screen
-            var sprite = cache.GetResource<Sprite2D>("Textures/NinjaSnowWar/Sight.png");
-            var targetSprite_ = hudScene.CreateChild("targetSprite");
-            targetSprite_.SetPosition2D(new Vector2(0,0));
-            targetSprite_.SetScale2D( new Vector2(0.75f, 0.75f));
-            var staticSprite = targetSprite_.CreateComponent<StaticSprite2D>();
-            staticSprite.SetSprite(sprite);   // Set sprite
-            staticSprite.SetBlendMode( AtomicEngine.BlendMode.BLEND_ALPHA ); // Set blend mode
-            staticSprite.SetAlpha(0.3f);  
 
 
-            // borrow the spinning coin from the 2DSprite example to show what the possibilities are
-            float halfWidth = graphics.Width * 0.5f * PixelSize;
-            float halfHeight = graphics.Height * 0.5f * PixelSize;
-            // Get animation set
-            AnimationSet2D animationSet = cache.Get<AnimationSet2D>("Urho2D/GoldIcon.scml");
-            if (animationSet == null) return;
-            var spriteNode2 = hudScene.CreateChild("AnimatedSprite2D");
-            AnimatedSprite2D animatedSprite = spriteNode2.CreateComponent<AnimatedSprite2D>();
-            animatedSprite.AnimationSet = animationSet;         // Set animation
-            animatedSprite.SetAnimation("idle", LoopMode2D.LM_DEFAULT);
-            spriteNode2.SetPosition2D(new Vector2(halfWidth - 0.4f, halfHeight - 0.4f));
-
-            // (bullet) mass, speed size feature huds
-            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill1.png") );
-            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill2.png") );
-            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill3.png") );
-            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill4.png") );
-            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill5.png") );
-            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill6.png") );
-
-            Sprite2D spritem = cache.GetResource<Sprite2D>("Textures/hudmass.png");
-            Node hudm = hudScene.CreateChild("hudMass");
-            hudm.SetScale2D(new Vector2(hscal,hscal));
-            hudm.SetPosition2D( new Vector2( 0f - (halfWidth/3.0f), halfHeight - 0.4f)); 
-            StaticSprite2D hudSpritem = hudm.CreateComponent<StaticSprite2D>();
-            hudSpritem.SetSprite(spritem);
-            hudSpritem.SetAlpha(0.9f);
-            hudSpritem.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
-            hudSpritem.SetOrderInLayer(3); 
-            Node hudfm = hudm.CreateChild("hudMassFill");
-            hudfm.SetScale2D(new Vector2(1f,1f));
-            hudfm.SetPosition2D( new Vector2( 0f, 0f)); 
-            StaticSprite2D hudSpritefm = hudfm.CreateComponent<StaticSprite2D>();
-            hudSpritefm.SetSprite(filler[0]);
-            hudSpritefm.SetAlpha(0.9f);
-            hudSpritefm.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
-            hudSpritefm.SetOrderInLayer(-3); 
-
-            Sprite2D sprites = cache.GetResource<Sprite2D>("Textures/hudspeed.png");
-            Node huds = hudScene.CreateChild("hudSpeed");
-            huds.SetScale2D(new Vector2(hscal,hscal));
-            huds.SetPosition2D( new Vector2( 0f, halfHeight - 0.4f)); 
-            StaticSprite2D hudSprites = huds.CreateComponent<StaticSprite2D>();
-            hudSprites.SetSprite(sprites);
-            hudSprites.SetAlpha(0.9f);
-            hudSprites.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
-            hudSprites.SetOrderInLayer(3); 
-            Node hudsm = huds.CreateChild("hudSpeedFill");
-            hudsm.SetScale2D(new Vector2(1f,1f));
-            hudsm.SetPosition2D( new Vector2( 0f, 0f)); 
-            StaticSprite2D hudSpritesm = hudsm.CreateComponent<StaticSprite2D>();
-            hudSpritesm.SetSprite(filler[0]);
-            hudSpritesm.SetAlpha(0.9f);
-            hudSpritesm.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
-            hudSpritesm.SetOrderInLayer(-3); 
-
-            Sprite2D spritez = cache.GetResource<Sprite2D>("Textures/hudsize.png");
-            Node hudz = hudScene.CreateChild("hudSize");
-            hudz.SetScale2D(new Vector2(hscal,hscal));
-            hudz.SetPosition2D( new Vector2( 0f + (halfWidth/3.0f), halfHeight - 0.4f)); 
-            StaticSprite2D hudSpritez = hudz.CreateComponent<StaticSprite2D>();
-            hudSpritez.SetSprite(spritez);
-            hudSpritez.SetAlpha(0.9f);
-            hudSpritez.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
-            hudSpritez.SetOrderInLayer(3); 
-            Node hudzm = hudz.CreateChild("hudSizeFill");
-            hudzm.SetScale2D(new Vector2(1f,1f));
-            hudzm.SetPosition2D( new Vector2( 0f, 0f)); 
-            StaticSprite2D hudSpritezm = hudzm.CreateComponent<StaticSprite2D>();
-            hudSpritezm.SetSprite(filler[0]);
-            hudSpritezm.SetAlpha(0.9f);
-            hudSpritezm.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
-            hudSpritezm.SetOrderInLayer(-3);
-        }
-
-        void UpdateMassHud ( int value )
-        {
-            Node xNode = hudScene.GetChild("hudMass", true);
-            if (xNode != null) {
-                Node fillx = xNode.GetChild("hudMassFill");
-                if (fillx != null) {
-                    StaticSprite2D hudSprite = fillx.GetComponent<StaticSprite2D>();
-                    hudSprite.SetSprite(filler[value]);
-                }
-            }
-        }
-
-        void UpdateSpeedHud ( int value )
-        {
-            Node xNode = hudScene.GetChild("hudSpeed", true);
-            if (xNode != null) {
-                Node fillx = xNode.GetChild("hudSpeedFill");
-                if (fillx != null) {
-                    StaticSprite2D hudSprite = fillx.GetComponent<StaticSprite2D>();
-                    hudSprite.SetSprite(filler[value]);
-                }
-            }
-        }
-
-        void UpdateSizeHud ( int value )
-        {
-            Node xNode = hudScene.GetChild("hudSize", true);
-            if (xNode != null) {
-                Node fillx = xNode.GetChild("hudSizeFill");
-                if (fillx != null) {
-                    StaticSprite2D hudSprite = fillx.GetComponent<StaticSprite2D>();
-                    hudSprite.SetSprite(filler[value]);
-                }
-            }
+            // Create the camera. Limit far clip distance to match the fog
+            CameraNode = new Node();
+            camera = CameraNode.CreateComponent<Camera>();
+            camera.FarClip = 300.0f;
+            // Set an initial position for the camera scene node above the plane
+            CameraNode.Position = new Vector3(0.0f, 3.0f, -20.0f);
         }
         }
 
 
         void SpawnObject()
         void SpawnObject()
@@ -460,39 +188,25 @@ namespace FeatureExamples
             Node boxNode = scene.CreateChild("Sphere");
             Node boxNode = scene.CreateChild("Sphere");
             boxNode.Position = CameraNode.Position;
             boxNode.Position = CameraNode.Position;
             boxNode.Rotation = CameraNode.Rotation;
             boxNode.Rotation = CameraNode.Rotation;
-            boxNode.SetScale(bulletSize[sizeCount]);
+            boxNode.SetScale(0.25f);
             StaticModel boxObject = boxNode.CreateComponent<StaticModel>();
             StaticModel boxObject = boxNode.CreateComponent<StaticModel>();
             boxObject.Model = cache.Get<Model>("Models/Sphere.mdl");
             boxObject.Model = cache.Get<Model>("Models/Sphere.mdl");
             boxObject.SetMaterial(cache.Get<Material>("Materials/StoneSmall.xml"));
             boxObject.SetMaterial(cache.Get<Material>("Materials/StoneSmall.xml"));
             boxObject.CastShadows = true;
             boxObject.CastShadows = true;
 
 
             RigidBody body = boxNode.CreateComponent<RigidBody>();
             RigidBody body = boxNode.CreateComponent<RigidBody>();
-            body.Mass = bulletMass[massCount];
+            body.Mass = 1.0f;
             body.RollingFriction = 0.15f;
             body.RollingFriction = 0.15f;
             CollisionShape shape = boxNode.CreateComponent<CollisionShape>();
             CollisionShape shape = boxNode.CreateComponent<CollisionShape>();
             shape.SetSphere(1.0f, Vector3.Zero, Quaternion.Identity);
             shape.SetSphere(1.0f, Vector3.Zero, Quaternion.Identity);
 
 
-            float objectVelocity = bulletSpeed[speedCount];
+            const float objectVelocity = 10.0f;
 
 
             // Set initial velocity for the RigidBody based on camera forward vector. Add also a slight up component
             // Set initial velocity for the RigidBody based on camera forward vector. Add also a slight up component
             // to overcome gravity better
             // to overcome gravity better
-            body.SetLinearVelocity(CameraNode.Rotation * new Vector3(0.0f, bulletArc, 1.0f) * objectVelocity);
+            body.SetLinearVelocity(CameraNode.Rotation * new Vector3(0.0f, 0.25f, 1.0f) * objectVelocity);
         }
         }
 
 
-        void CleanUpSome() // destroy the bullets when they get far enough away
-        {
-            Node cam = CameraNode; // note - the camera isnt in the scene
-            if ( cam == null )
-                return;
-            var mm = new Vector <Node>();
-            scene.GetChildrenWithName ( mm, "Sphere", true);
-            for ( int ii=0; ii<mm.Size; ii++ ) { 
-              float dist = ( mm[ii].GetWorldPosition() - cam.GetWorldPosition() ).Length;
-                if (dist > 270.0f) {
-                    mm[ii].Remove ();
-                }
-            }
-        }
+        
     }
     }
-
 }
 }

+ 1 - 8
FeatureExamples/CSharp/Resources/Scripts/Sample.cs

@@ -35,7 +35,6 @@ namespace FeatureExamples
         protected float Pitch { get; set; }
         protected float Pitch { get; set; }
         protected bool TouchEnabled { get; set; }
         protected bool TouchEnabled { get; set; }
         protected Node CameraNode { get; set; }
         protected Node CameraNode { get; set; }
-        protected UIEditField label { get; set; }
 
 
         protected UIView UIView { get; set; }
         protected UIView UIView { get; set; }
 
 
@@ -172,7 +171,7 @@ namespace FeatureExamples
             fontDesc.Id = "Vera";
             fontDesc.Id = "Vera";
             fontDesc.Size = 18;
             fontDesc.Size = 18;
 
 
-            label = new UIEditField();
+            var label = new UIEditField();
             label.FontDescription = fontDesc;
             label.FontDescription = fontDesc;
             label.ReadOnly = true;
             label.ReadOnly = true;
             label.Multiline = true;
             label.Multiline = true;
@@ -184,12 +183,6 @@ namespace FeatureExamples
 
 
         }
         }
 
 
-        public void SetInstructions(string text = "")
-        {
-            if ( label != null )
-                label.Text = text;
-        }
-
         void CreateLogo()
         void CreateLogo()
         {
         {
         }
         }

+ 0 - 0
FeatureExamples/CPlusPlus/Data/NinjaSnowWar/Sight.png → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/NinjaSnowWar/Sight.png


+ 0 - 0
FeatureExamples/CPlusPlus/Data/PostProcess/FrontPath.xml → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/PostProcess/FrontPath.xml


+ 0 - 0
FeatureExamples/CPlusPlus/Data/hudfill1.png → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill1.png


+ 0 - 0
FeatureExamples/CPlusPlus/Data/hudfill2.png → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill2.png


+ 0 - 0
FeatureExamples/CPlusPlus/Data/hudfill3.png → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill3.png


+ 0 - 0
FeatureExamples/CPlusPlus/Data/hudfill4.png → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill4.png


+ 0 - 0
FeatureExamples/CPlusPlus/Data/hudfill5.png → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill5.png


+ 0 - 0
FeatureExamples/CPlusPlus/Data/hudfill6.png → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudfill6.png


+ 0 - 0
FeatureExamples/CPlusPlus/Data/hudmass.png → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudmass.png


+ 0 - 0
FeatureExamples/CPlusPlus/Data/hudsize.png → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudsize.png


+ 0 - 0
FeatureExamples/CPlusPlus/Data/hudspeed.png → FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Data/hudspeed.png


+ 219 - 0
FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/CreateRagdoll.cpp

@@ -0,0 +1,219 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+// Copyright (c) 2014-2016, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include <Atomic/Graphics/AnimatedModel.h>
+#include <Atomic/IO/Log.h>
+#include <Atomic/Physics/PhysicsEvents.h>
+#include <Atomic/Physics/RigidBody.h>
+#include <Atomic/Scene/Scene.h>
+#include <Atomic/Resource/ResourceCache.h>
+#include <Atomic/Graphics/Material.h>
+#include <Atomic/Graphics/ParticleEmitter.h>
+#include <Atomic/Graphics/ParticleEffect.h>
+
+#include "CreateRagdoll.h"
+
+#include <Atomic/DebugNew.h>
+
+CreateRagdoll::CreateRagdoll(Context* context) :
+    Component(context)
+{
+}
+
+void CreateRagdoll::OnNodeSet(Node* node)
+{
+    // If the node pointer is non-null, this component has been created into a scene node. Subscribe to physics collisions that
+    // concern this scene node
+    if (node)
+        SubscribeToEvent(node, E_NODECOLLISION, ATOMIC_HANDLER(CreateRagdoll, HandleNodeCollision));
+}
+
+void CreateRagdoll::HandleNodeCollision(StringHash eventType, VariantMap& eventData)
+{
+    using namespace NodeCollision;
+
+    // Get the other colliding body, make sure it is moving (has nonzero mass)
+    RigidBody* otherBody = static_cast<RigidBody*>(eventData[P_OTHERBODY].GetPtr());
+
+    if (otherBody->GetMass() > 0.0f)
+    {
+        HitEffect (node_); // bam!
+
+       // We do not need the physics components in the AnimatedModel's root scene node anymore
+        node_->RemoveComponent<RigidBody>();
+        node_->RemoveComponent<CollisionShape>();
+
+        // Create RigidBody & CollisionShape components to bones
+        CreateRagdollBone("Bip01_Pelvis", SHAPE_BOX, Vector3(0.3f, 0.2f, 0.25f), Vector3(0.0f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 0.0f));
+        CreateRagdollBone("Bip01_Spine1", SHAPE_BOX, Vector3(0.35f, 0.2f, 0.3f), Vector3(0.15f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 0.0f));
+        CreateRagdollBone("Bip01_L_Thigh", SHAPE_CAPSULE, Vector3(0.175f, 0.45f, 0.175f), Vector3(0.25f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 90.0f));
+        CreateRagdollBone("Bip01_R_Thigh", SHAPE_CAPSULE, Vector3(0.175f, 0.45f, 0.175f), Vector3(0.25f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 90.0f));
+        CreateRagdollBone("Bip01_L_Calf", SHAPE_CAPSULE, Vector3(0.15f, 0.55f, 0.15f), Vector3(0.25f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 90.0f));
+        CreateRagdollBone("Bip01_R_Calf", SHAPE_CAPSULE, Vector3(0.15f, 0.55f, 0.15f), Vector3(0.25f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 90.0f));
+        CreateRagdollBone("Bip01_Head", SHAPE_BOX, Vector3(0.2f, 0.2f, 0.2f), Vector3(0.1f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 0.0f));
+        CreateRagdollBone("Bip01_L_UpperArm", SHAPE_CAPSULE, Vector3(0.15f, 0.35f, 0.15f), Vector3(0.1f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 90.0f));
+        CreateRagdollBone("Bip01_R_UpperArm", SHAPE_CAPSULE, Vector3(0.15f, 0.35f, 0.15f), Vector3(0.1f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 90.0f));
+        CreateRagdollBone("Bip01_L_Forearm", SHAPE_CAPSULE, Vector3(0.125f, 0.4f, 0.125f), Vector3(0.2f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 90.0f));
+        CreateRagdollBone("Bip01_R_Forearm", SHAPE_CAPSULE, Vector3(0.125f, 0.4f, 0.125f), Vector3(0.2f, 0.0f, 0.0f),
+            Quaternion(0.0f, 0.0f, 90.0f));
+
+        // Create Constraints between bones
+        CreateRagdollConstraint("Bip01_L_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3::BACK, Vector3::FORWARD,
+            Vector2(45.0f, 45.0f), Vector2::ZERO);
+        CreateRagdollConstraint("Bip01_R_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3::BACK, Vector3::FORWARD,
+            Vector2(45.0f, 45.0f), Vector2::ZERO);
+        CreateRagdollConstraint("Bip01_L_Calf", "Bip01_L_Thigh", CONSTRAINT_HINGE, Vector3::BACK, Vector3::BACK,
+            Vector2(90.0f, 0.0f), Vector2::ZERO);
+        CreateRagdollConstraint("Bip01_R_Calf", "Bip01_R_Thigh", CONSTRAINT_HINGE, Vector3::BACK, Vector3::BACK,
+            Vector2(90.0f, 0.0f), Vector2::ZERO);
+        CreateRagdollConstraint("Bip01_Spine1", "Bip01_Pelvis", CONSTRAINT_HINGE, Vector3::FORWARD, Vector3::FORWARD,
+            Vector2(45.0f, 0.0f), Vector2(-10.0f, 0.0f));
+        CreateRagdollConstraint("Bip01_Head", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3::LEFT, Vector3::LEFT,
+            Vector2(0.0f, 30.0f), Vector2::ZERO);
+        CreateRagdollConstraint("Bip01_L_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3::DOWN, Vector3::UP,
+            Vector2(45.0f, 45.0f), Vector2::ZERO, false);
+        CreateRagdollConstraint("Bip01_R_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3::DOWN, Vector3::UP,
+            Vector2(45.0f, 45.0f), Vector2::ZERO, false);
+        CreateRagdollConstraint("Bip01_L_Forearm", "Bip01_L_UpperArm", CONSTRAINT_HINGE, Vector3::BACK, Vector3::BACK,
+            Vector2(90.0f, 0.0f), Vector2::ZERO);
+        CreateRagdollConstraint("Bip01_R_Forearm", "Bip01_R_UpperArm", CONSTRAINT_HINGE, Vector3::BACK, Vector3::BACK,
+            Vector2(90.0f, 0.0f), Vector2::ZERO);
+
+        // Disable keyframe animation from all bones so that they will not interfere with the ragdoll
+        AnimatedModel* model = GetComponent<AnimatedModel>();
+        Skeleton& skeleton = model->GetSkeleton();
+        for (unsigned i = 0; i < skeleton.GetNumBones(); ++i)
+            skeleton.GetBone(i)->animated_ = false;
+
+        // Finally remove self from the scene node. Note that this must be the last operation performed in the function
+        Remove();
+    }
+}
+
+void CreateRagdoll::CreateRagdollBone(const String& boneName, ShapeType type, const Vector3& size, const Vector3& position,
+    const Quaternion& rotation)
+{
+    // Find the correct child scene node recursively
+    Node* boneNode = node_->GetChild(boneName, true);
+    if (!boneNode)
+    {
+        ATOMIC_LOGWARNING("Could not find bone " + boneName + " for creating ragdoll physics components");
+        return;
+    }
+
+    RigidBody* body = boneNode->CreateComponent<RigidBody>();
+    // Set mass to make movable
+    body->SetMass(1.0f);
+    // Set damping parameters to smooth out the motion
+    body->SetLinearDamping(0.05f);
+    body->SetAngularDamping(0.85f);
+    // Set rest thresholds to ensure the ragdoll rigid bodies come to rest to not consume CPU endlessly
+    body->SetLinearRestThreshold(1.5f);
+    body->SetAngularRestThreshold(2.5f);
+
+    CollisionShape* shape = boneNode->CreateComponent<CollisionShape>();
+    // We use either a box or a capsule shape for all of the bones
+    if (type == SHAPE_BOX)
+        shape->SetBox(size, position, rotation);
+    else
+        shape->SetCapsule(size.x_, size.y_, position, rotation);
+}
+
+void CreateRagdoll::CreateRagdollConstraint(const String& boneName, const String& parentName, ConstraintType type,
+    const Vector3& axis, const Vector3& parentAxis, const Vector2& highLimit, const Vector2& lowLimit,
+    bool disableCollision)
+{
+    Node* boneNode = node_->GetChild(boneName, true);
+    Node* parentNode = node_->GetChild(parentName, true);
+    if (!boneNode)
+    {
+        ATOMIC_LOGWARNING("Could not find bone " + boneName + " for creating ragdoll constraint");
+        return;
+    }
+    if (!parentNode)
+    {
+        ATOMIC_LOGWARNING("Could not find bone " + parentName + " for creating ragdoll constraint");
+        return;
+    }
+
+    Constraint* constraint = boneNode->CreateComponent<Constraint>();
+    constraint->SetConstraintType(type);
+    // Most of the constraints in the ragdoll will work better when the connected bodies don't collide against each other
+    constraint->SetDisableCollision(disableCollision);
+    // The connected body must be specified before setting the world position
+    constraint->SetOtherBody(parentNode->GetComponent<RigidBody>());
+    // Position the constraint at the child bone we are connecting
+    constraint->SetWorldPosition(boneNode->GetWorldPosition());
+    // Configure axes and limits
+    constraint->SetAxis(axis);
+    constraint->SetOtherAxis(parentAxis);
+    constraint->SetHighLimit(highLimit);
+    constraint->SetLowLimit(lowLimit);
+}
+
+void CreateRagdoll::HitEffect ( Node* parent ) // ragdoll gets the donuts blown out of him
+{
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    Scene* myscene = parent->GetScene ();
+    Vector3 where = parent->GetWorldPosition ();
+    
+    for (int mm=0; mm<5; mm++)
+    {
+        Node* xNode = myscene->CreateChild("Stuffing");
+        xNode->SetPosition( Vector3( Random(1), Random(4), Random(15)) + where );
+        xNode->SetRotation( Quaternion(Random(360), 0, Random(360)));
+        xNode->SetScale(0.3f);
+
+        ParticleEmitter* pEmitter = xNode->CreateComponent<ParticleEmitter>();
+        pEmitter->SetEffect(cache->GetResource<ParticleEffect>("Particle/Fire.xml"));
+        pEmitter->SetEnabled(true);  // sparkle donuts
+
+        //create obj
+        StaticModel* boxObject = xNode->CreateComponent<StaticModel>();
+        boxObject->SetModel(cache->GetResource<Model>("Models/Torus.mdl"));
+        boxObject->SetMaterial(cache->GetResource<Material>("Materials/Mushroom.xml"));
+        boxObject->SetCastShadows(true);
+        RigidBody* body = xNode->CreateComponent<RigidBody>();
+        body->SetMass( 0.45f);
+        body->SetRollingFriction(0.15f);
+        body->SetFriction( 0.75f);
+        body->SetUseGravity (true);
+        // Disable collision event signaling to reduce CPU load of the physics simulation a111
+        body->SetCollisionEventMode( COLLISION_NEVER );
+        CollisionShape* shape = xNode->CreateComponent<CollisionShape>();
+        shape->SetSphere(1.0f, Vector3(0,0,0), Quaternion(1,0,0,0));
+        float objectVelocity = 22.0f;
+        //Node.Rotation
+        body->SetLinearVelocity( Quaternion(Random(360), 0, Random(360))* Vector3(0.0f, 0.02f, 1.0f) * objectVelocity);
+    }
+}

+ 52 - 0
FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/CreateRagdoll.h

@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+// Copyright (c) 2014-2016, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include <Atomic/Physics/CollisionShape.h>
+#include <Atomic/Physics/Constraint.h>
+
+using namespace Atomic;
+
+/// Custom component that creates a ragdoll upon collision.
+class CreateRagdoll : public Component
+{
+    ATOMIC_OBJECT(CreateRagdoll, Component)
+    
+public:
+    /// Construct.
+    CreateRagdoll(Context* context);
+    
+protected:
+    /// Handle node being assigned.
+    virtual void OnNodeSet(Node* node);
+    void HitEffect ( Node* parent ); // ragdoll gets the donuts blown out of him
+    
+private:
+    /// Handle scene node's physics collision.
+    void HandleNodeCollision(StringHash eventType, VariantMap& eventData);
+    /// Make a bone physical by adding RigidBody and CollisionShape components.
+    void CreateRagdollBone(const String& boneName, ShapeType type, const Vector3& size, const Vector3& position, const Quaternion& rotation);
+    /// Join two bones with a Constraint component.
+    void CreateRagdollConstraint(const String& boneName, const String& parentName, ConstraintType type, const Vector3& axis, const Vector3& parentAxis, const Vector2& highLimit, const Vector2& lowLimit, bool disableCollision = true);
+};

+ 568 - 0
FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/Ragdolls.cpp

@@ -0,0 +1,568 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+// Copyright (c) 2014-2016, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include <Atomic/Core/CoreEvents.h>
+#include <Atomic/Engine/Engine.h>
+#include <Atomic/Graphics/AnimatedModel.h>
+#include <Atomic/Graphics/Camera.h>
+#include <Atomic/Graphics/DebugRenderer.h>
+#include <Atomic/Graphics/Graphics.h>
+#include <Atomic/Graphics/Light.h>
+#include <Atomic/Graphics/Material.h>
+#include <Atomic/Graphics/Octree.h>
+#include <Atomic/Graphics/Renderer.h>
+#include <Atomic/Graphics/Zone.h>
+#include <Atomic/Input/Input.h>
+#include <Atomic/IO/File.h>
+#include <Atomic/IO/FileSystem.h>
+#include <Atomic/Physics/CollisionShape.h>
+#include <Atomic/Physics/PhysicsWorld.h>
+#include <Atomic/Physics/RigidBody.h>
+#include <Atomic/Resource/ResourceCache.h>
+#include <Atomic/Scene/Scene.h>
+#include <Atomic/UI/UI.h>
+#include <Atomic/Atomic2D/StaticSprite2D.h>
+#include <Atomic/Atomic2D/AnimationSet2D.h>
+#include <Atomic/Atomic2D/AnimatedSprite2D.h>
+#include <Atomic/Atomic2D/Sprite2D.h>
+#include <Atomic/Graphics/RenderPath.h>
+#include <Atomic/Resource/XMLFile.h>
+
+#include "CreateRagdoll.h"
+#include "Ragdolls.h"
+
+#include <Atomic/DebugNew.h>
+
+Ragdolls::Ragdolls(Context* context) :
+    Sample(context),
+    drawDebug_(false)
+{
+    // Register an object factory for our custom CreateRagdoll component so that we can create them to scene nodes
+    context->RegisterFactory<CreateRagdoll>();
+    
+    massCount = 2;
+    speedCount = 2;
+    sizeCount = 2;
+
+    bulletMass.Push(1.0f);
+    bulletMass.Push(10.0f);
+    bulletMass.Push(50.0f);
+    bulletMass.Push(100.0f);
+    bulletMass.Push(300.0f);
+    bulletMass.Push(666.0f);
+    bulletMass.Push(1000.0f);
+    bulletSpeed.Push(10.0f);
+    bulletSpeed.Push(22.0f);
+    bulletSpeed.Push(41.0f);
+    bulletSpeed.Push(72.0f);
+    bulletSpeed.Push(116.0f);
+    bulletSpeed.Push(200.0f);
+    bulletSpeed.Push(450.0f);
+    bulletSize.Push(0.25f);
+    bulletSize.Push(0.5f);
+    bulletSize.Push(1.25f);
+    bulletSize.Push(3.25f);
+    bulletSize.Push(5.25f);
+    bulletSize.Push(7.25f);
+    bulletSize.Push(11.25f);
+    bulletSize.Push(16.25f);
+
+    bulletArc = 0.25f;
+
+}
+
+void Ragdolls::Start()
+{
+    // Execute base class startup
+    Sample::Start();
+
+    // Create the scene content
+    CreateScene();
+
+    // add an overlay HUD that tells you settings
+    CreateHUD();
+
+    // Create the UI content
+    CreateInstructions();
+
+    // Setup the viewport for displaying the scene
+    SetupViewport();
+
+    // Hook up to the frame update and render post-update events
+    SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_ABSOLUTE);
+    
+    RestartJacks ();
+
+    UpdateSpeedHud (speedCount);
+    UpdateMassHud (massCount);
+    UpdateSizeHud (sizeCount);
+
+    GetSubsystem<Input>()->SetMouseVisible (false);
+
+}
+
+void Ragdolls::CreateScene()
+{
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+
+    scene_ = new Scene(context_);
+
+    // Create octree, use default volume (-1000, -1000, -1000) to (1000, 1000, 1000)
+    // Create a physics simulation world with default parameters, which will update at 60fps. Like the Octree must
+    // exist before creating drawable components, the PhysicsWorld must exist before creating physics components.
+    // Finally, create a DebugRenderer component so that we can draw physics debug geometry
+    scene_->CreateComponent<Octree>();
+    scene_->CreateComponent<PhysicsWorld>();
+    scene_->CreateComponent<DebugRenderer>();
+
+    // Create a Zone component for ambient lighting & fog control
+    Node* zoneNode = scene_->CreateChild("Zone");
+    Zone* zone = zoneNode->CreateComponent<Zone>();
+    zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f));
+    zone->SetAmbientColor(Color(0.15f, 0.15f, 0.15f));
+    zone->SetFogColor(Color(0.5f, 0.5f, 0.7f));
+    zone->SetFogStart(100.0f);
+    zone->SetFogEnd(300.0f);
+
+    // Create a directional light to the world. Enable cascaded shadows on it
+    Node* lightNode = scene_->CreateChild("DirectionalLight");
+    lightNode->SetDirection(Vector3(0.6f, -1.0f, 0.8f));
+    Light* light = lightNode->CreateComponent<Light>();
+    light->SetLightType(LIGHT_DIRECTIONAL);
+    light->SetCastShadows(true);
+    light->SetShadowBias(BiasParameters(0.00025f, 0.5f));
+    // Set cascade splits at 10, 50 and 200 world units, fade shadows out at 80% of maximum shadow distance
+    light->SetShadowCascade(CascadeParameters(10.0f, 50.0f, 200.0f, 0.0f, 0.8f));
+
+    // Create a floor object, 500 x 500 world units. Adjust position so that the ground is at zero Y
+    Node* floorNode = scene_->CreateChild("Floor");
+    floorNode->SetPosition(Vector3(0.0f, -0.5f, 0.0f));
+    floorNode->SetScale(Vector3(500.0f, 1.0f, 500.0f));
+    StaticModel* floorObject = floorNode->CreateComponent<StaticModel>();
+    floorObject->SetModel(cache->GetResource<Model>("Models/Box.mdl"));
+    floorObject->SetMaterial(cache->GetResource<Material>("Materials/StoneTiled.xml"));
+
+    // Make the floor physical by adding RigidBody and CollisionShape components
+    RigidBody* body = floorNode->CreateComponent<RigidBody>();
+    // We will be spawning spherical objects in this sample. The ground also needs non-zero rolling friction so that
+    // the spheres will eventually come to rest
+    body->SetRollingFriction(0.15f);
+    CollisionShape* shape = floorNode->CreateComponent<CollisionShape>();
+    // Set a box shape of size 1 x 1 x 1 for collision. The shape will be scaled with the scene node scale, so the
+    // rendering and physics representation sizes should match (the box model is also 1 x 1 x 1.)
+    shape->SetBox(Vector3::ONE);
+
+    // Create the camera. Limit far clip distance to match the fog. Note: now we actually create the camera node outside
+    // the scene, because we want it to be unaffected by scene load / save
+    cameraNode_ = new Node(context_);
+    Camera* camera = cameraNode_->CreateComponent<Camera>();
+    camera->SetFarClip(300.0f);
+
+    // Set an initial position for the camera scene node above the floor
+    cameraNode_->SetPosition(Vector3(0.0f, 3.0f, -20.0f));
+}
+
+void Ragdolls::CreateInstructions()
+{
+    SimpleCreateInstructions (
+        "Use WASD keys and mouse/touch to move\n"
+        "LMB to spawn physics objects\n"
+        "F5 to save scene, F7 to load\n"
+        "Space to toggle physics debug geometry"
+    );
+}
+
+void Ragdolls::SetupViewport()
+{
+    Renderer* renderer = GetSubsystem<Renderer>();
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+   
+    renderer->SetNumViewports(2);  // use 2 viewports, 1 for 3d and 1 for the 2d hud
+    Viewport* viewport2_ = new Viewport(context_, hudScene, hudCamera );  // hud orthographic viewport, scene and camera
+    RenderPath *overlayRenderPath = new RenderPath(); 
+    overlayRenderPath->Load(cache->GetResource<XMLFile>("PostProcess/FrontPath.xml"));  //special renderpath that does not clear
+    viewport2_->SetRenderPath(overlayRenderPath);  // apply to hud viewport, so the background is transparent
+    renderer->SetViewport(0, new Viewport(context_, scene_, cameraNode_->GetComponent<Camera>())); // perspective viewport, scene and camera
+    renderer->SetViewport(1, viewport2_);  // and add in the HUD viewport
+}
+
+void Ragdolls::MoveCamera(float timeStep)
+{
+
+    Input* input = GetSubsystem<Input>();
+
+    // Movement speed as world units per second
+    const float MOVE_SPEED = 20.0f;
+    // Mouse sensitivity as degrees per pixel
+    const float MOUSE_SENSITIVITY = 0.1f;
+
+    // Use this frame's mouse motion to adjust camera node yaw and pitch. Clamp the pitch between -90 and 90 degrees
+    IntVector2 mouseMove = input->GetMouseMove();
+    yaw_ += MOUSE_SENSITIVITY * mouseMove.x_;
+    pitch_ += MOUSE_SENSITIVITY * mouseMove.y_;
+    pitch_ = Clamp(pitch_, -90.0f, 90.0f);
+
+    // Construct new orientation for the camera scene node from yaw and pitch. Roll is fixed to zero
+    cameraNode_->SetRotation(Quaternion(pitch_, yaw_, 0.0f));
+
+    // Read WASD keys and move the camera scene node to the corresponding direction if they are pressed
+    if (input->GetKeyDown(KEY_W))
+        cameraNode_->Translate(Vector3::FORWARD * MOVE_SPEED * timeStep);
+    if (input->GetKeyDown(KEY_S))
+        cameraNode_->Translate(Vector3::BACK * MOVE_SPEED * timeStep);
+    if (input->GetKeyDown(KEY_A))
+        cameraNode_->Translate(Vector3::LEFT * MOVE_SPEED * timeStep);
+    if (input->GetKeyDown(KEY_D))
+        cameraNode_->Translate(Vector3::RIGHT * MOVE_SPEED * timeStep);
+
+    // "Shoot" a physics object with left mousebutton
+    if (input->GetMouseButtonPress(MOUSEB_LEFT))
+        SpawnObject();
+
+    // Check for loading / saving the scene
+    if (input->GetKeyPress(KEY_F5))
+    {
+        File saveFile(context_, GetSubsystem<FileSystem>()->GetProgramDir() + "Data/Scenes/Ragdolls.xml", FILE_WRITE);
+        scene_->SaveXML(saveFile);
+    }
+    if (input->GetKeyPress(KEY_F7))
+    {
+        File loadFile(context_, GetSubsystem<FileSystem>()->GetProgramDir() + "Data/Scenes/Ragdolls.xml", FILE_READ);
+        scene_->LoadXML(loadFile);
+    }
+
+    // Toggle physics debug geometry with space
+    if (input->GetKeyPress(KEY_SPACE))
+        drawDebug_ = !drawDebug_;
+        
+    if (input->GetKeyPress (KEY_U)) {
+        massCount++;
+        if ( massCount > 5 )
+            massCount = 0;
+        UpdateMassHud (massCount);
+    }
+
+    if (input->GetKeyPress (KEY_I)) {
+        speedCount++;
+        if ( speedCount> 5 )
+            speedCount = 0;
+        UpdateSpeedHud (speedCount);
+    }
+
+    if (input->GetKeyPress (KEY_O)) {
+        sizeCount++;
+        if ( sizeCount > 5 )
+            sizeCount = 0;
+        UpdateSizeHud (sizeCount);
+    }
+
+    if (input->GetKeyPress (KEY_P)) {
+        if ( bulletArc == 0.0 )
+            bulletArc = 0.25f;
+        else if ( bulletArc > 0.0 )
+            bulletArc = 0.0f;
+    }
+
+    if (input->GetKeyPress (KEY_R)) {
+        RestartJacks ();
+    }
+
+    UpdateFps ();
+    CleanUpSome ();
+
+}
+
+void Ragdolls::SpawnObject()
+{
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+
+    Node* boxNode = scene_->CreateChild("Sphere");
+    boxNode->SetPosition(cameraNode_->GetPosition());
+    boxNode->SetRotation(cameraNode_->GetRotation());
+    boxNode->SetScale(bulletSize[sizeCount]);
+    StaticModel* boxObject = boxNode->CreateComponent<StaticModel>();
+    boxObject->SetModel(cache->GetResource<Model>("Models/Sphere.mdl"));
+    boxObject->SetMaterial(cache->GetResource<Material>("Materials/StoneSmall.xml"));
+    boxObject->SetCastShadows(true);
+
+    RigidBody* body = boxNode->CreateComponent<RigidBody>();
+    body->SetMass(bulletMass[massCount]);
+    body->SetRollingFriction(0.15f);
+    CollisionShape* shape = boxNode->CreateComponent<CollisionShape>();
+    shape->SetSphere(1.0f);
+
+    const float OBJECT_VELOCITY = bulletSpeed[speedCount];
+
+    // Set initial velocity for the RigidBody based on camera forward vector. Add also a slight up component
+    // to overcome gravity better
+    body->SetLinearVelocity(cameraNode_->GetRotation() * Vector3(0.0f, bulletArc, 1.0f) * OBJECT_VELOCITY);
+}
+
+void Ragdolls::SubscribeToEvents()
+{
+    // Subscribe HandleUpdate() function for processing update events
+    SubscribeToEvent(E_UPDATE, ATOMIC_HANDLER(Ragdolls, HandleUpdate));
+
+    // Subscribe HandlePostRenderUpdate() function for processing the post-render update event, during which we request
+    // debug geometry
+    SubscribeToEvent(E_POSTRENDERUPDATE, ATOMIC_HANDLER(Ragdolls, HandlePostRenderUpdate));
+}
+
+void Ragdolls::HandleUpdate(StringHash eventType, VariantMap& eventData)
+{
+    using namespace Update;
+
+    // Take the frame time step, which is stored as a float
+    float timeStep = eventData[P_TIMESTEP].GetFloat();
+
+    // Move the camera, scale movement with time step
+    MoveCamera(timeStep);
+}
+
+void Ragdolls::HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
+{
+    // If draw debug mode is enabled, draw physics debug geometry. Use depth test to make the result easier to interpret
+    if (drawDebug_)
+        scene_->GetComponent<PhysicsWorld>()->DrawDebugGeometry(true);
+}
+
+    // support for 2D hud and new features
+void Ragdolls::CreateHUD()
+{
+     float hscal = 0.4f;
+    //
+    // create a 2nd viewport and scene for a hud with sprites.
+    //
+    hudScene = new Scene(context_);
+    hudScene->CreateComponent<Octree>();
+    // Create camera node
+    Node* hudCam = hudScene->CreateChild("HudCamera");
+    // Set camera's position
+    hudCam->SetPosition( Vector3(0.0f, 0.0f, -10.0f));
+    hudCamera = hudCam->CreateComponent<Camera>();
+    hudCamera->SetOrthographic(true);
+    Graphics* graphics = GetSubsystem<Graphics>();
+    hudCamera->SetOrthoSize ((float)graphics->GetHeight () * 0.01f ); //PIXEL_SIZE
+
+    ResourceCache *cache = GetSubsystem<ResourceCache>();
+
+    // add a crosshair in the center of the screen
+    Sprite2D* sprite = cache->GetResource<Sprite2D>("Textures/NinjaSnowWar/Sight.png");
+    Node* targetSprite_ = hudScene->CreateChild("targetSprite");
+    targetSprite_->SetPosition2D(Vector2(0,0));
+    targetSprite_->SetScale2D(Vector2(0.75f, 0.75f));
+    StaticSprite2D* staticSprite = targetSprite_->CreateComponent<StaticSprite2D>();
+    staticSprite->SetSprite(sprite);   // Set sprite
+    staticSprite->SetBlendMode( BLEND_ALPHA ); // Set blend mode
+    staticSprite->SetAlpha(0.3f);  
+
+    // borrow the spinning coin from the 2DSprite example to show what the possibilities are
+    float halfWidth = graphics->GetWidth() * 0.5f * 0.01;
+    float halfHeight = graphics->GetHeight() * 0.5f * 0.01;
+    // Get animation set
+    AnimationSet2D* animationSet = cache->GetResource<AnimationSet2D>("Urho2D/GoldIcon.scml");
+    if (animationSet == NULL) return;
+    Node* spriteNode2 = hudScene->CreateChild("AnimatedSprite2D");
+    AnimatedSprite2D* animatedSprite = spriteNode2->CreateComponent<AnimatedSprite2D>();
+    animatedSprite->SetAnimationSet(animationSet);         // Set animation
+    animatedSprite->SetAnimation("idle", LM_DEFAULT);
+    spriteNode2->SetPosition2D( Vector2(halfWidth - 0.4f, halfHeight - 0.4f));
+
+    // (bullet) mass, speed size feature huds
+    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill1.png") );
+    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill2.png") );
+    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill3.png") );
+    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill4.png") );
+    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill5.png") );
+    filler.Push ( cache->GetResource<Sprite2D>("Textures/hudfill6.png") );
+
+    Sprite2D* spritem = cache->GetResource<Sprite2D>("Textures/hudmass.png");
+    Node* hudm = hudScene->CreateChild("hudMass");
+    hudm->SetScale2D( Vector2(hscal,hscal));
+    hudm->SetPosition2D( Vector2( 0 - (halfWidth/3.0), halfHeight - 0.4)); 
+    StaticSprite2D* hudSpritem = hudm->CreateComponent<StaticSprite2D>();
+    hudSpritem->SetSprite(spritem);
+    hudSpritem->SetAlpha(0.9);
+    hudSpritem->SetBlendMode( BLEND_ALPHA);
+    hudSpritem->SetOrderInLayer(3); 
+    Node* hudfm = hudm->CreateChild("hudMassFill");
+    hudfm->SetScale2D( Vector2(1,1));
+    hudfm->SetPosition2D(  Vector2( 0, 0)); 
+    StaticSprite2D* hudSpritefm = hudfm->CreateComponent<StaticSprite2D>();
+    hudSpritefm->SetSprite(filler[0]);
+    hudSpritefm->SetAlpha(0.9);
+    hudSpritefm->SetBlendMode( BLEND_ALPHA);
+    hudSpritefm->SetOrderInLayer(-3); 
+
+    Sprite2D* sprites = cache->GetResource<Sprite2D>("Textures/hudspeed.png");
+    Node* huds = hudScene->CreateChild("hudSpeed");
+    huds->SetScale2D( Vector2(hscal,hscal));
+    huds->SetPosition2D(  Vector2( 0, halfHeight - 0.4)); 
+    StaticSprite2D* hudSprites = huds->CreateComponent<StaticSprite2D>();
+    hudSprites->SetSprite(sprites);
+    hudSprites->SetAlpha(0.9);
+    hudSprites->SetBlendMode( BLEND_ALPHA);
+    hudSprites->SetOrderInLayer(3); 
+    Node* hudsm = huds->CreateChild("hudSpeedFill");
+    hudsm->SetScale2D( Vector2(1,1));
+    hudsm->SetPosition2D( Vector2( 0, 0)); 
+    StaticSprite2D* hudSpritesm = hudsm->CreateComponent<StaticSprite2D>();
+    hudSpritesm->SetSprite(filler[0]);
+    hudSpritesm->SetAlpha(0.9);
+    hudSpritesm->SetBlendMode( BLEND_ALPHA);
+    hudSpritesm->SetOrderInLayer(-3); 
+
+    Sprite2D* spritez = cache->GetResource<Sprite2D>("Textures/hudsize.png");
+    Node* hudz = hudScene->CreateChild("hudSize");
+    hudz->SetScale2D( Vector2(hscal,hscal));
+    hudz->SetPosition2D(  Vector2( 0 + (halfWidth/3.0), halfHeight - 0.4)); 
+    StaticSprite2D* hudSpritez = hudz->CreateComponent<StaticSprite2D>();
+    hudSpritez->SetSprite(spritez);
+    hudSpritez->SetAlpha(0.9);
+    hudSpritez->SetBlendMode( BLEND_ALPHA);
+    hudSpritez->SetOrderInLayer(3); 
+    Node* hudzm = hudz->CreateChild("hudSizeFill");
+    hudzm->SetScale2D( Vector2(1,1));
+    hudzm->SetPosition2D( Vector2( 0, 0)); 
+    StaticSprite2D* hudSpritezm = hudzm->CreateComponent<StaticSprite2D>();
+    hudSpritezm->SetSprite(filler[0]);
+    hudSpritezm->SetAlpha(0.9);
+    hudSpritezm->SetBlendMode( BLEND_ALPHA);
+    hudSpritezm->SetOrderInLayer(-3);
+}
+
+void Ragdolls::RestartJacks()
+{
+    PODVector< Node * >allnodes;
+    scene_->GetChildren (allnodes, true);
+
+    for ( int ii=0; ii<allnodes.Size() ; ii++ ) 
+    { 
+        if ( allnodes[ii]->GetName().Compare ("Sphere") == 0) allnodes[ii]->Remove ();
+        else if ( allnodes[ii]->GetName().Compare ("Stuffing") == 0 ) allnodes[ii]->Remove ();
+        else if ( allnodes[ii]->GetName().Compare ("Jack") == 0 ) allnodes[ii]->Remove ();
+    }
+
+    ResourceCache *cache = GetSubsystem<ResourceCache>();
+    // Create animated models, you dont know ... jack
+   for (int z = -1; z <= 1; ++z)
+    {
+        for (int x = -4; x <= 4; ++x)
+        {
+            Node* modelNode = scene_->CreateChild("Jack");
+            modelNode->SetPosition(Vector3(x * 5.0f, 0.0f, z * 5.0f));
+            modelNode->SetRotation(Quaternion(0.0f, 180.0f, 0.0f));
+            AnimatedModel* modelObject = modelNode->CreateComponent<AnimatedModel>();
+            modelObject->SetModel(cache->GetResource<Model>("Models/Jack.mdl"));
+            modelObject->SetMaterial(cache->GetResource<Material>("Materials/Jack.xml"));
+            modelObject->SetCastShadows(true);
+            // Set the model to also update when invisible to avoid staying invisible when the model should come into
+            // view, but does not as the bounding box is not updated
+            modelObject->SetUpdateInvisible(true);
+
+            // Create a rigid body and a collision shape. These will act as a trigger for transforming the
+            // model into a ragdoll when hit by a moving object
+            RigidBody* body = modelNode->CreateComponent<RigidBody>();
+            // The Trigger mode makes the rigid body only detect collisions, but impart no forces on the
+            // colliding objects
+            body->SetTrigger(true);
+            CollisionShape* shape = modelNode->CreateComponent<CollisionShape>();
+            // Create the capsule shape with an offset so that it is correctly aligned with the model, which
+            // has its origin at the feet
+            shape->SetCapsule(0.7f, 2.0f, Vector3(0.0f, 1.0f, 0.0f));
+
+            // Create a custom component that reacts to collisions and creates the ragdoll
+            modelNode->CreateComponent<CreateRagdoll>();
+        }
+    }    
+}
+
+void Ragdolls::CleanUpSome()
+{
+    Node* cam = cameraNode_; // note - the camera isnt in the scene
+    if ( cam == NULL )
+        return;
+
+    PODVector< Node * >allnodes;
+    scene_->GetChildren (allnodes, true);
+    for ( int ii=0; ii<allnodes.Size() ; ii++ ) 
+    { 
+        if ( allnodes[ii]->GetName().Compare ("Sphere") == 0 ) 
+        {
+            if (( allnodes[ii]->GetWorldPosition() - cam->GetWorldPosition() ).Length() > 270.0f)
+            {
+                allnodes[ii]->Remove ();
+            }
+        }
+    }    
+}
+
+void Ragdolls::UpdateFps ()
+{
+    Engine* eng = GetSubsystem<Engine>();
+    String mystr = "FPS: " + String(eng->GetFps());
+    mystr += "\nUse WASD keys and mouse/touch to move\n";
+    mystr += "LMB to spawn physics objects\n";
+    mystr += "U=Mass, I=Speed, O=Size, R=Restart\n";
+    mystr += "Space to toggle physics debug geometry";
+    SetInstructions ( mystr );
+}
+
+void Ragdolls::UpdateMassHud ( int value )
+{
+    Node* xNode = hudScene->GetChild("hudMass", true);
+    if (xNode) {
+        Node* fillx = xNode->GetChild("hudMassFill");
+        if (fillx) {
+            StaticSprite2D* hudSprite = fillx->GetComponent<StaticSprite2D>();
+            hudSprite->SetSprite(filler[value]);
+        }
+    }
+}
+
+void Ragdolls::UpdateSpeedHud ( int value )
+{
+    Node* xNode = hudScene->GetChild("hudSpeed", true);
+    if (xNode) {
+        Node* fillx = xNode->GetChild("hudSpeedFill");
+        if (fillx) {
+            StaticSprite2D* hudSprite = fillx->GetComponent<StaticSprite2D>();
+            hudSprite->SetSprite(filler[value]);
+        }
+    }
+}
+
+void Ragdolls::UpdateSizeHud ( int value )
+{
+    Node* xNode = hudScene->GetChild("hudSize", true);
+    if (xNode) {
+        Node* fillx = xNode->GetChild("hudSizeFill");
+        if (fillx) {
+            StaticSprite2D* hudSprite = fillx->GetComponent<StaticSprite2D>();
+            hudSprite->SetSprite(filler[value]);
+        }
+    }
+}

+ 98 - 0
FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/Ragdolls.h

@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+// Copyright (c) 2014-2016, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "Sample.h"
+
+namespace Atomic
+{
+
+class Node;
+class Scene;
+class Sprite2D;
+
+}
+
+/// Ragdoll example.
+/// This sample demonstrates:
+///     - Detecting physics collisions
+///     - Moving an AnimatedModel's bones with physics and connecting them with constraints
+///     - Using rolling friction to stop rolling objects from moving infinitely
+class Ragdolls : public Sample
+{
+    ATOMIC_OBJECT(Ragdolls, Sample)
+
+public:
+    /// Construct.
+    Ragdolls(Context* context);
+
+    /// Setup after engine initialization and before running the main loop.
+    virtual void Start();
+
+protected:
+
+private:
+    /// Construct the scene content.
+    void CreateScene();
+    /// Construct an instruction text to the UI.
+    void CreateInstructions();
+    /// Set up a viewport for displaying the scene.
+    void SetupViewport();
+    /// Subscribe to application-wide logic update and post-render update events.
+    void SubscribeToEvents();
+    /// Read input and moves the camera.
+    void MoveCamera(float timeStep);
+    /// Spawn a physics object from the camera position.
+    void SpawnObject();
+    /// Handle the logic update event.
+    void HandleUpdate(StringHash eventType, VariantMap& eventData);
+    /// Handle the post-render update event.
+    void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData);
+
+    /// Flag for drawing debug geometry.
+    bool drawDebug_;
+    
+    // support for 2D hud and new features
+    void CreateHUD();
+    void RestartJacks();
+    void CleanUpSome();
+    void UpdateFps ();
+    void UpdateMassHud ( int value );
+    void UpdateSpeedHud ( int value );
+    void UpdateSizeHud ( int value );
+    
+    // the  2nd scene for the hud "overlay"
+    SharedPtr<Scene> hudScene;    // the hud scene
+    SharedPtr<Camera> hudCamera;  // ortho cam for the (pixel perfect) hud
+    Vector <Sprite2D*> filler;    // for bargraph display
+
+    // more fun features...
+    PODVector <float> bulletMass;   // how heavy the bullet is
+    PODVector <float> bulletSpeed;  // how fast the bullet is
+    PODVector <float> bulletSize;   // how big the bullet is
+    int massCount, speedCount, sizeCount; // counters
+
+    float bulletArc;    // shooting inclination
+
+};

+ 268 - 0
FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/Sample.cpp

@@ -0,0 +1,268 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+// Copyright (c) 2014-2016, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include <Atomic/Core/ProcessUtils.h>
+#include <Atomic/IO/FileSystem.h>
+#include <Atomic/Graphics/Graphics.h>
+#include <Atomic/Graphics/Renderer.h>
+#include <Atomic/Resource/Image.h>
+#include <Atomic/Scene/Scene.h>
+
+#include <Atomic/UI/UI.h>
+#include <Atomic/UI/UIEvents.h>
+#include <Atomic/UI/UIFontDescription.h>
+#include <Atomic/UI/UIView.h>
+#include <Atomic/UI/UILayout.h>
+
+#include "Sample.h"
+#include "SampleSelector.h"
+#include "FeatureExamples.h"
+
+Sample::Sample(Context* context) :
+    Object(context),
+    yaw_(0.0f),
+    pitch_(0.0f),
+    touchEnabled_(false),
+    paused_(false),
+    useMouseMode_(MM_ABSOLUTE)
+{
+
+}
+
+void Sample::Start()
+{
+    SubscribeToEvent(E_KEYUP, ATOMIC_HANDLER(Sample, HandleKeyDown));
+}
+
+void Sample::Stop()
+{
+
+}
+
+void Sample::InitMouseMode(MouseMode mode)
+{
+    useMouseMode_ = mode;
+
+    Input* input = GetSubsystem<Input>();
+
+    if (GetPlatform() != "Web")
+    {
+        if (useMouseMode_ == MM_FREE)
+            input->SetMouseVisible(true);
+
+        // ATOMIC: FIXME
+        // Console* console = GetSubsystem<Console>();
+
+        if (useMouseMode_ != MM_ABSOLUTE)
+        {
+            input->SetMouseMode(useMouseMode_);
+
+            // ATOMIC: FIXME
+            /*
+            if (console && console->IsVisible())
+                input->SetMouseMode(MM_ABSOLUTE, true);
+            */
+        }
+    }
+    else
+    {
+        input->SetMouseVisible(true);
+        SubscribeToEvent(E_MOUSEBUTTONDOWN, ATOMIC_HANDLER(Sample, HandleMouseModeRequest));
+        SubscribeToEvent(E_MOUSEMODECHANGED, ATOMIC_HANDLER(Sample, HandleMouseModeChange));
+    }
+}
+
+void Sample::BackToSelector()
+{
+    GetSubsystem<Input>()->SetMouseVisible(true);
+ 
+    UnsubscribeFromAllEvents();
+    Renderer* renderer = GetSubsystem<Renderer>();
+    for (unsigned i = 0; i <  renderer->GetNumViewports(); i++)
+    {
+        renderer->SetViewport(i, 0);
+    }
+
+    FeatureExamples::GetUIView()->DeleteAllChildren();
+
+    new SampleSelector(context_);
+}
+
+void Sample::HandleKeyDown(StringHash eventType, VariantMap& eventData)
+{
+    using namespace KeyDown;
+
+    int key = eventData[P_KEY].GetInt();
+
+    if (key == KEY_ESCAPE )
+    {
+        BackToSelector();
+        return;
+    }
+
+    // Common rendering quality controls, only when UI has no focused element
+    Renderer* renderer = GetSubsystem<Renderer>();
+
+    // Texture quality
+    if (key == '1')
+    {
+        int quality = renderer->GetTextureQuality();
+        ++quality;
+        if (quality > QUALITY_HIGH)
+            quality = QUALITY_LOW;
+        renderer->SetTextureQuality(quality);
+    }
+
+    // Material quality
+    else if (key == '2')
+    {
+        int quality = renderer->GetMaterialQuality();
+        ++quality;
+        if (quality > QUALITY_HIGH)
+            quality = QUALITY_LOW;
+        renderer->SetMaterialQuality(quality);
+    }
+
+    // Specular lighting
+    else if (key == '3')
+        renderer->SetSpecularLighting(!renderer->GetSpecularLighting());
+
+    // Shadow rendering
+    else if (key == '4')
+        renderer->SetDrawShadows(!renderer->GetDrawShadows());
+
+    // Shadow map resolution
+    else if (key == '5')
+    {
+        int shadowMapSize = renderer->GetShadowMapSize();
+        shadowMapSize *= 2;
+        if (shadowMapSize > 2048)
+            shadowMapSize = 512;
+        renderer->SetShadowMapSize(shadowMapSize);
+    }
+
+    // Shadow depth and filtering quality
+    else if (key == '6')
+    {
+        ShadowQuality quality = renderer->GetShadowQuality();
+        quality = (ShadowQuality)(quality + 1);
+        if (quality > SHADOWQUALITY_BLUR_VSM)
+            quality = SHADOWQUALITY_SIMPLE_16BIT;
+        renderer->SetShadowQuality(quality);
+    }
+
+    // Occlusion culling
+    else if (key == '7')
+    {
+        bool occlusion = renderer->GetMaxOccluderTriangles() > 0;
+        occlusion = !occlusion;
+        renderer->SetMaxOccluderTriangles(occlusion ? 5000 : 0);
+    }
+
+    // Instancing
+    else if (key == '8')
+        renderer->SetDynamicInstancing(!renderer->GetDynamicInstancing());
+
+    // Take screenshot
+    else if (key == '9')
+    {
+        Graphics* graphics = GetSubsystem<Graphics>();
+        Image screenshot(context_);
+        graphics->TakeScreenShot(&screenshot);
+        // Here we save in the Data folder with date and time appended
+        screenshot.SavePNG(GetSubsystem<FileSystem>()->GetProgramDir() + "Data/Screenshot_" +
+            Time::GetTimeStamp().Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_') + ".png");
+    }
+}
+
+void Sample::SimpleCreateInstructionsWithWasd(const String& extra)
+{
+    SimpleCreateInstructions("Use WASD keys and mouse/touch to move" + extra);
+}
+
+void Sample::SimpleCreateInstructions(const String& text)
+{
+
+    UILayout* layout = new UILayout(context_);
+
+    layout->SetRect(FeatureExamples::GetUIView()->GetRect());
+
+    layout->SetLayoutPosition (UI_LAYOUT_POSITION_RIGHT_BOTTOM);
+    layout->SetLayoutDistributionPosition (UI_LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM);
+
+    SharedPtr<UIFontDescription> fontDesc(new UIFontDescription(context_));
+    fontDesc->SetId("Vera");
+    fontDesc->SetSize(18);
+
+    String msgText = text;
+
+    if (text.Length() && !text.EndsWith("\n"))
+        msgText += "\n";
+
+    msgText += "Press ESC for menu";
+
+    label_ = new UIEditField(context_);
+    label_->SetFontDescription(fontDesc);
+    label_->SetReadOnly(true);
+    label_->SetMultiline(true);
+    label_->SetAdaptToContentSize(true);
+    label_->SetText(msgText);
+    layout->AddChild(label_);
+
+    FeatureExamples::GetUIView()->AddChild(layout);
+
+}
+
+void Sample::SetInstructions(const String& text)
+{
+    if ( label_ != NULL )
+        label_->SetText(text);
+}
+
+// If the user clicks the canvas, attempt to switch to relative mouse mode on web platform
+void Sample::HandleMouseModeRequest(StringHash eventType, VariantMap& eventData)
+{
+    // ATOMIC: FIXME
+    /*
+    Console* console = GetSubsystem<Console>();
+    if (console && console->IsVisible())
+        return;
+    */
+
+    Input* input = GetSubsystem<Input>();
+    if (useMouseMode_ == MM_ABSOLUTE)
+        input->SetMouseVisible(false);
+    else if (useMouseMode_ == MM_FREE)
+        input->SetMouseVisible(true);
+    input->SetMouseMode(useMouseMode_);
+}
+
+void Sample::HandleMouseModeChange(StringHash eventType, VariantMap& eventData)
+{
+    Input* input = GetSubsystem<Input>();
+    bool mouseLocked = eventData[MouseModeChanged::P_MOUSELOCKED].GetBool();
+    input->SetMouseVisible(!mouseLocked);
+}
+
+
+

+ 125 - 0
FeatureExamples/Mods/Ragdoll2DHud/CPlusPlus/Source/Sample.h

@@ -0,0 +1,125 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+// Copyright (c) 2014-2016, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+#include <Atomic/Core/StringUtils.h>
+#include <Atomic/Input/Input.h>
+#include <Atomic/UI/UIEditField.h>
+
+namespace Atomic
+{
+
+class Node;
+class Scene;
+class UIEditField;
+
+}
+
+using namespace Atomic;
+
+const float TOUCH_SENSITIVITY = 2.0f;
+
+/// Sample class, as framework for all samples.
+///    - Initialization of the Urho3D engine (in Application class)
+///    - Modify engine parameters for windowed mode and to show the class name as title
+///    - Create Urho3D logo at screen
+///    - Set custom window title and icon
+///    - Create Console and Debug HUD, and use F1 and F2 key to toggle them
+///    - Toggle rendering options from the keys 1-8
+///    - Take screenshot with key 9
+///    - Handle Esc key down to hide Console or exit application
+///    - Init touch input on mobile platform using screen joysticks (patched for each individual sample)
+class Sample : public Object
+{
+    // Enable type information.
+    ATOMIC_OBJECT(Sample, Object)
+
+public:
+    /// Construct.
+    Sample(Context* context);
+
+    virtual void Start();
+    virtual void Stop();
+
+protected:
+
+    /// Initialize touch input on mobile platform.
+    void InitTouchInput();
+    /// Initialize mouse mode on non-web platform.
+    void InitMouseMode(MouseMode mode);
+    /// Control logo visibility.
+    void SetLogoVisible(bool enable);
+
+    void SimpleCreateInstructionsWithWasd(const String& extra = String::EMPTY);
+
+    void SimpleCreateInstructions(const String& text = String::EMPTY);
+
+    void SetInstructions(const String& text = String::EMPTY);
+
+    void BackToSelector();
+
+    /// Logo sprite.
+    // SharedPtr<Sprite> logoSprite_;
+    /// Scene.
+    SharedPtr<Scene> scene_;
+    /// Camera scene node.
+    SharedPtr<Node> cameraNode_;
+    /// Camera yaw angle.
+    float yaw_;
+    /// Camera pitch angle.
+    float pitch_;
+    /// Flag to indicate whether touch input has been enabled.
+    bool touchEnabled_;
+    /// Mouse mode option to use in the sample.
+    MouseMode useMouseMode_;
+    /// for making the instructions writable
+    SharedPtr<UIEditField> label_;
+    
+private:
+
+    /// Create logo.
+    void CreateLogo();
+    /// Set custom window Title & Icon
+    void SetWindowTitleAndIcon();
+    /// Handle request for mouse mode on web platform.
+    void HandleMouseModeRequest(StringHash eventType, VariantMap& eventData);
+    /// Handle request for mouse mode change on web platform.
+    void HandleMouseModeChange(StringHash eventType, VariantMap& eventData);
+    /// Handle key down event to process key controls common to all samples.
+    void HandleKeyDown(StringHash eventType, VariantMap& eventData);
+    /// Handle key up event to process key controls common to all samples.
+    void HandleKeyUp(StringHash eventType, VariantMap& eventData);
+    /// Handle scene update event to control camera's pitch and yaw for all samples.
+    void HandleSceneUpdate(StringHash eventType, VariantMap& eventData);
+    /// Handle touch begin event to initialize touch input on desktop platform.
+    void HandleTouchBegin(StringHash eventType, VariantMap& eventData);
+
+    /// Screen joystick index for navigational controls (mobile platforms only).
+    unsigned screenJoystickIndex_;
+    /// Screen joystick index for settings (mobile platforms only).
+    unsigned screenJoystickSettingsIndex_;
+    /// Pause flag.
+    bool paused_;
+};

+ 0 - 0
FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Components/.gitkeep


+ 215 - 0
FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Components/Ragdoll.cs

@@ -0,0 +1,215 @@
+//
+// Copyright (c) 2008-2015 the Urho3D project.
+// Copyright (c) 2015 Xamarin Inc
+// Copyright (c) 2016 THUNDERBEAST GAMES LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+using System;
+using AtomicEngine;
+
+namespace FeatureExamples
+{
+    class Ragdoll : CSComponent
+    {
+        public void Start()
+        {
+            SubscribeToEvent<NodeCollisionEvent>(Node, HandleNodeCollision);
+            
+        }
+
+        void HandleNodeCollision(NodeCollisionEvent e)
+        {
+            // Get the other colliding body, make sure it is moving (has nonzero mass)
+            RigidBody otherBody = e.OtherBody;
+
+            if (otherBody.Mass > 0.0f)
+            {
+                HitEffect (Node); // bam!
+
+                // We do not need the physics components in the AnimatedModel's root scene node anymore
+                Node.RemoveComponent<RigidBody>();
+                Node.RemoveComponent<CollisionShape>();
+
+                // Create RigidBody & CollisionShape components to bones
+                CreateRagdollBone("Bip01_Pelvis", ShapeType.SHAPE_BOX, new Vector3(0.3f, 0.2f, 0.25f), new Vector3(0.0f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 0.0f));
+                CreateRagdollBone("Bip01_Spine1", ShapeType.SHAPE_BOX, new Vector3(0.35f, 0.2f, 0.3f), new Vector3(0.15f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 0.0f));
+                CreateRagdollBone("Bip01_L_Thigh", ShapeType.SHAPE_CAPSULE, new Vector3(0.175f, 0.45f, 0.175f), new Vector3(0.25f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 90.0f));
+                CreateRagdollBone("Bip01_R_Thigh", ShapeType.SHAPE_CAPSULE, new Vector3(0.175f, 0.45f, 0.175f), new Vector3(0.25f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 90.0f));
+                CreateRagdollBone("Bip01_L_Calf", ShapeType.SHAPE_CAPSULE, new Vector3(0.15f, 0.55f, 0.15f), new Vector3(0.25f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 90.0f));
+                CreateRagdollBone("Bip01_R_Calf", ShapeType.SHAPE_CAPSULE, new Vector3(0.15f, 0.55f, 0.15f), new Vector3(0.25f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 90.0f));
+                CreateRagdollBone("Bip01_Head", ShapeType.SHAPE_BOX, new Vector3(0.2f, 0.2f, 0.2f), new Vector3(0.1f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 0.0f));
+                CreateRagdollBone("Bip01_L_UpperArm", ShapeType.SHAPE_CAPSULE, new Vector3(0.15f, 0.35f, 0.15f), new Vector3(0.1f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 90.0f));
+                CreateRagdollBone("Bip01_R_UpperArm", ShapeType.SHAPE_CAPSULE, new Vector3(0.15f, 0.35f, 0.15f), new Vector3(0.1f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 90.0f));
+                CreateRagdollBone("Bip01_L_Forearm", ShapeType.SHAPE_CAPSULE, new Vector3(0.125f, 0.4f, 0.125f), new Vector3(0.2f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 90.0f));
+                CreateRagdollBone("Bip01_R_Forearm", ShapeType.SHAPE_CAPSULE, new Vector3(0.125f, 0.4f, 0.125f), new Vector3(0.2f, 0.0f, 0.0f),
+                    new Quaternion(0.0f, 0.0f, 90.0f));
+
+                Vector3 back = new Vector3(0f, 0f, -1f);
+                Vector3 forward = new Vector3(0f, 0f, 1f);
+                Vector3 left = new Vector3(-1f, 0f, 0f);
+                Vector3 down = new Vector3(0f, -1f, 0f);
+                Vector3 up = new Vector3(0f, 1f, 0f);
+
+                // Create Constraints between bones
+                CreateRagdollConstraint("Bip01_L_Thigh", "Bip01_Pelvis", ConstraintType.CONSTRAINT_CONETWIST, back, forward,
+                    new Vector2(45.0f, 45.0f), Vector2.Zero);
+                CreateRagdollConstraint("Bip01_R_Thigh", "Bip01_Pelvis", ConstraintType.CONSTRAINT_CONETWIST, back, forward,
+                    new Vector2(45.0f, 45.0f), Vector2.Zero);
+                CreateRagdollConstraint("Bip01_L_Calf", "Bip01_L_Thigh", ConstraintType.CONSTRAINT_HINGE, back, back,
+                    new Vector2(90.0f, 0.0f), Vector2.Zero);
+                CreateRagdollConstraint("Bip01_R_Calf", "Bip01_R_Thigh", ConstraintType.CONSTRAINT_HINGE, back, back,
+                    new Vector2(90.0f, 0.0f), Vector2.Zero);
+                CreateRagdollConstraint("Bip01_Spine1", "Bip01_Pelvis", ConstraintType.CONSTRAINT_HINGE, forward, forward,
+                    new Vector2(45.0f, 0.0f), new Vector2(-10.0f, 0.0f));
+                CreateRagdollConstraint("Bip01_Head", "Bip01_Spine1", ConstraintType.CONSTRAINT_CONETWIST, left, left,
+                    new Vector2(0.0f, 30.0f), Vector2.Zero);
+                CreateRagdollConstraint("Bip01_L_UpperArm", "Bip01_Spine1", ConstraintType.CONSTRAINT_CONETWIST, down, up,
+                    new Vector2(45.0f, 45.0f), Vector2.Zero, false);
+                CreateRagdollConstraint("Bip01_R_UpperArm", "Bip01_Spine1", ConstraintType.CONSTRAINT_CONETWIST, down, up,
+                    new Vector2(45.0f, 45.0f), Vector2.Zero, false);
+                CreateRagdollConstraint("Bip01_L_Forearm", "Bip01_L_UpperArm", ConstraintType.CONSTRAINT_HINGE, back, back,
+                    new Vector2(90.0f, 0.0f), Vector2.Zero);
+                CreateRagdollConstraint("Bip01_R_Forearm", "Bip01_R_UpperArm", ConstraintType.CONSTRAINT_HINGE, back, back,
+                    new Vector2(90.0f, 0.0f), Vector2.Zero);
+
+                // Disable keyframe animation from all bones so that they will not interfere with the ragdoll
+                AnimatedModel model = GetComponent<AnimatedModel>();
+
+                Skeleton skeleton = model.Skeleton;
+                for (uint i = 0; i < skeleton.GetNumBones(); ++i)
+                {
+                    skeleton.GetBone(i).Animated = false;
+                }
+
+                // Finally remove self from the scene node. Note that this must be the last operation performed in the function
+                Remove();
+            }
+        }
+
+        void CreateRagdollBone(string boneName, ShapeType type, Vector3 size, Vector3 position, Quaternion rotation)
+        {
+            // Find the correct child scene node recursively
+            Node boneNode = Node.GetChild(boneName, true);
+            if (boneNode == null)
+            {
+                Log.Warn($"Could not find bone {boneName} for creating ragdoll physics components");
+                return;
+            }
+
+            RigidBody body = boneNode.CreateComponent<RigidBody>();
+            // Set mass to make movable
+            body.Mass = 1.0f;
+            // Set damping parameters to smooth out the motion
+            body.LinearDamping = 0.05f;
+            body.AngularDamping = 0.85f;
+            // Set rest thresholds to ensure the ragdoll rigid bodies come to rest to not consume CPU endlessly
+            body.LinearRestThreshold = 1.5f;
+            body.AngularRestThreshold = 2.5f;
+
+            CollisionShape shape = boneNode.CreateComponent<CollisionShape>();
+            // We use either a box or a capsule shape for all of the bones
+            if (type == ShapeType.SHAPE_BOX)
+                shape.SetBox(size, position, rotation);
+            else
+                shape.SetCapsule(size.X, size.Y, position, rotation);
+        }
+
+        void CreateRagdollConstraint(string boneName, string parentName, ConstraintType type,
+            Vector3 axis, Vector3 parentAxis, Vector2 highLimit, Vector2 lowLimit, bool disableCollision = true)
+        {
+            Node boneNode = Node.GetChild(boneName, true);
+            Node parentNode = Node.GetChild(parentName, true);
+            if (boneNode == null)
+            {
+                Log.Warn($"Could not find bone {boneName} for creating ragdoll constraint");
+                return;
+            }
+            if (parentNode == null)
+            {
+                Log.Warn($"Could not find bone {parentName} for creating ragdoll constraint");
+                return;
+            }
+
+            Constraint constraint = boneNode.CreateComponent<Constraint>();
+            constraint.ConstraintType = type;
+            // Most of the constraints in the ragdoll will work better when the connected bodies don't collide against each other
+            constraint.DisableCollision = disableCollision;
+            // The connected body must be specified before setting the world position
+            constraint.OtherBody = parentNode.GetComponent<RigidBody>();
+            // Position the constraint at the child bone we are connecting
+            constraint.SetWorldPosition(boneNode.WorldPosition);
+            // Configure axes and limits
+            constraint.SetAxis(axis);
+            constraint.SetOtherAxis(parentAxis);
+            constraint.HighLimit = highLimit;
+            constraint.LowLimit = lowLimit;
+        }
+
+        void HitEffect ( Node parent ) // ragdoll gets the donuts blown out of him
+        {
+            Random rand = new Random();
+            var cache = GetSubsystem<ResourceCache>();
+            Scene myscene = parent.GetScene ();
+            Vector3 where = parent.GetWorldPosition ();
+    
+            for (int mm=0; mm<5; mm++)
+            {
+                Node xNode = myscene.CreateChild("Stuffing");
+                xNode.SetPosition( new Vector3( (float)rand.Next(0,1), (float)rand.Next(0,4), (float)rand.Next(0,15)) + where );
+                xNode.SetRotation( new Quaternion((float)rand.Next(0,360), 0, (float)rand.Next(0,360)));
+                xNode.SetScale(0.3f);
+
+                ParticleEmitter pEmitter = xNode.CreateComponent<ParticleEmitter>();
+................pEmitter.SetEffect(cache.GetResource<ParticleEffect>("Particle/Fire.xml"));
+................pEmitter.SetEnabled(true);  // sparkle donuts.
+
+                //create obj
+                StaticModel boxObject = xNode.CreateComponent<StaticModel>();
+                boxObject.Model = cache.Get<Model>("Models/Torus.mdl");
+                boxObject.SetMaterial(cache.Get<Material>("Materials/Mushroom.xml"));
+                boxObject.CastShadows = true;
+                RigidBody body = xNode.CreateComponent<RigidBody>();
+                body.Mass = 0.45f;
+                body.RollingFriction = 0.15f;
+                body.Friction = 0.75f;
+                body.UseGravity = true;
+                // Disable collision event signaling to reduce CPU load of the physics simulation a111
+                body.SetCollisionEventMode( CollisionEventMode.COLLISION_NEVER );
+                CollisionShape shape = xNode.CreateComponent<CollisionShape>();
+                shape.SetSphere(1.0f, Vector3.Zero, Quaternion.Identity );
+                float objectVelocity = 22.0f;
+                //Node.Rotation
+                body.SetLinearVelocity( new Quaternion((float)rand.Next(0,360), 0, (float)rand.Next(0,360))* new Vector3(0.0f, 0.02f, 1.0f) * objectVelocity);
+            }
+        }
+
+    }
+}

+ 0 - 0
FeatureExamples/CSharp/Resources/PostProcess/FrontPath.xml → FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/PostProcess/FrontPath.xml


+ 498 - 0
FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Scripts/13_Ragdolls.cs

@@ -0,0 +1,498 @@
+//
+// Copyright (c) 2008-2015 the Urho3D project.
+// Copyright (c) 2015 Xamarin Inc
+// Copyright (c) 2016 THUNDERBEAST GAMES LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+using System.Collections.Generic;
+using AtomicEngine;
+
+namespace FeatureExamples
+{
+    public class RagdollSample : Sample
+    {
+        Scene scene;     // perspective (3d) scene, you know, where the ragdolls are.
+        Camera camera;   // the regular camera
+        bool drawDebug;  // bool to turn on/off debug hud.
+
+        // the  2nd scene for the hud "overlay"
+        Scene hudScene;   // the hud scene
+        Camera hudCamera;  // ortho cam for the (pixel perfect) hud
+        Vector <Sprite2D> filler;  // for bargraph display
+
+        // more fun features...
+        List <float> bulletMass;   // how heavy the bullet is
+        List <float> bulletSpeed;  // how fast the bullet is
+        List <float> bulletSize;   // how big the bullet is
+        int massCount, speedCount, sizeCount; // counters
+
+        float bulletArc;    // shooting inclination
+
+        public RagdollSample() : base() { }
+
+        public override void Start()
+        {
+            massCount = 2;
+            speedCount = 2;
+            sizeCount = 2;
+
+            bulletMass = new List<float>();
+            bulletSpeed = new List<float>();
+            bulletSize = new List<float>();
+
+            filler = new Vector <Sprite2D>();
+
+            bulletMass.Add(1.0f);
+            bulletMass.Add(10.0f);
+            bulletMass.Add(50.0f);
+            bulletMass.Add(100.0f);
+            bulletMass.Add(300.0f);
+            bulletMass.Add(666.0f);
+            bulletMass.Add(1000.0f);
+            bulletSpeed.Add(10.0f);
+            bulletSpeed.Add(22.0f);
+            bulletSpeed.Add(41.0f);
+            bulletSpeed.Add(72.0f);
+            bulletSpeed.Add(116.0f);
+            bulletSpeed.Add(200.0f);
+            bulletSpeed.Add(450.0f);
+            bulletSize.Add(0.25f);
+            bulletSize.Add(0.5f);
+            bulletSize.Add(1.25f);
+            bulletSize.Add(3.25f);
+            bulletSize.Add(5.25f);
+            bulletSize.Add(7.25f);
+            bulletSize.Add(11.25f);
+            bulletSize.Add(16.25f);
+
+            bulletArc = 0.25f;
+
+            base.Start();
+            CreateScene();
+            CreateHUD(); // add an overlay HUD that tells you settings
+            SimpleCreateInstructionsWithWasd(
+                "LMB to spawn physics objects\n" +
+                "U=Mass, I=Speed, O=Size, R=Restart\n" +
+                "Space to toggle physics debug geometry\n");
+            SetupViewport();
+            SubscribeToEvents();
+
+            RestartJacks ();
+
+            UpdateSpeedHud (speedCount);
+            UpdateMassHud (massCount);
+            UpdateSizeHud (sizeCount);
+
+            GetSubsystem<Input>().SetMouseVisible (false);
+        }
+
+        void SubscribeToEvents()
+        {
+            SubscribeToEvent<PostRenderUpdateEvent>(e =>
+            {
+                // If draw debug mode is enabled, draw viewport debug geometry, which will show eg. drawable bounding boxes and skeleton
+                // bones. Note that debug geometry has to be separately requested each frame. Disable depth test so that we can see the
+                // bones properly
+                if (drawDebug)
+                    GetSubsystem<Renderer>().DrawDebugGeometry(false);
+            });
+        }
+
+        protected override void Update(float timeStep)
+        {
+            base.Update(timeStep);
+
+            SimpleMoveCamera3D(timeStep);
+
+            var input = GetSubsystem<Input>();
+
+            if (input.GetMouseButtonPress(Constants.MOUSEB_LEFT))
+                SpawnObject();
+
+            /* TODO: Scene.SaveXML/Scene.LoadXML
+            if (input.GetKeyPress(Constants.KEY_F5))
+                scene.SaveXml(fileSystem.UserDocumentsDir + "/Scenes/Physics.xml");
+            if (input.GetKeyPress(Constants.KEY_F7))
+                scene.LoadXml(fileSystem.UserDocumentsDir + "/Scenes/Physics.xml");
+            */
+
+            if (input.GetKeyPress (Constants.KEY_U)) {
+                massCount++;
+                if ( massCount > 5 )
+                    massCount = 0;
+                UpdateMassHud (massCount);
+            }
+
+            if (input.GetKeyPress (Constants.KEY_I)) {
+                speedCount++;
+                if ( speedCount> 5 )
+                    speedCount = 0;
+                UpdateSpeedHud (speedCount);
+            }
+
+            if (input.GetKeyPress (Constants.KEY_O)) {
+                sizeCount++;
+                if ( sizeCount > 5 )
+                    sizeCount = 0;
+                UpdateSizeHud (sizeCount);
+            }
+
+            if (input.GetKeyPress (Constants.KEY_P)) {
+                if ( bulletArc == 0.0 )
+                    bulletArc = 0.25f;
+                else if ( bulletArc > 0.0 )
+                    bulletArc = 0.0f;
+            }
+
+            if (input.GetKeyPress (Constants.KEY_R)) {
+                RestartJacks ();
+            }
+
+            if (input.GetKeyPress(Constants.KEY_SPACE))
+                drawDebug = !drawDebug;
+
+            UpdateFps ();
+            CleanUpSome ();
+        }
+
+        void UpdateFps ()
+        {
+            var eng = GetSubsystem<Engine>();
+            string mystr = "FPS: " + eng.GetFps ().ToString ();
+            mystr += "\nUse WASD keys and mouse/touch to move\n"
+                + "LMB to spawn physics objects\n" 
+                + "U=Mass, I=Speed, O=Size, R=Restart\n" 
+                + "Space to toggle physics debug geometry";
+            SetInstructions ( mystr );
+        }
+
+        void SetupViewport()
+        {
+            var renderer = GetSubsystem<Renderer>();
+            var cache = GetSubsystem<ResourceCache>();
+
+            renderer.SetNumViewports(2);  // use 2 viewports, 1 for 3d and 1 for the 2d hud
+            var viewport2_ = new Viewport(hudScene, hudCamera );  // hud orthographic viewport, scene and camera
+            var overlayRenderPath = new RenderPath(); 
+            overlayRenderPath.Load(cache.GetResource<XMLFile>("PostProcess/FrontPath.xml"));  //special renderpath that does not clear
+            viewport2_.SetRenderPath(overlayRenderPath);  // apply to hud viewport, so the background is transparent
+            renderer.SetViewport(0, new Viewport(scene, camera)); // perspective viewport, scene and camera
+            renderer.SetViewport(1, viewport2_);  // and add in the HUD viewport
+        }
+
+        void CreateScene()
+        {
+            var cache = GetSubsystem<ResourceCache>();
+            scene = new Scene();
+
+            // Create octree, use default volume (-1000, -1000, -1000) to (1000, 1000, 1000)
+            // Create a physics simulation world with default parameters, which will update at 60fps. Like the Octree must
+            // exist before creating drawable components, the PhysicsWorld must exist before creating physics components.
+            // Finally, create a DebugRenderer component so that we can draw physics debug geometry
+            scene.CreateComponent<Octree>();
+            scene.CreateComponent<PhysicsWorld>();
+            scene.CreateComponent<DebugRenderer>();
+
+            // Create a Zone component for ambient lighting & fog control
+            Node zoneNode = scene.CreateChild("Zone");
+            Zone zone = zoneNode.CreateComponent<Zone>();
+            zone.SetBoundingBox(new BoundingBox(-1000.0f, 1000.0f));
+            zone.AmbientColor = (new Color(0.15f, 0.15f, 0.15f));
+            zone.FogColor = new Color(0.5f, 0.5f, 0.7f);
+            zone.FogStart = 100.0f;
+            zone.FogEnd = 300.0f;
+
+            // Create a directional light to the world. Enable cascaded shadows on it
+            Node lightNode = scene.CreateChild("DirectionalLight");
+            lightNode.SetDirection(new Vector3(0.6f, -1.0f, 0.8f));
+            Light light = lightNode.CreateComponent<Light>();
+            light.LightType = LightType.LIGHT_DIRECTIONAL;
+            light.CastShadows = true;
+            light.ShadowBias = new BiasParameters(0.00025f, 0.5f);
+            // Set cascade splits at 10, 50 and 200 world units, fade shadows out at 80% of maximum shadow distance
+            light.ShadowCascade = new CascadeParameters(10.0f, 50.0f, 200.0f, 0.0f, 0.8f);
+
+            {
+                // Create a floor object, 500 x 500 world units. Adjust position so that the ground is at zero Y
+                Node floorNode = scene.CreateChild("Floor");
+                floorNode.Position = new Vector3(0.0f, -0.5f, 0.0f);
+                floorNode.Scale = new Vector3(500.0f, 1.0f, 500.0f);
+                StaticModel floorObject = floorNode.CreateComponent<StaticModel>();
+                floorObject.Model = cache.Get<Model>("Models/Box.mdl");
+                floorObject.SetMaterial(cache.Get<Material>("Materials/StoneTiled.xml"));
+
+                // Make the floor physical by adding RigidBody and CollisionShape components
+                RigidBody body = floorNode.CreateComponent<RigidBody>();
+                // We will be spawning spherical objects in this sample. The ground also needs non-zero rolling friction so that
+                // the spheres will eventually come to rest
+                body.RollingFriction = 0.15f;
+                CollisionShape shape = floorNode.CreateComponent<CollisionShape>();
+                // Set a box shape of size 1 x 1 x 1 for collision. The shape will be scaled with the scene node scale, so the
+                // rendering and physics representation sizes should match (the box model is also 1 x 1 x 1.)
+                shape.SetBox(Vector3.One, Vector3.Zero, Quaternion.Identity);
+            }
+
+            // Create the camera. Limit far clip distance to match the fog
+            CameraNode = new Node();
+            CameraNode.SetName("Camera");
+            camera = CameraNode.CreateComponent<Camera>();
+            camera.FarClip = 300.0f;
+            // Set an initial position for the camera scene node above the plane
+            CameraNode.Position = new Vector3(0.0f, 3.0f, -20.0f);
+        }
+
+        void RestartJacks()
+        {
+            var ll = new Vector <Node>();  //get rid of some old objects
+            scene.GetChildrenWithName ( ll, "Sphere", true); 
+            for ( int ii=0; ii<ll.Size; ii++ ) { 
+                ll[ii].Remove ();
+            }
+
+            var nn = new Vector <Node>();
+            scene.GetChildrenWithName ( nn, "Stuffing", true);
+            for ( int ii=0; ii<nn.Size; ii++ ) { 
+                nn[ii].Remove ();
+            }
+
+            var mm = new Vector <Node>();
+            scene.GetChildrenWithName ( mm, "Jack", true); 
+            for ( int ii=0; ii<mm.Size; ii++ ) { 
+                    mm[ii].Remove ();
+                }
+
+            // Create animated models, you dont know ... jack
+            var cache = GetSubsystem<ResourceCache>();
+            for (int z = -1; z <= 1; ++z)
+            {
+                for (int x = -4; x <= 4; ++x)
+                {
+                    Node modelNode = scene.CreateChild("Jack");
+                    modelNode.Position = new Vector3(x * 5.0f, 0.0f, z * 5.0f);
+                    modelNode.Rotation = new Quaternion(0.0f, 180.0f, 0.0f);
+                    AnimatedModel modelObject = modelNode.CreateComponent<AnimatedModel>();
+                    modelObject.Model = cache.Get<Model>("Models/Jack.mdl");
+                    modelObject.SetMaterial(cache.Get<Material>("Materials/Jack.xml"));
+                    modelObject.CastShadows = true;
+                    // Set the model to also update when invisible to avoid staying invisible when the model should come into
+                    // view, but does not as the bounding box is not updated
+                    modelObject.UpdateInvisible = true;
+
+                    // Create a rigid body and a collision shape. These will act as a trigger for transforming the
+                    // model into a ragdoll when hit by a moving object
+                    RigidBody body = modelNode.CreateComponent<RigidBody>();
+                    // The Trigger mode makes the rigid body only detect collisions, but impart no forces on the
+                    // colliding objects
+                    body.Trigger = true;
+                    CollisionShape shape = modelNode.CreateComponent<CollisionShape>();
+                    // Create the capsule shape with an offset so that it is correctly aligned with the model, which
+                    // has its origin at the feet
+                    shape.SetCapsule(0.7f, 2.0f, new Vector3(0.0f, 1.0f, 0.0f), Quaternion.Identity);
+
+                    // Create a custom component that reacts to collisions and creates the ragdoll
+                    modelNode.AddComponent(new Ragdoll());
+                }
+            }
+        }
+
+        void CreateHUD()
+        {
+            float hscal = 0.4f;
+            //
+            // create a 2nd viewport and scene for a hud with sprites.
+            //
+            hudScene = new Scene();
+            hudScene.CreateComponent<Octree>();
+            // Create camera node
+            var hudCam = hudScene.CreateChild("HudCamera");
+            // Set camera's position
+            hudCam.SetPosition(new Vector3(0.0f, 0.0f, -10.0f));
+            hudCamera = hudCam.CreateComponent<Camera>();
+            hudCamera.SetOrthographic(true);
+            var graphics = GetSubsystem<Graphics>();
+            hudCamera.SetOrthoSize ((float)graphics.GetHeight () * PixelSize ); //PIXEL_SIZE
+
+            var cache = GetSubsystem<ResourceCache>();
+
+            // add a crosshair in the center of the screen
+            var sprite = cache.GetResource<Sprite2D>("Textures/NinjaSnowWar/Sight.png");
+            var targetSprite_ = hudScene.CreateChild("targetSprite");
+            targetSprite_.SetPosition2D(new Vector2(0,0));
+            targetSprite_.SetScale2D( new Vector2(0.75f, 0.75f));
+            var staticSprite = targetSprite_.CreateComponent<StaticSprite2D>();
+            staticSprite.SetSprite(sprite);   // Set sprite
+            staticSprite.SetBlendMode( AtomicEngine.BlendMode.BLEND_ALPHA ); // Set blend mode
+            staticSprite.SetAlpha(0.3f);  
+
+            // borrow the spinning coin from the 2DSprite example to show what the possibilities are
+            float halfWidth = graphics.Width * 0.5f * PixelSize;
+            float halfHeight = graphics.Height * 0.5f * PixelSize;
+            // Get animation set
+            AnimationSet2D animationSet = cache.Get<AnimationSet2D>("Urho2D/GoldIcon.scml");
+            if (animationSet == null) return;
+            var spriteNode2 = hudScene.CreateChild("AnimatedSprite2D");
+            AnimatedSprite2D animatedSprite = spriteNode2.CreateComponent<AnimatedSprite2D>();
+            animatedSprite.AnimationSet = animationSet;         // Set animation
+            animatedSprite.SetAnimation("idle", LoopMode2D.LM_DEFAULT);
+            spriteNode2.SetPosition2D(new Vector2(halfWidth - 0.4f, halfHeight - 0.4f));
+
+            // (bullet) mass, speed size feature huds
+            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill1.png") );
+            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill2.png") );
+            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill3.png") );
+            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill4.png") );
+            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill5.png") );
+            filler.Push ( cache.GetResource<Sprite2D>("Textures/hudfill6.png") );
+
+            Sprite2D spritem = cache.GetResource<Sprite2D>("Textures/hudmass.png");
+            Node hudm = hudScene.CreateChild("hudMass");
+            hudm.SetScale2D(new Vector2(hscal,hscal));
+            hudm.SetPosition2D( new Vector2( 0f - (halfWidth/3.0f), halfHeight - 0.4f)); 
+            StaticSprite2D hudSpritem = hudm.CreateComponent<StaticSprite2D>();
+            hudSpritem.SetSprite(spritem);
+            hudSpritem.SetAlpha(0.9f);
+            hudSpritem.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
+            hudSpritem.SetOrderInLayer(3); 
+            Node hudfm = hudm.CreateChild("hudMassFill");
+            hudfm.SetScale2D(new Vector2(1f,1f));
+            hudfm.SetPosition2D( new Vector2( 0f, 0f)); 
+            StaticSprite2D hudSpritefm = hudfm.CreateComponent<StaticSprite2D>();
+            hudSpritefm.SetSprite(filler[0]);
+            hudSpritefm.SetAlpha(0.9f);
+            hudSpritefm.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
+            hudSpritefm.SetOrderInLayer(-3); 
+
+            Sprite2D sprites = cache.GetResource<Sprite2D>("Textures/hudspeed.png");
+            Node huds = hudScene.CreateChild("hudSpeed");
+            huds.SetScale2D(new Vector2(hscal,hscal));
+            huds.SetPosition2D( new Vector2( 0f, halfHeight - 0.4f)); 
+            StaticSprite2D hudSprites = huds.CreateComponent<StaticSprite2D>();
+            hudSprites.SetSprite(sprites);
+            hudSprites.SetAlpha(0.9f);
+            hudSprites.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
+            hudSprites.SetOrderInLayer(3); 
+            Node hudsm = huds.CreateChild("hudSpeedFill");
+            hudsm.SetScale2D(new Vector2(1f,1f));
+            hudsm.SetPosition2D( new Vector2( 0f, 0f)); 
+            StaticSprite2D hudSpritesm = hudsm.CreateComponent<StaticSprite2D>();
+            hudSpritesm.SetSprite(filler[0]);
+            hudSpritesm.SetAlpha(0.9f);
+            hudSpritesm.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
+            hudSpritesm.SetOrderInLayer(-3); 
+
+            Sprite2D spritez = cache.GetResource<Sprite2D>("Textures/hudsize.png");
+            Node hudz = hudScene.CreateChild("hudSize");
+            hudz.SetScale2D(new Vector2(hscal,hscal));
+            hudz.SetPosition2D( new Vector2( 0f + (halfWidth/3.0f), halfHeight - 0.4f)); 
+            StaticSprite2D hudSpritez = hudz.CreateComponent<StaticSprite2D>();
+            hudSpritez.SetSprite(spritez);
+            hudSpritez.SetAlpha(0.9f);
+            hudSpritez.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
+            hudSpritez.SetOrderInLayer(3); 
+            Node hudzm = hudz.CreateChild("hudSizeFill");
+            hudzm.SetScale2D(new Vector2(1f,1f));
+            hudzm.SetPosition2D( new Vector2( 0f, 0f)); 
+            StaticSprite2D hudSpritezm = hudzm.CreateComponent<StaticSprite2D>();
+            hudSpritezm.SetSprite(filler[0]);
+            hudSpritezm.SetAlpha(0.9f);
+            hudSpritezm.SetBlendMode(AtomicEngine.BlendMode.BLEND_ALPHA);
+            hudSpritezm.SetOrderInLayer(-3);
+        }
+
+        void UpdateMassHud ( int value )
+        {
+            Node xNode = hudScene.GetChild("hudMass", true);
+            if (xNode != null) {
+                Node fillx = xNode.GetChild("hudMassFill");
+                if (fillx != null) {
+                    StaticSprite2D hudSprite = fillx.GetComponent<StaticSprite2D>();
+                    hudSprite.SetSprite(filler[value]);
+                }
+            }
+        }
+
+        void UpdateSpeedHud ( int value )
+        {
+            Node xNode = hudScene.GetChild("hudSpeed", true);
+            if (xNode != null) {
+                Node fillx = xNode.GetChild("hudSpeedFill");
+                if (fillx != null) {
+                    StaticSprite2D hudSprite = fillx.GetComponent<StaticSprite2D>();
+                    hudSprite.SetSprite(filler[value]);
+                }
+            }
+        }
+
+        void UpdateSizeHud ( int value )
+        {
+            Node xNode = hudScene.GetChild("hudSize", true);
+            if (xNode != null) {
+                Node fillx = xNode.GetChild("hudSizeFill");
+                if (fillx != null) {
+                    StaticSprite2D hudSprite = fillx.GetComponent<StaticSprite2D>();
+                    hudSprite.SetSprite(filler[value]);
+                }
+            }
+        }
+
+        void SpawnObject()
+        {
+            var cache = GetSubsystem<ResourceCache>();
+
+            Node boxNode = scene.CreateChild("Sphere");
+            boxNode.Position = CameraNode.Position;
+            boxNode.Rotation = CameraNode.Rotation;
+            boxNode.SetScale(bulletSize[sizeCount]);
+            StaticModel boxObject = boxNode.CreateComponent<StaticModel>();
+            boxObject.Model = cache.Get<Model>("Models/Sphere.mdl");
+            boxObject.SetMaterial(cache.Get<Material>("Materials/StoneSmall.xml"));
+            boxObject.CastShadows = true;
+
+            RigidBody body = boxNode.CreateComponent<RigidBody>();
+            body.Mass = bulletMass[massCount];
+            body.RollingFriction = 0.15f;
+            CollisionShape shape = boxNode.CreateComponent<CollisionShape>();
+            shape.SetSphere(1.0f, Vector3.Zero, Quaternion.Identity);
+
+            float objectVelocity = bulletSpeed[speedCount];
+
+            // Set initial velocity for the RigidBody based on camera forward vector. Add also a slight up component
+            // to overcome gravity better
+            body.SetLinearVelocity(CameraNode.Rotation * new Vector3(0.0f, bulletArc, 1.0f) * objectVelocity);
+        }
+
+        void CleanUpSome() // destroy the bullets when they get far enough away
+        {
+            Node cam = CameraNode; // note - the camera isnt in the scene
+            if ( cam == null )
+                return;
+            var mm = new Vector <Node>();
+            scene.GetChildrenWithName ( mm, "Sphere", true);
+            for ( int ii=0; ii<mm.Size; ii++ ) { 
+              float dist = ( mm[ii].GetWorldPosition() - cam.GetWorldPosition() ).Length;
+                if (dist > 270.0f) {
+                    mm[ii].Remove ();
+                }
+            }
+        }
+    }
+
+}

+ 303 - 0
FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Scripts/Sample.cs

@@ -0,0 +1,303 @@
+//
+// Copyright (c) 2008-2015 the Urho3D project.
+// Copyright (c) 2015 Xamarin Inc
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+using System;
+using System.Globalization;
+using AtomicEngine;
+
+namespace FeatureExamples
+{
+    public class Sample : NETScriptObject
+    {
+        protected const float PixelSize = 0.01f;
+        protected const float TouchSensitivity = 2;
+        protected float Yaw { get; set; }
+        protected float Pitch { get; set; }
+        protected bool TouchEnabled { get; set; }
+        protected Node CameraNode { get; set; }
+        protected UIEditField label { get; set; }
+
+        protected UIView UIView { get; set; }
+
+        protected Sample()
+        {
+            UIView = SampleSelector.UIView;
+        }
+
+        protected void Exit() { GetSubsystem<Engine>().Exit(); }
+
+        static readonly Random random = new Random();
+        /// Return a random float between 0.0 (inclusive) and 1.0 (exclusive.)
+        public static float NextRandom() { return (float)random.NextDouble(); }
+        /// Return a random float between 0.0 and range, inclusive from both ends.
+        public static float NextRandom(float range) { return (float)random.NextDouble() * range; }
+        /// Return a random float between min and max, inclusive from both ends.
+        public static float NextRandom(float min, float max) { return (float)((random.NextDouble() * (max - min)) + min); }
+        /// Return a random integer between min and max - 1.
+        public static int NextRandom(int min, int max) { return random.Next(min, max); }
+
+
+        public virtual void Start()
+        {
+            SubscribeToEvent<UpdateEvent>((e) => { Update(e.TimeStep); });
+
+            SubscribeToEvent<KeyDownEvent>(HandleKeyDown);
+
+        }
+
+        protected virtual void Update(float timeStep)
+        {
+            MoveCameraByTouches(timeStep);
+        }
+
+        /// <summary>
+        /// Move camera for 2D samples
+        /// </summary>
+        protected void SimpleMoveCamera2D(float timeStep)
+        {
+            // Movement speed as world units per second
+            const float moveSpeed = 4.0f;
+
+            var input = GetSubsystem<Input>();
+
+            // Read WASD keys and move the camera scene node to the corresponding direction if they are pressed
+            if (input.GetKeyDown(Constants.KEY_W)) CameraNode.Translate(Vector3.UnitY * moveSpeed * timeStep);
+            if (input.GetKeyDown(Constants.KEY_S)) CameraNode.Translate(-Vector3.UnitY * moveSpeed * timeStep);
+            if (input.GetKeyDown(Constants.KEY_A)) CameraNode.Translate(-Vector3.UnitX * moveSpeed * timeStep);
+            if (input.GetKeyDown(Constants.KEY_D)) CameraNode.Translate(Vector3.UnitX * moveSpeed * timeStep);
+
+            if (input.GetKeyDown(Constants.KEY_PAGEUP))
+            {
+                Camera camera = CameraNode.GetComponent<Camera>();
+                camera.Zoom = camera.Zoom * 1.01f;
+            }
+
+            if (input.GetKeyDown(Constants.KEY_PAGEDOWN))
+            {
+                Camera camera = CameraNode.GetComponent<Camera>();
+                camera.Zoom = camera.Zoom * 0.99f;
+            }
+        }
+
+        /// <summary>
+        /// Move camera for 3D samples
+        /// </summary>
+        protected void SimpleMoveCamera3D(float timeStep, float moveSpeed = 10.0f)
+        {
+            const float mouseSensitivity = .1f;
+
+            var input = GetSubsystem<Input>();
+
+            var mouseMove = input.MouseMove;
+            Yaw += mouseSensitivity * mouseMove.X;
+            Pitch += mouseSensitivity * mouseMove.Y;
+            Pitch = MathHelper.Clamp(Pitch, -90, 90);
+
+            CameraNode.Rotation = new Quaternion(Pitch, Yaw, 0);
+
+            if (input.GetKeyDown(Constants.KEY_W)) CameraNode.Translate(Vector3.UnitZ * moveSpeed * timeStep);
+            if (input.GetKeyDown(Constants.KEY_S)) CameraNode.Translate(-Vector3.UnitZ * moveSpeed * timeStep);
+            if (input.GetKeyDown(Constants.KEY_A)) CameraNode.Translate(-Vector3.UnitX * moveSpeed * timeStep);
+            if (input.GetKeyDown(Constants.KEY_D)) CameraNode.Translate(Vector3.UnitX * moveSpeed * timeStep);
+        }
+
+        protected void MoveCameraByTouches(float timeStep)
+        {
+            if (!TouchEnabled || CameraNode == null)
+                return;
+
+            var input = GetSubsystem<Input>();
+            for (uint i = 0, num = input.NumTouches; i < num; ++i)
+            {
+                var delta = input.GetTouchDelta(i);
+
+                if (delta.X != 0 || delta.Y != 0)
+                {
+                    var camera = CameraNode.GetComponent<Camera>();
+
+                    if (camera == null)
+                        return;
+
+                    var graphics = GetSubsystem<Graphics>();
+                    Yaw += TouchSensitivity * camera.Fov / graphics.Height * delta.X;
+                    Pitch += TouchSensitivity * camera.Fov / graphics.Height * delta.Y;
+                    CameraNode.Rotation = new Quaternion(Pitch, Yaw, 0);
+                }
+                else
+                {
+                    //var cursor = UI.Cursor;
+
+                    //if (cursor != null && cursor.Visible)
+                    //    cursor.Position = state.Position;
+                }
+            }
+        }
+
+        protected void SimpleCreateInstructionsWithWasd(string extra = "")
+        {
+            SimpleCreateInstructions("Use WASD keys and mouse/touch to move" + extra);
+        }
+
+        protected void SimpleCreateInstructions(string text = "")
+        {
+
+            var layout = new UILayout();
+
+            layout.Rect = UIView.Rect;
+
+            layout.LayoutPosition = UI_LAYOUT_POSITION.UI_LAYOUT_POSITION_RIGHT_BOTTOM;
+            layout.LayoutDistributionPosition = UI_LAYOUT_DISTRIBUTION_POSITION.UI_LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM;
+
+            var fontDesc = new UIFontDescription();
+            fontDesc.Id = "Vera";
+            fontDesc.Size = 18;
+
+            label = new UIEditField();
+            label.FontDescription = fontDesc;
+            label.ReadOnly = true;
+            label.Multiline = true;
+            label.AdaptToContentSize = true;
+            label.Text = text;
+            layout.AddChild(label);
+
+            UIView.AddChild(layout);
+
+        }
+
+        public void SetInstructions(string text = "")
+        {
+            if ( label != null )
+                label.Text = text;
+        }
+
+        void CreateLogo()
+        {
+        }
+
+        void SetWindowAndTitleIcon()
+        {
+        }
+
+        void CreateConsoleAndDebugHud()
+        {
+        }
+
+        protected void BackToSelector()
+        {
+            GetSubsystem<Input>().SetMouseVisible(true);
+            UnsubscribeFromAllEvents();
+            var renderer = GetSubsystem<Renderer>();
+            for (uint i = 0; i <  renderer.NumViewports; i++)
+            {
+                renderer.SetViewport(i, null);
+            }
+            SampleSelector.sampleRef = null;
+            SampleSelector.UIView.DeleteAllChildren();
+            new SampleSelector();
+        }
+
+
+        void HandleKeyDown(KeyDownEvent e)
+        {
+            var renderer = GetSubsystem<Renderer>();
+
+            switch (e.Key)
+            {
+                case Constants.KEY_ESCAPE:
+                    BackToSelector();
+                    return;
+                case Constants.KEY_F1:
+                    GetSubsystem<UI>().ToggleConsole();
+                    return;
+                case Constants.KEY_F2:
+                    GetSubsystem<UI>().ToggleDebugHud();
+                    return;
+            }
+
+            switch (e.Key)
+            {
+                case Constants.KEY_1:
+                    var quality = renderer.TextureQuality;
+                    ++quality;
+                    if (quality > 2)
+                        quality = 0;
+                    renderer.TextureQuality = quality;
+                    break;
+
+                case Constants.KEY_2:
+                    var mquality = renderer.MaterialQuality;
+                    ++mquality;
+                    if (mquality > 2)
+                        mquality = 0;
+                    renderer.MaterialQuality = mquality;
+                    break;
+
+                case Constants.KEY_3:
+                    renderer.SpecularLighting = !renderer.SpecularLighting;
+                    break;
+
+                case Constants.KEY_4:
+                    renderer.DrawShadows = !renderer.DrawShadows;
+                    break;
+
+                case Constants.KEY_5:
+                    var shadowMapSize = renderer.ShadowMapSize;
+                    shadowMapSize *= 2;
+                    if (shadowMapSize > 2048)
+                        shadowMapSize = 512;
+                    renderer.ShadowMapSize = shadowMapSize;
+                    break;
+
+                // shadow depth and filtering quality
+                case Constants.KEY_6:
+                    var q = (int)renderer.ShadowQuality++;
+                    if (q > 3)
+                        q = 0;
+                    renderer.ShadowQuality = (ShadowQuality)q;
+                    break;
+
+                // occlusion culling
+                case Constants.KEY_7:
+                    var o = !(renderer.MaxOccluderTriangles > 0);
+                    renderer.MaxOccluderTriangles = o ? 5000 : 0;
+                    break;
+
+                // instancing
+                case Constants.KEY_8:
+                    renderer.DynamicInstancing = !renderer.DynamicInstancing;
+                    break;
+
+                case Constants.KEY_9:
+                    Image screenshot = new Image();
+                    GetSubsystem<Graphics>().TakeScreenShot(screenshot);
+                    screenshot.SavePNG(GetSubsystem<FileSystem>().ProgramDir + $"Data/Screenshot_{GetType().Name}_{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss", CultureInfo.InvariantCulture)}.png");
+                    break;
+            }
+        }
+
+        void InitTouchInput()
+        {
+            TouchEnabled = true;
+        }
+    }
+}

+ 0 - 0
FeatureExamples/CSharp/Resources/Textures/hudfill1.png → FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill1.png


+ 0 - 0
FeatureExamples/CSharp/Resources/Textures/hudfill2.png → FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill2.png


+ 0 - 0
FeatureExamples/CSharp/Resources/Textures/hudfill3.png → FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill3.png


+ 0 - 0
FeatureExamples/CSharp/Resources/Textures/hudfill4.png → FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill4.png


+ 0 - 0
FeatureExamples/CSharp/Resources/Textures/hudfill5.png → FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill5.png


+ 0 - 0
FeatureExamples/CSharp/Resources/Textures/hudfill6.png → FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudfill6.png


+ 0 - 0
FeatureExamples/CSharp/Resources/Textures/hudmass.png → FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudmass.png


+ 0 - 0
FeatureExamples/CSharp/Resources/Textures/hudsize.png → FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudsize.png


+ 0 - 0
FeatureExamples/CSharp/Resources/Textures/hudspeed.png → FeatureExamples/Mods/Ragdoll2DHud/CSharp/Resources/Textures/hudspeed.png


+ 6 - 0
FeatureExamples/Mods/Ragdoll2DHud/README.md

@@ -0,0 +1,6 @@
+
+#### Ragdoll Physics 2D HUD
+
+This example shows the technique of using a 2D viewport as a hud, having the same real estate as the 3D viewport.
+
+The non-clearing renderpath makes it all work, and then you just operate both scenes as separate but equal entities. I added the rotating coin to make sure animated sprites work. Using the "U" key, you can change the mass of the ball, "I" = Speed, "O" = Size, then you can see the appropriate HUD change in response to your selection. Then fire at will, or Jack, as it were. When Jack is hit, he gets the donuts blown out of him. Once all the Jacks are down, you can press "R" to restart the "level".

+ 12 - 0
FeatureExamples/README.md

@@ -0,0 +1,12 @@
+
+#### Feature Examples
+
+This example showcases and provides example usage of specific Atomic technology features.
+
+The examples are minimal and strive to use minimal API and concise code.
+
+##### Feature Example Mods
+
+In the Mods subdirectory, are modifications of the feature example which show extended usage and subsystem integration.
+
+A mod can be applied, simply by copying the mod folder into your project's root folder.