瀏覽代碼

Merge remote-tracking branch 'hdunderscore/input_mousemode_update'

Lasse Öörni 9 年之前
父節點
當前提交
5246f74984
共有 100 個文件被更改,包括 1095 次插入258 次删除
  1. 3 0
      Source/Samples/01_HelloWorld/HelloWorld.cpp
  2. 6 2
      Source/Samples/02_HelloGUI/HelloGUI.cpp
  3. 3 0
      Source/Samples/03_Sprites/Sprites.cpp
  4. 3 0
      Source/Samples/04_StaticScene/StaticScene.cpp
  5. 3 0
      Source/Samples/05_AnimatingScene/AnimatingScene.cpp
  6. 3 0
      Source/Samples/06_SkeletalAnimation/SkeletalAnimation.cpp
  7. 3 0
      Source/Samples/07_Billboards/Billboards.cpp
  8. 3 0
      Source/Samples/08_Decals/Decals.cpp
  9. 3 0
      Source/Samples/09_MultipleViewports/MultipleViewports.cpp
  10. 3 0
      Source/Samples/10_RenderToTexture/RenderToTexture.cpp
  11. 3 0
      Source/Samples/11_Physics/Physics.cpp
  12. 3 0
      Source/Samples/12_PhysicsStressTest/PhysicsStressTest.cpp
  13. 3 0
      Source/Samples/13_Ragdolls/Ragdolls.cpp
  14. 3 0
      Source/Samples/14_SoundEffects/SoundEffects.cpp
  15. 3 0
      Source/Samples/15_Navigation/Navigation.cpp
  16. 3 0
      Source/Samples/16_Chat/Chat.cpp
  17. 3 0
      Source/Samples/17_SceneReplication/SceneReplication.cpp
  18. 3 0
      Source/Samples/18_CharacterDemo/CharacterDemo.cpp
  19. 3 0
      Source/Samples/19_VehicleDemo/VehicleDemo.cpp
  20. 3 0
      Source/Samples/20_HugeObjectCount/HugeObjectCount.cpp
  21. 3 0
      Source/Samples/21_AngelScriptIntegration/AngelScriptIntegration.cpp
  22. 3 0
      Source/Samples/22_LuaIntegration/LuaIntegration.cpp
  23. 3 0
      Source/Samples/23_Water/Water.cpp
  24. 3 0
      Source/Samples/24_Urho2DSprite/Urho2DSprite.cpp
  25. 4 1
      Source/Samples/25_Urho2DParticle/Urho2DParticle.cpp
  26. 5 1
      Source/Samples/26_ConsoleInput/ConsoleInput.cpp
  27. 3 0
      Source/Samples/27_Urho2DPhysics/Urho2DPhysics.cpp
  28. 3 0
      Source/Samples/28_Urho2DPhysicsRope/Urho2DPhysicsRope.cpp
  29. 3 0
      Source/Samples/29_SoundSynthesis/SoundSynthesis.cpp
  30. 3 0
      Source/Samples/30_LightAnimation/LightAnimation.cpp
  31. 3 0
      Source/Samples/31_MaterialAnimation/MaterialAnimation.cpp
  32. 3 0
      Source/Samples/32_Urho2DConstraints/Urho2DConstraints.cpp
  33. 3 1
      Source/Samples/33_Urho2DSpriterAnimation/Urho2DSpriterAnimation.cpp
  34. 3 0
      Source/Samples/34_DynamicGeometry/DynamicGeometry.cpp
  35. 3 0
      Source/Samples/35_SignedDistanceFieldText/SignedDistanceFieldText.cpp
  36. 3 0
      Source/Samples/36_Urho2DTileMap/Urho2DTileMap.cpp
  37. 3 0
      Source/Samples/37_UIDrag/UIDrag.cpp
  38. 3 0
      Source/Samples/38_SceneAndUILoad/SceneAndUILoad.cpp
  39. 3 0
      Source/Samples/39_CrowdNavigation/CrowdNavigation.cpp
  40. 5 1
      Source/Samples/40_Localization/L10n.cpp
  41. 3 0
      Source/Samples/41_DatabaseDemo/DatabaseDemo.cpp
  42. 11 0
      Source/Samples/Sample.h
  43. 75 6
      Source/Samples/Sample.inl
  44. 17 2
      Source/Urho3D/AngelScript/InputAPI.cpp
  45. 1 1
      Source/Urho3D/Core/ProcessUtils.h
  46. 21 5
      Source/Urho3D/Engine/Console.cpp
  47. 525 191
      Source/Urho3D/Input/Input.cpp
  48. 50 21
      Source/Urho3D/Input/Input.h
  49. 1 0
      Source/Urho3D/Input/InputEvents.h
  50. 4 2
      Source/Urho3D/LuaScript/pkgs/Input/Input.pkg
  51. 4 2
      Source/Urho3D/UI/UI.cpp
  52. 3 0
      bin/Data/LuaScripts/01_HelloWorld.lua
  53. 3 0
      bin/Data/LuaScripts/02_HelloGUI.lua
  54. 3 0
      bin/Data/LuaScripts/03_Sprites.lua
  55. 3 0
      bin/Data/LuaScripts/04_StaticScene.lua
  56. 3 0
      bin/Data/LuaScripts/05_AnimatingScene.lua
  57. 3 0
      bin/Data/LuaScripts/06_SkeletalAnimation.lua
  58. 3 0
      bin/Data/LuaScripts/07_Billboards.lua
  59. 10 1
      bin/Data/LuaScripts/08_Decals.lua
  60. 3 0
      bin/Data/LuaScripts/09_MultipleViewports.lua
  61. 3 0
      bin/Data/LuaScripts/10_RenderToTexture.lua
  62. 3 0
      bin/Data/LuaScripts/11_Physics.lua
  63. 3 0
      bin/Data/LuaScripts/12_PhysicsStressTest.lua
  64. 3 0
      bin/Data/LuaScripts/13_Ragdolls.lua
  65. 3 0
      bin/Data/LuaScripts/14_SoundEffects.lua
  66. 10 1
      bin/Data/LuaScripts/15_Navigation.lua
  67. 3 0
      bin/Data/LuaScripts/16_Chat.lua
  68. 10 1
      bin/Data/LuaScripts/17_SceneReplication.lua
  69. 3 0
      bin/Data/LuaScripts/18_CharacterDemo.lua
  70. 3 1
      bin/Data/LuaScripts/19_VehicleDemo.lua
  71. 3 0
      bin/Data/LuaScripts/20_HugeObjectCount.lua
  72. 3 0
      bin/Data/LuaScripts/23_Water.lua
  73. 3 0
      bin/Data/LuaScripts/24_Urho2DSprite.lua
  74. 3 0
      bin/Data/LuaScripts/25_Urho2DParticle.lua
  75. 3 0
      bin/Data/LuaScripts/26_ConsoleInput.lua
  76. 3 0
      bin/Data/LuaScripts/27_Urho2DPhysics.lua
  77. 3 0
      bin/Data/LuaScripts/28_Urho2DPhysicsRope.lua
  78. 3 0
      bin/Data/LuaScripts/30_LightAnimation.lua
  79. 3 0
      bin/Data/LuaScripts/31_MaterialAnimation.lua
  80. 2 0
      bin/Data/LuaScripts/32_Urho2DConstraints.lua
  81. 3 0
      bin/Data/LuaScripts/33_Urho2DSpriterAnimation.lua
  82. 8 5
      bin/Data/LuaScripts/34_DynamicGeometry.lua
  83. 4 1
      bin/Data/LuaScripts/35_SignedDistanceFieldText.lua
  84. 3 0
      bin/Data/LuaScripts/36_Urho2DTileMap.lua
  85. 4 1
      bin/Data/LuaScripts/37_UIDrag.lua
  86. 10 1
      bin/Data/LuaScripts/38_SceneAndUILoad.lua
  87. 10 1
      bin/Data/LuaScripts/39_CrowdNavigation.lua
  88. 3 1
      bin/Data/LuaScripts/40_Localization.lua
  89. 3 0
      bin/Data/LuaScripts/41_DatabaseDemo.lua
  90. 63 7
      bin/Data/LuaScripts/Utilities/Sample.lua
  91. 3 0
      bin/Data/Scripts/01_HelloWorld.as
  92. 3 0
      bin/Data/Scripts/02_HelloGUI.as
  93. 3 0
      bin/Data/Scripts/03_Sprites.as
  94. 3 0
      bin/Data/Scripts/04_StaticScene.as
  95. 3 0
      bin/Data/Scripts/05_AnimatingScene.as
  96. 3 0
      bin/Data/Scripts/06_SkeletalAnimation.as
  97. 3 0
      bin/Data/Scripts/07_Billboards.as
  98. 10 1
      bin/Data/Scripts/08_Decals.as
  99. 3 0
      bin/Data/Scripts/09_MultipleViewports.as
  100. 3 0
      bin/Data/Scripts/10_RenderToTexture.as

+ 3 - 0
Source/Samples/01_HelloWorld/HelloWorld.cpp

@@ -51,6 +51,9 @@ void HelloWorld::Start()
     // like the ScreenMode event sent by the Graphics subsystem when opening the application window. To catch those as well we
     // like the ScreenMode event sent by the Graphics subsystem when opening the application window. To catch those as well we
     // could subscribe in the constructor instead.
     // could subscribe in the constructor instead.
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void HelloWorld::CreateText()
 void HelloWorld::CreateText()

+ 6 - 2
Source/Samples/02_HelloGUI/HelloGUI.cpp

@@ -71,6 +71,9 @@ void HelloGUI::Start()
 
 
     // Create a draggable Fish
     // Create a draggable Fish
     CreateDraggableFish();
     CreateDraggableFish();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void HelloGUI::InitControls()
 void HelloGUI::InitControls()
@@ -181,7 +184,7 @@ void HelloGUI::CreateDraggableFish()
 
 
 void HelloGUI::HandleDragBegin(StringHash eventType, VariantMap& eventData)
 void HelloGUI::HandleDragBegin(StringHash eventType, VariantMap& eventData)
 {
 {
-    // Get UIElement relative position where input (touch or click) occured (top-left = IntVector2(0,0))
+    // Get UIElement relative position where input (touch or click) occurred (top-left = IntVector2(0,0))
     dragBeginPosition_ = IntVector2(eventData["ElementX"].GetInt(), eventData["ElementY"].GetInt());
     dragBeginPosition_ = IntVector2(eventData["ElementX"].GetInt(), eventData["ElementY"].GetInt());
 }
 }
 
 
@@ -198,7 +201,8 @@ void HelloGUI::HandleDragEnd(StringHash eventType, VariantMap& eventData) // For
 
 
 void HelloGUI::HandleClosePressed(StringHash eventType, VariantMap& eventData)
 void HelloGUI::HandleClosePressed(StringHash eventType, VariantMap& eventData)
 {
 {
-    engine_->Exit();
+    if (GetPlatform() != "Web")
+        engine_->Exit();
 }
 }
 
 
 void HelloGUI::HandleControlClicked(StringHash eventType, VariantMap& eventData)
 void HelloGUI::HandleControlClicked(StringHash eventType, VariantMap& eventData)

+ 3 - 0
Source/Samples/03_Sprites/Sprites.cpp

@@ -54,6 +54,9 @@ void Sprites::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void Sprites::CreateSprites()
 void Sprites::CreateSprites()

+ 3 - 0
Source/Samples/04_StaticScene/StaticScene.cpp

@@ -63,6 +63,9 @@ void StaticScene::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void StaticScene::CreateScene()
 void StaticScene::CreateScene()

+ 3 - 0
Source/Samples/05_AnimatingScene/AnimatingScene.cpp

@@ -67,6 +67,9 @@ void AnimatingScene::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void AnimatingScene::CreateScene()
 void AnimatingScene::CreateScene()

+ 3 - 0
Source/Samples/06_SkeletalAnimation/SkeletalAnimation.cpp

@@ -71,6 +71,9 @@ void SkeletalAnimation::Start()
 
 
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_ABSOLUTE);
 }
 }
 
 
 void SkeletalAnimation::CreateScene()
 void SkeletalAnimation::CreateScene()

+ 3 - 0
Source/Samples/07_Billboards/Billboards.cpp

@@ -68,6 +68,9 @@ void Billboards::Start()
 
 
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_ABSOLUTE);
 }
 }
 
 
 void Billboards::CreateScene()
 void Billboards::CreateScene()

+ 3 - 0
Source/Samples/08_Decals/Decals.cpp

@@ -68,6 +68,9 @@ void Decals::Start()
 
 
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void Decals::CreateScene()
 void Decals::CreateScene()

+ 3 - 0
Source/Samples/09_MultipleViewports/MultipleViewports.cpp

@@ -68,6 +68,9 @@ void MultipleViewports::Start()
 
 
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_ABSOLUTE);
 }
 }
 
 
 void MultipleViewports::CreateScene()
 void MultipleViewports::CreateScene()

+ 3 - 0
Source/Samples/10_RenderToTexture/RenderToTexture.cpp

@@ -70,6 +70,9 @@ void RenderToTexture::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void RenderToTexture::CreateScene()
 void RenderToTexture::CreateScene()

+ 3 - 0
Source/Samples/11_Physics/Physics.cpp

@@ -72,6 +72,9 @@ void Physics::Start()
 
 
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void Physics::CreateScene()
 void Physics::CreateScene()

+ 3 - 0
Source/Samples/12_PhysicsStressTest/PhysicsStressTest.cpp

@@ -72,6 +72,9 @@ void PhysicsStressTest::Start()
 
 
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void PhysicsStressTest::CreateScene()
 void PhysicsStressTest::CreateScene()

+ 3 - 0
Source/Samples/13_Ragdolls/Ragdolls.cpp

@@ -74,6 +74,9 @@ void Ragdolls::Start()
 
 
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_ABSOLUTE);
 }
 }
 
 
 void Ragdolls::CreateScene()
 void Ragdolls::CreateScene()

+ 3 - 0
Source/Samples/14_SoundEffects/SoundEffects.cpp

@@ -80,6 +80,9 @@ void SoundEffects::Start()
 
 
     // Create the user interface
     // Create the user interface
     CreateUI();
     CreateUI();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void SoundEffects::CreateUI()
 void SoundEffects::CreateUI()

+ 3 - 0
Source/Samples/15_Navigation/Navigation.cpp

@@ -68,6 +68,9 @@ void Navigation::Start()
 
 
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void Navigation::CreateScene()
 void Navigation::CreateScene()

+ 3 - 0
Source/Samples/16_Chat/Chat.cpp

@@ -75,6 +75,9 @@ void Chat::Start()
 
 
     // Subscribe to UI and network events
     // Subscribe to UI and network events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void Chat::CreateUI()
 void Chat::CreateUI()

+ 3 - 0
Source/Samples/17_SceneReplication/SceneReplication.cpp

@@ -90,6 +90,9 @@ void SceneReplication::Start()
 
 
     // Hook up to necessary events
     // Hook up to necessary events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void SceneReplication::CreateScene()
 void SceneReplication::CreateScene()

+ 3 - 0
Source/Samples/18_CharacterDemo/CharacterDemo.cpp

@@ -81,6 +81,9 @@ void CharacterDemo::Start()
 
 
     // Subscribe to necessary events
     // Subscribe to necessary events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void CharacterDemo::CreateScene()
 void CharacterDemo::CreateScene()

+ 3 - 0
Source/Samples/19_VehicleDemo/VehicleDemo.cpp

@@ -76,6 +76,9 @@ void VehicleDemo::Start()
 
 
     // Subscribe to necessary events
     // Subscribe to necessary events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void VehicleDemo::CreateScene()
 void VehicleDemo::CreateScene()

+ 3 - 0
Source/Samples/20_HugeObjectCount/HugeObjectCount.cpp

@@ -67,6 +67,9 @@ void HugeObjectCount::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void HugeObjectCount::CreateScene()
 void HugeObjectCount::CreateScene()

+ 3 - 0
Source/Samples/21_AngelScriptIntegration/AngelScriptIntegration.cpp

@@ -69,6 +69,9 @@ void AngelScriptIntegration::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void AngelScriptIntegration::CreateScene()
 void AngelScriptIntegration::CreateScene()

+ 3 - 0
Source/Samples/22_LuaIntegration/LuaIntegration.cpp

@@ -70,6 +70,9 @@ void LuaIntegration::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void LuaIntegration::CreateScene()
 void LuaIntegration::CreateScene()

+ 3 - 0
Source/Samples/23_Water/Water.cpp

@@ -70,6 +70,9 @@ void Water::Start()
 
 
     // Hook up to the frame update event
     // Hook up to the frame update event
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void Water::CreateScene()
 void Water::CreateScene()

+ 3 - 0
Source/Samples/24_Urho2DSprite/Urho2DSprite.cpp

@@ -69,6 +69,9 @@ void Urho2DSprite::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void Urho2DSprite::CreateScene()
 void Urho2DSprite::CreateScene()

+ 4 - 1
Source/Samples/25_Urho2DParticle/Urho2DParticle.cpp

@@ -51,7 +51,7 @@ void Urho2DParticle::Start()
     // Execute base class startup
     // Execute base class startup
     Sample::Start();
     Sample::Start();
 
 
-    // Set mouse visibile
+    // Set mouse visible
     Input* input = GetSubsystem<Input>();
     Input* input = GetSubsystem<Input>();
     input->SetMouseVisible(true);
     input->SetMouseVisible(true);
 
 
@@ -66,6 +66,9 @@ void Urho2DParticle::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+    
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void Urho2DParticle::CreateScene()
 void Urho2DParticle::CreateScene()

+ 5 - 1
Source/Samples/26_ConsoleInput/ConsoleInput.cpp

@@ -70,6 +70,7 @@ void ConsoleInput::Start()
 
 
     // Subscribe key down event
     // Subscribe key down event
     SubscribeToEvent(E_KEYDOWN, URHO3D_HANDLER(ConsoleInput, HandleEscKeyDown));
     SubscribeToEvent(E_KEYDOWN, URHO3D_HANDLER(ConsoleInput, HandleEscKeyDown));
+    UnsubscribeFromEvent(E_KEYUP);
 
 
     // Hide logo to make room for the console
     // Hide logo to make room for the console
     SetLogoVisible(false);
     SetLogoVisible(false);
@@ -86,6 +87,9 @@ void ConsoleInput::Start()
     // Show OS mouse cursor
     // Show OS mouse cursor
     GetSubsystem<Input>()->SetMouseVisible(true);
     GetSubsystem<Input>()->SetMouseVisible(true);
 
 
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
+
     // Open the operating system console window (for stdin / stdout) if not open yet
     // Open the operating system console window (for stdin / stdout) if not open yet
     OpenConsoleWindow();
     OpenConsoleWindow();
 
 
@@ -114,7 +118,7 @@ void ConsoleInput::HandleUpdate(StringHash eventType, VariantMap& eventData)
 void ConsoleInput::HandleEscKeyDown(StringHash eventType, VariantMap& eventData)
 void ConsoleInput::HandleEscKeyDown(StringHash eventType, VariantMap& eventData)
 {
 {
     // Unlike the other samples, exiting the engine when ESC is pressed instead of just closing the console
     // Unlike the other samples, exiting the engine when ESC is pressed instead of just closing the console
-    if (eventData[KeyDown::P_KEY].GetInt() == KEY_ESC)
+    if (eventData[KeyDown::P_KEY].GetInt() == KEY_ESC && GetPlatform() != "Web")
         engine_->Exit();
         engine_->Exit();
 }
 }
 
 

+ 3 - 0
Source/Samples/27_Urho2DPhysics/Urho2DPhysics.cpp

@@ -70,6 +70,9 @@ void Urho2DPhysics::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void Urho2DPhysics::CreateScene()
 void Urho2DPhysics::CreateScene()

+ 3 - 0
Source/Samples/28_Urho2DPhysicsRope/Urho2DPhysicsRope.cpp

@@ -68,6 +68,9 @@ void Urho2DPhysicsRope::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void Urho2DPhysicsRope::CreateScene()
 void Urho2DPhysicsRope::CreateScene()

+ 3 - 0
Source/Samples/29_SoundSynthesis/SoundSynthesis.cpp

@@ -67,6 +67,9 @@ void SoundSynthesis::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void SoundSynthesis::CreateSound()
 void SoundSynthesis::CreateSound()

+ 3 - 0
Source/Samples/30_LightAnimation/LightAnimation.cpp

@@ -65,6 +65,9 @@ void LightAnimation::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void LightAnimation::CreateScene()
 void LightAnimation::CreateScene()

+ 3 - 0
Source/Samples/31_MaterialAnimation/MaterialAnimation.cpp

@@ -64,6 +64,9 @@ void MaterialAnimation::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void MaterialAnimation::CreateScene()
 void MaterialAnimation::CreateScene()

+ 3 - 0
Source/Samples/32_Urho2DConstraints/Urho2DConstraints.cpp

@@ -88,6 +88,9 @@ void Urho2DConstraints::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void Urho2DConstraints::CreateScene()
 void Urho2DConstraints::CreateScene()

+ 3 - 1
Source/Samples/33_Urho2DSpriterAnimation/Urho2DSpriterAnimation.cpp

@@ -61,6 +61,9 @@ void Urho2DSpriterAnimation::Start()
     // Setup the viewport for displaying the scene
     // Setup the viewport for displaying the scene
     SetupViewport();
     SetupViewport();
 
 
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
+
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
 }
 }
@@ -159,7 +162,6 @@ void Urho2DSpriterAnimation::SubscribeToEvents()
     SubscribeToEvent(E_UPDATE, URHO3D_HANDLER(Urho2DSpriterAnimation, HandleUpdate));
     SubscribeToEvent(E_UPDATE, URHO3D_HANDLER(Urho2DSpriterAnimation, HandleUpdate));
     SubscribeToEvent(E_MOUSEBUTTONDOWN, URHO3D_HANDLER(Urho2DSpriterAnimation, HandleMouseButtonDown));
     SubscribeToEvent(E_MOUSEBUTTONDOWN, URHO3D_HANDLER(Urho2DSpriterAnimation, HandleMouseButtonDown));
 
 
-
     // Unsubscribe the SceneUpdate event from base class to prevent camera pitch and yaw in 2D sample
     // Unsubscribe the SceneUpdate event from base class to prevent camera pitch and yaw in 2D sample
     UnsubscribeFromEvent(E_SCENEUPDATE);
     UnsubscribeFromEvent(E_SCENEUPDATE);
 }
 }

+ 3 - 0
Source/Samples/34_DynamicGeometry/DynamicGeometry.cpp

@@ -71,6 +71,9 @@ void DynamicGeometry::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void DynamicGeometry::CreateScene()
 void DynamicGeometry::CreateScene()

+ 3 - 0
Source/Samples/35_SignedDistanceFieldText/SignedDistanceFieldText.cpp

@@ -64,6 +64,9 @@ void SignedDistanceFieldText::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void SignedDistanceFieldText::CreateScene()
 void SignedDistanceFieldText::CreateScene()

+ 3 - 0
Source/Samples/36_Urho2DTileMap/Urho2DTileMap.cpp

@@ -63,6 +63,9 @@ void Urho2DTileMap::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void Urho2DTileMap::CreateScene()
 void Urho2DTileMap::CreateScene()

+ 3 - 0
Source/Samples/37_UIDrag/UIDrag.cpp

@@ -53,6 +53,9 @@ void UIDrag::Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void UIDrag::CreateGUI()
 void UIDrag::CreateGUI()

+ 3 - 0
Source/Samples/38_SceneAndUILoad/SceneAndUILoad.cpp

@@ -59,6 +59,9 @@ void SceneAndUILoad::Start()
 
 
     // Subscribe to global events for camera movement
     // Subscribe to global events for camera movement
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_RELATIVE);
 }
 }
 
 
 void SceneAndUILoad::CreateScene()
 void SceneAndUILoad::CreateScene()

+ 3 - 0
Source/Samples/39_CrowdNavigation/CrowdNavigation.cpp

@@ -75,6 +75,9 @@ void CrowdNavigation::Start()
 
 
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_ABSOLUTE);
 }
 }
 
 
 void CrowdNavigation::CreateScene()
 void CrowdNavigation::CreateScene()

+ 5 - 1
Source/Samples/40_Localization/L10n.cpp

@@ -62,6 +62,9 @@ void L10n::Start()
 
 
     // Init the user interface
     // Init the user interface
     CreateGUI();
     CreateGUI();
+
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
 }
 }
 
 
 void L10n::InitLocalizationSystem()
 void L10n::InitLocalizationSystem()
@@ -215,7 +218,8 @@ void L10n::HandleChangeLangButtonPressed(StringHash eventType, VariantMap& event
 
 
 void L10n::HandleQuitButtonPressed(StringHash eventType, VariantMap& eventData)
 void L10n::HandleQuitButtonPressed(StringHash eventType, VariantMap& eventData)
 {
 {
-    engine_->Exit();
+    if (GetPlatform() != "Web")
+        engine_->Exit();
 }
 }
 
 
 // You can manually change texts, sprites and other aspects of the game when language is changed
 // You can manually change texts, sprites and other aspects of the game when language is changed

+ 3 - 0
Source/Samples/41_DatabaseDemo/DatabaseDemo.cpp

@@ -79,6 +79,9 @@ void DatabaseDemo::Start()
     // Show OS mouse cursor
     // Show OS mouse cursor
     GetSubsystem<Input>()->SetMouseVisible(true);
     GetSubsystem<Input>()->SetMouseVisible(true);
 
 
+    // Set the mouse mode to use in the sample
+    Sample::InitMouseMode(MM_FREE);
+
     // Open the operating system console window (for stdin / stdout) if not open yet
     // Open the operating system console window (for stdin / stdout) if not open yet
     OpenConsoleWindow();
     OpenConsoleWindow();
 
 

+ 11 - 0
Source/Samples/Sample.h

@@ -23,6 +23,7 @@
 #pragma once
 #pragma once
 
 
 #include <Urho3D/Engine/Application.h>
 #include <Urho3D/Engine/Application.h>
+#include <Urho3D/Input/Input.h>
 
 
 namespace Urho3D
 namespace Urho3D
 {
 {
@@ -69,6 +70,8 @@ protected:
     virtual String GetScreenJoystickPatchString() const { return String::EMPTY; }
     virtual String GetScreenJoystickPatchString() const { return String::EMPTY; }
     /// Initialize touch input on mobile platform.
     /// Initialize touch input on mobile platform.
     void InitTouchInput();
     void InitTouchInput();
+    /// Initialize mouse mode on non-web platform.
+    void InitMouseMode(MouseMode mode);
     /// Control logo visibility.
     /// Control logo visibility.
     void SetLogoVisible(bool enable);
     void SetLogoVisible(bool enable);
 
 
@@ -84,6 +87,8 @@ protected:
     float pitch_;
     float pitch_;
     /// Flag to indicate whether touch input has been enabled.
     /// Flag to indicate whether touch input has been enabled.
     bool touchEnabled_;
     bool touchEnabled_;
+    /// Mouse mode option to use in the sample.
+    MouseMode useMouseMode_;
 
 
 private:
 private:
     /// Create logo.
     /// Create logo.
@@ -92,8 +97,14 @@ private:
     void SetWindowTitleAndIcon();
     void SetWindowTitleAndIcon();
     /// Create console and debug HUD.
     /// Create console and debug HUD.
     void CreateConsoleAndDebugHud();
     void CreateConsoleAndDebugHud();
+    /// 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.
     /// Handle key down event to process key controls common to all samples.
     void HandleKeyDown(StringHash eventType, VariantMap& eventData);
     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.
     /// Handle scene update event to control camera's pitch and yaw for all samples.
     void HandleSceneUpdate(StringHash eventType, VariantMap& eventData);
     void HandleSceneUpdate(StringHash eventType, VariantMap& eventData);
     /// Handle touch begin event to initialize touch input on desktop platform.
     /// Handle touch begin event to initialize touch input on desktop platform.

+ 75 - 6
Source/Samples/Sample.inl

@@ -39,6 +39,7 @@
 #include <Urho3D/Core/Timer.h>
 #include <Urho3D/Core/Timer.h>
 #include <Urho3D/UI/UI.h>
 #include <Urho3D/UI/UI.h>
 #include <Urho3D/Resource/XMLFile.h>
 #include <Urho3D/Resource/XMLFile.h>
+#include <Urho3D/IO/Log.h>
 
 
 Sample::Sample(Context* context) :
 Sample::Sample(Context* context) :
     Application(context),
     Application(context),
@@ -47,7 +48,8 @@ Sample::Sample(Context* context) :
     touchEnabled_(false),
     touchEnabled_(false),
     screenJoystickIndex_(M_MAX_UNSIGNED),
     screenJoystickIndex_(M_MAX_UNSIGNED),
     screenJoystickSettingsIndex_(M_MAX_UNSIGNED),
     screenJoystickSettingsIndex_(M_MAX_UNSIGNED),
-    paused_(false)
+    paused_(false),
+    useMouseMode_(MM_ABSOLUTE)
 {
 {
 }
 }
 
 
@@ -87,6 +89,8 @@ void Sample::Start()
 
 
     // Subscribe key down event
     // Subscribe key down event
     SubscribeToEvent(E_KEYDOWN, URHO3D_HANDLER(Sample, HandleKeyDown));
     SubscribeToEvent(E_KEYDOWN, URHO3D_HANDLER(Sample, HandleKeyDown));
+    // Subscribe key up event
+    SubscribeToEvent(E_KEYUP, URHO3D_HANDLER(Sample, HandleKeyUp));
     // Subscribe scene update event
     // Subscribe scene update event
     SubscribeToEvent(E_SCENEUPDATE, URHO3D_HANDLER(Sample, HandleSceneUpdate));
     SubscribeToEvent(E_SCENEUPDATE, URHO3D_HANDLER(Sample, HandleSceneUpdate));
 }
 }
@@ -115,6 +119,33 @@ void Sample::InitTouchInput()
     input->SetScreenJoystickVisible(screenJoystickSettingsIndex_, true);
     input->SetScreenJoystickVisible(screenJoystickSettingsIndex_, true);
 }
 }
 
 
+void Sample::InitMouseMode(MouseMode mode)
+{
+    useMouseMode_ = mode;
+
+    Input* input = GetSubsystem<Input>();
+
+    if (GetPlatform() != "Web")
+    {
+        if (useMouseMode_ == MM_FREE)
+            input->SetMouseVisible(true);
+
+        Console* console = GetSubsystem<Console>();
+        if (useMouseMode_ != MM_ABSOLUTE)
+        {
+            input->SetMouseMode(useMouseMode_);
+            if (console && console->IsVisible())
+                input->SetMouseMode(MM_ABSOLUTE, true);
+        }
+    }
+    else
+    {
+        input->SetMouseVisible(true);
+        SubscribeToEvent(E_MOUSEBUTTONDOWN, URHO3D_HANDLER(Sample, HandleMouseModeRequest));
+        SubscribeToEvent(E_MOUSEMODECHANGED, URHO3D_HANDLER(Sample, HandleMouseModeChange));
+    }
+}
+
 void Sample::SetLogoVisible(bool enable)
 void Sample::SetLogoVisible(bool enable)
 {
 {
     if (logoSprite_)
     if (logoSprite_)
@@ -183,9 +214,10 @@ void Sample::CreateConsoleAndDebugHud()
     debugHud->SetDefaultStyle(xmlFile);
     debugHud->SetDefaultStyle(xmlFile);
 }
 }
 
 
-void Sample::HandleKeyDown(StringHash eventType, VariantMap& eventData)
+
+void Sample::HandleKeyUp(StringHash eventType, VariantMap& eventData)
 {
 {
-    using namespace KeyDown;
+    using namespace KeyUp;
 
 
     int key = eventData[P_KEY].GetInt();
     int key = eventData[P_KEY].GetInt();
 
 
@@ -196,11 +228,27 @@ void Sample::HandleKeyDown(StringHash eventType, VariantMap& eventData)
         if (console->IsVisible())
         if (console->IsVisible())
             console->SetVisible(false);
             console->SetVisible(false);
         else
         else
-            engine_->Exit();
+        {
+            if (GetPlatform() == "Web")
+            {
+                GetSubsystem<Input>()->SetMouseVisible(true);
+                if (useMouseMode_ != MM_ABSOLUTE)
+                    GetSubsystem<Input>()->SetMouseMode(MM_FREE);
+            }
+            else
+                engine_->Exit();
+        }
     }
     }
+}
+
+void Sample::HandleKeyDown(StringHash eventType, VariantMap& eventData)
+{
+    using namespace KeyDown;
+
+    int key = eventData[P_KEY].GetInt();
 
 
-    // Toggle console with F1
-    else if (key == KEY_F1)
+    // Toggle console with F1 or Z
+    if (key == KEY_F1 || key == 'Z')
         GetSubsystem<Console>()->Toggle();
         GetSubsystem<Console>()->Toggle();
 
 
     // Toggle debug HUD with F2
     // Toggle debug HUD with F2
@@ -357,3 +405,24 @@ void Sample::HandleTouchBegin(StringHash eventType, VariantMap& eventData)
     InitTouchInput();
     InitTouchInput();
     UnsubscribeFromEvent("TouchBegin");
     UnsubscribeFromEvent("TouchBegin");
 }
 }
+
+// If the user clicks the canvas, attempt to switch to relative mouse mode on web platform
+void Sample::HandleMouseModeRequest(StringHash eventType, VariantMap& eventData)
+{
+    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);
+}

+ 17 - 2
Source/Urho3D/AngelScript/InputAPI.cpp

@@ -497,6 +497,16 @@ static void InputSetMouseVisible(bool enable, Input* ptr)
     ptr->SetMouseVisible(enable, false);
     ptr->SetMouseVisible(enable, false);
 }
 }
 
 
+static void InputSetMouseMode(MouseMode mode, Input* ptr)
+{
+    ptr->SetMouseMode(mode, false);
+}
+
+static void InputSetMouseGrabbed(bool enable, Input* ptr)
+{
+    ptr->SetMouseGrabbed(enable, false);
+}
+
 static void RegisterInput(asIScriptEngine* engine)
 static void RegisterInput(asIScriptEngine* engine)
 {
 {
     engine->RegisterEnum("MouseMode");
     engine->RegisterEnum("MouseMode");
@@ -550,10 +560,15 @@ static void RegisterInput(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Input", "void set_mouseVisible(bool)", asFUNCTION(InputSetMouseVisible), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Input", "void set_mouseVisible(bool)", asFUNCTION(InputSetMouseVisible), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Input", "void ResetMouseVisible()", asMETHOD(Input, ResetMouseVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "void ResetMouseVisible()", asMETHOD(Input, ResetMouseVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_mouseVisible() const", asMETHOD(Input, IsMouseVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_mouseVisible() const", asMETHOD(Input, IsMouseVisible), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Input", "void set_mouseGrabbed(bool)", asMETHOD(Input, SetMouseGrabbed), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Input", "void SetMouseGrabbed(bool, bool = false)", asMETHOD(Input, SetMouseGrabbed), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Input", "void set_mouseGrabbed(bool)", asFUNCTION(InputSetMouseGrabbed), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Input", "bool get_mouseGrabbed() const", asMETHOD(Input, IsMouseGrabbed), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_mouseGrabbed() const", asMETHOD(Input, IsMouseGrabbed), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Input", "void set_mouseMode(MouseMode) const", asMETHOD(Input, SetMouseMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Input", "void ResetMouseGrabbed()", asMETHOD(Input, ResetMouseGrabbed), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Input", "void SetMouseMode(MouseMode, bool = false)", asMETHOD(Input, SetMouseMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Input", "void set_mouseMode(MouseMode)", asFUNCTION(InputSetMouseMode), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Input", "void ResetMouseMode()", asMETHOD(Input, ResetMouseMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "MouseMode get_mouseMode() const", asMETHOD(Input, GetMouseMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "MouseMode get_mouseMode() const", asMETHOD(Input, GetMouseMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Input", "bool get_mouseLocked() const", asMETHOD(Input, IsMouseLocked), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "void set_screenJoystickVisible(int, bool)", asMETHOD(Input, SetScreenJoystickVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "void set_screenJoystickVisible(int, bool)", asMETHOD(Input, SetScreenJoystickVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_screenJoystickVisible(int)", asMETHOD(Input, IsScreenJoystickVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_screenJoystickVisible(int)", asMETHOD(Input, IsScreenJoystickVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "void set_screenKeyboardVisible(bool)", asMETHOD(Input, SetScreenKeyboardVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "void set_screenKeyboardVisible(bool)", asMETHOD(Input, SetScreenKeyboardVisible), asCALL_THISCALL);

+ 1 - 1
Source/Urho3D/Core/ProcessUtils.h

@@ -59,7 +59,7 @@ URHO3D_API const Vector<String>& ParseArguments(int argc, char** argv);
 URHO3D_API const Vector<String>& GetArguments();
 URHO3D_API const Vector<String>& GetArguments();
 /// Read input from the console window. Return empty if no input.
 /// Read input from the console window. Return empty if no input.
 URHO3D_API String GetConsoleInput();
 URHO3D_API String GetConsoleInput();
-/// Return the runtime platform identifier, one of "Windows", "Linux", "Mac OS X", "Android", "iOS" or "Raspberry Pi".
+/// Return the runtime platform identifier, one of "Windows", "Linux", "Mac OS X", "Android", "iOS", "Web" or "Raspberry Pi".
 URHO3D_API String GetPlatform();
 URHO3D_API String GetPlatform();
 /// Return the number of physical CPU cores.
 /// Return the number of physical CPU cores.
 URHO3D_API unsigned GetNumPhysicalCPUs();
 URHO3D_API unsigned GetNumPhysicalCPUs();

+ 21 - 5
Source/Urho3D/Engine/Console.cpp

@@ -127,21 +127,31 @@ void Console::SetDefaultStyle(XMLFile* style)
 void Console::SetVisible(bool enable)
 void Console::SetVisible(bool enable)
 {
 {
     Input* input = GetSubsystem<Input>();
     Input* input = GetSubsystem<Input>();
+    UI* ui = GetSubsystem<UI>();
+    Cursor* cursor = ui->GetCursor();
+
     background_->SetVisible(enable);
     background_->SetVisible(enable);
     closeButton_->SetVisible(enable);
     closeButton_->SetVisible(enable);
+
     if (enable)
     if (enable)
     {
     {
         // Check if we have receivers for E_CONSOLECOMMAND every time here in case the handler is being added later dynamically
         // Check if we have receivers for E_CONSOLECOMMAND every time here in case the handler is being added later dynamically
         bool hasInterpreter = PopulateInterpreter();
         bool hasInterpreter = PopulateInterpreter();
         commandLine_->SetVisible(hasInterpreter);
         commandLine_->SetVisible(hasInterpreter);
         if (hasInterpreter && focusOnShow_)
         if (hasInterpreter && focusOnShow_)
-            GetSubsystem<UI>()->SetFocusElement(lineEdit_);
+            ui->SetFocusElement(lineEdit_);
 
 
         // Ensure the background has no empty space when shown without the lineedit
         // Ensure the background has no empty space when shown without the lineedit
         background_->SetHeight(background_->GetMinHeight());
         background_->SetHeight(background_->GetMinHeight());
 
 
-        // Show OS mouse
-        input->SetMouseVisible(true, true);
+        if (!cursor)
+        {
+            // Show OS mouse
+            input->SetMouseMode(MM_FREE, true);
+            input->SetMouseVisible(true, true);
+        }
+
+        input->SetMouseGrabbed(false, true);
     }
     }
     else
     else
     {
     {
@@ -149,8 +159,14 @@ void Console::SetVisible(bool enable)
         interpreters_->SetFocus(false);
         interpreters_->SetFocus(false);
         lineEdit_->SetFocus(false);
         lineEdit_->SetFocus(false);
 
 
-        // Restore OS mouse visibility
-        input->ResetMouseVisible();
+        if (!cursor)
+        {
+            // Restore OS mouse visibility
+            input->ResetMouseMode();
+            input->ResetMouseVisible();
+        }
+
+        input->ResetMouseGrabbed();
     }
     }
 }
 }
 
 

文件差異過大導致無法顯示
+ 525 - 191
Source/Urho3D/Input/Input.cpp


+ 50 - 21
Source/Urho3D/Input/Input.h

@@ -38,7 +38,8 @@ enum MouseMode
     MM_ABSOLUTE = 0,
     MM_ABSOLUTE = 0,
     MM_RELATIVE,
     MM_RELATIVE,
     MM_WRAP,
     MM_WRAP,
-    MM_FREE
+    MM_FREE,
+    MM_INVALID
 };
 };
 
 
 class Deserializer;
 class Deserializer;
@@ -155,7 +156,9 @@ public:
     /// Reset last mouse visibility that was not suppressed in SetMouseVisible.
     /// Reset last mouse visibility that was not suppressed in SetMouseVisible.
     void ResetMouseVisible();
     void ResetMouseVisible();
     /// Set whether the mouse is currently being grabbed by an operation.
     /// Set whether the mouse is currently being grabbed by an operation.
-    void SetMouseGrabbed(bool grab);
+    void SetMouseGrabbed(bool grab, bool suppressEvent = false);
+    /// Reset the mouse grabbed to the last unsuppressed SetMouseGrabbed call
+    void ResetMouseGrabbed();
     /// Set the mouse mode.
     /// Set the mouse mode.
     /** Set the mouse mode behaviour.
     /** Set the mouse mode behaviour.
      *  MM_ABSOLUTE is the default behaviour, allowing the toggling of operating system cursor visibility and allowing the cursor to escape the window when visible.
      *  MM_ABSOLUTE is the default behaviour, allowing the toggling of operating system cursor visibility and allowing the cursor to escape the window when visible.
@@ -174,7 +177,9 @@ public:
      *  MM_FREE does not grab/confine the mouse cursor even when it is hidden. This can be used for cases where the cursor should render using the operating system
      *  MM_FREE does not grab/confine the mouse cursor even when it is hidden. This can be used for cases where the cursor should render using the operating system
      *  outside the window, and perform custom rendering (with SetMouseVisible(false)) inside.
      *  outside the window, and perform custom rendering (with SetMouseVisible(false)) inside.
     */
     */
-    void SetMouseMode(MouseMode mode);
+    void SetMouseMode(MouseMode mode, bool suppressEvent = false);
+    /// Reset the last mouse mode that wasn't suppressed in SetMouseMode
+    void ResetMouseMode();
     /// Add screen joystick.
     /// Add screen joystick.
     /** Return the joystick instance ID when successful or negative on error.
     /** Return the joystick instance ID when successful or negative on error.
      *  If layout file is not given, use the default screen joystick layout.
      *  If layout file is not given, use the default screen joystick layout.
@@ -240,28 +245,22 @@ public:
     int GetQualifiers() const;
     int GetQualifiers() const;
     /// Return mouse position within window. Should only be used with a visible mouse cursor.
     /// Return mouse position within window. Should only be used with a visible mouse cursor.
     IntVector2 GetMousePosition() const;
     IntVector2 GetMousePosition() const;
-
     /// Return mouse movement since last frame.
     /// Return mouse movement since last frame.
-    const IntVector2& GetMouseMove() const { return mouseMove_; }
-
+    const IntVector2& GetMouseMove() const;
     /// Return horizontal mouse movement since last frame.
     /// Return horizontal mouse movement since last frame.
-    int GetMouseMoveX() const { return mouseMove_.x_; }
-
+    int GetMouseMoveX() const;
     /// Return vertical mouse movement since last frame.
     /// Return vertical mouse movement since last frame.
-    int GetMouseMoveY() const { return mouseMove_.y_; }
-
+    int GetMouseMoveY() const;
     /// Return mouse wheel movement since last frame.
     /// Return mouse wheel movement since last frame.
     int GetMouseMoveWheel() const { return mouseMoveWheel_; }
     int GetMouseMoveWheel() const { return mouseMoveWheel_; }
 
 
     /// Return number of active finger touches.
     /// Return number of active finger touches.
     unsigned GetNumTouches() const { return touches_.Size(); }
     unsigned GetNumTouches() const { return touches_.Size(); }
-
     /// Return active finger touch by index.
     /// Return active finger touch by index.
     TouchState* GetTouch(unsigned index) const;
     TouchState* GetTouch(unsigned index) const;
 
 
     /// Return number of connected joysticks.
     /// Return number of connected joysticks.
     unsigned GetNumJoysticks() const { return joysticks_.Size(); }
     unsigned GetNumJoysticks() const { return joysticks_.Size(); }
-
     /// Return joystick state by ID, or null if does not exist.
     /// Return joystick state by ID, or null if does not exist.
     JoystickState* GetJoystick(SDL_JoystickID id);
     JoystickState* GetJoystick(SDL_JoystickID id);
     /// Return joystick state by index, or null if does not exist. 0 = first connected joystick.
     /// Return joystick state by index, or null if does not exist. 0 = first connected joystick.
@@ -282,9 +281,10 @@ public:
 
 
     /// Return whether the operating system mouse cursor is visible.
     /// Return whether the operating system mouse cursor is visible.
     bool IsMouseVisible() const { return mouseVisible_; }
     bool IsMouseVisible() const { return mouseVisible_; }
-
     /// Return whether the mouse is currently being grabbed by an operation.
     /// Return whether the mouse is currently being grabbed by an operation.
     bool IsMouseGrabbed() const { return mouseGrabbed_; }
     bool IsMouseGrabbed() const { return mouseGrabbed_; }
+    /// Return whether the mouse is locked to the window
+    bool IsMouseLocked() const;
 
 
     /// Return the mouse mode.
     /// Return the mouse mode.
     MouseMode GetMouseMode() const { return mouseMode_; }
     MouseMode GetMouseMode() const { return mouseMode_; }
@@ -310,6 +310,8 @@ private:
     void ResetState();
     void ResetState();
     /// Clear touch states and send touch end events.
     /// Clear touch states and send touch end events.
     void ResetTouches();
     void ResetTouches();
+    /// Reset input accumulation.
+    void ResetInputAccumulation();
     /// Get the index of a touch based on the touch ID.
     /// Get the index of a touch based on the touch ID.
     unsigned GetTouchIndexFromID(int touchID);
     unsigned GetTouchIndexFromID(int touchID);
     /// Used internally to return and remove the next available touch index.
     /// Used internally to return and remove the next available touch index.
@@ -322,16 +324,16 @@ private:
     void SetMouseButton(int button, bool newState);
     void SetMouseButton(int button, bool newState);
     /// Handle a key change.
     /// Handle a key change.
     void SetKey(int key, int scancode, bool newState);
     void SetKey(int key, int scancode, bool newState);
-#ifdef __EMSCRIPTEN__
-    /// Set whether the operating system mouse cursor is visible (Emscripten platform only).
-    void SetMouseVisibleEmscripten(bool enable);
-    /// Set mouse mode (Emscripten platform only).
-    void SetMouseModeEmscripten(MouseMode mode);
-#endif
     /// Handle mouse wheel change.
     /// Handle mouse wheel change.
     void SetMouseWheel(int delta);
     void SetMouseWheel(int delta);
     /// Internal function to set the mouse cursor position.
     /// Internal function to set the mouse cursor position.
     void SetMousePosition(const IntVector2& position);
     void SetMousePosition(const IntVector2& position);
+    /// Center the mouse position.
+    void CenterMousePosition();
+    /// Suppress next mouse movement.
+    void SuppressNextMouseMove();
+    /// Unsuppress mouse movement.
+    void UnsuppressMouseMove();
     /// Handle screen mode event.
     /// Handle screen mode event.
     void HandleScreenMode(StringHash eventType, VariantMap& eventData);
     void HandleScreenMode(StringHash eventType, VariantMap& eventData);
     /// Handle frame start event.
     /// Handle frame start event.
@@ -341,6 +343,22 @@ private:
     /// Handle SDL event.
     /// Handle SDL event.
     void HandleSDLEvent(void* sdlEvent);
     void HandleSDLEvent(void* sdlEvent);
 
 
+#ifndef __EMSCRIPTEN__
+    /// Set SDL mouse mode relative.
+    void SetMouseModeRelative(SDL_bool enable);
+    /// Set SDL mouse mode absolute.
+    void SetMouseModeAbsolute(SDL_bool enable);
+#else
+    /// Set whether the operating system mouse cursor is visible (Emscripten platform only).
+    void SetMouseVisibleEmscripten(bool enable, bool suppressEvent = false);
+    /// Set mouse mode final resolution (Emscripten platform only).
+    void SetMouseModeEmscriptenFinal(MouseMode mode, bool suppressEvent = false);
+    /// SetMouseMode  (Emscripten platform only).
+    void SetMouseModeEmscripten(MouseMode mode, bool suppressEvent);
+    /// Handle frame end event.
+    void HandleEndFrame(StringHash eventType, VariantMap& eventData);
+#endif
+
     /// Graphics subsystem.
     /// Graphics subsystem.
     WeakPtr<Graphics> graphics_;
     WeakPtr<Graphics> graphics_;
     /// Key down state.
     /// Key down state.
@@ -383,8 +401,16 @@ private:
     bool lastMouseVisible_;
     bool lastMouseVisible_;
     /// Flag to indicate the mouse is being grabbed by an operation. Subsystems like UI that uses mouse should temporarily ignore the mouse hover or click events.
     /// Flag to indicate the mouse is being grabbed by an operation. Subsystems like UI that uses mouse should temporarily ignore the mouse hover or click events.
     bool mouseGrabbed_;
     bool mouseGrabbed_;
+    /// The last mouse grabbed set by SetMouseGrabbed.
+    bool lastMouseGrabbed_;
     /// Determines the mode of mouse behaviour.
     /// Determines the mode of mouse behaviour.
     MouseMode mouseMode_;
     MouseMode mouseMode_;
+    /// The last mouse mode set by SetMouseMode.
+    MouseMode lastMouseMode_;
+#ifndef __EMSCRIPTEN__
+    /// Flag to determine whether SDL mouse relative was used.
+    bool sdlMouseRelative_;
+#endif
     /// Touch emulation mode flag.
     /// Touch emulation mode flag.
     bool touchEmulation_;
     bool touchEmulation_;
     /// Input focus flag.
     /// Input focus flag.
@@ -401,13 +427,16 @@ private:
     bool screenModeChanged_;
     bool screenModeChanged_;
     /// Initialized flag.
     /// Initialized flag.
     bool initialized_;
     bool initialized_;
+
 #ifdef __EMSCRIPTEN__
 #ifdef __EMSCRIPTEN__
     /// Emscripten Input glue instance.
     /// Emscripten Input glue instance.
     EmscriptenInput* emscriptenInput_;
     EmscriptenInput* emscriptenInput_;
-    /// Flag used to detect mouse jump when exiting pointer lock.
+    /// Flag used to detect mouse jump when exiting pointer-lock.
     bool emscriptenExitingPointerLock_;
     bool emscriptenExitingPointerLock_;
-    /// Flag used to detect mouse jump on initial mouse click when entering pointer lock.
+    /// Flag used to detect mouse jump on initial mouse click when entering pointer-lock.
     bool emscriptenEnteredPointerLock_;
     bool emscriptenEnteredPointerLock_;
+    /// Flag indicating current pointer-lock status.
+    bool emscriptenPointerLock_;
 #endif
 #endif
 };
 };
 
 

+ 1 - 0
Source/Urho3D/Input/InputEvents.h

@@ -213,6 +213,7 @@ URHO3D_EVENT(E_MOUSEVISIBLECHANGED, MouseVisibleChanged)
 URHO3D_EVENT(E_MOUSEMODECHANGED, MouseModeChanged)
 URHO3D_EVENT(E_MOUSEMODECHANGED, MouseModeChanged)
 {
 {
     URHO3D_PARAM(P_MODE, Mode);                    // MouseMode
     URHO3D_PARAM(P_MODE, Mode);                    // MouseMode
+    URHO3D_PARAM(P_MOUSELOCKED, MouseLocked);      // bool
 }
 }
 
 
 /// Application exit requested.
 /// Application exit requested.

+ 4 - 2
Source/Urho3D/LuaScript/pkgs/Input/Input.pkg

@@ -47,8 +47,9 @@ class Input : public Object
 {
 {
     void SetToggleFullscreen(bool enable);
     void SetToggleFullscreen(bool enable);
     void SetMouseVisible(bool enable, bool suppressEvent = false);
     void SetMouseVisible(bool enable, bool suppressEvent = false);
-    void SetMouseGrabbed(bool grab);
-    void SetMouseMode(MouseMode mode);
+    void SetMouseGrabbed(bool grab, bool suppressEvent = false);
+    void SetMouseMode(MouseMode mode, bool suppressEvent = false);
+    bool IsMouseLocked();
     int AddScreenJoystick(XMLFile* layoutFile = 0, XMLFile* styleFile = 0);
     int AddScreenJoystick(XMLFile* layoutFile = 0, XMLFile* styleFile = 0);
     bool RemoveScreenJoystick(int id);
     bool RemoveScreenJoystick(int id);
     void SetScreenJoystickVisible(int id, bool enable);
     void SetScreenJoystickVisible(int id, bool enable);
@@ -115,6 +116,7 @@ class Input : public Object
     tolua_property__get_set bool touchEmulation;
     tolua_property__get_set bool touchEmulation;
     tolua_property__is_set bool mouseVisible;
     tolua_property__is_set bool mouseVisible;
     tolua_property__is_set bool mouseGrabbed;
     tolua_property__is_set bool mouseGrabbed;
+    tolua_readonly tolua_property__is_set bool mouseLocked;
     tolua_readonly tolua_property__has_set bool focus;
     tolua_readonly tolua_property__has_set bool focus;
     tolua_readonly tolua_property__is_set bool minimized;
     tolua_readonly tolua_property__is_set bool minimized;
 };
 };

+ 4 - 2
Source/Urho3D/UI/UI.cpp

@@ -1438,9 +1438,11 @@ void UI::HandleMouseMove(StringHash eventType, VariantMap& eventData)
     {
     {
         if (!input->IsMouseVisible())
         if (!input->IsMouseVisible())
         {
         {
-            // Relative mouse motion: move cursor only when visible
-            if (cursor_->IsVisible())
+            if (!input->IsMouseLocked())
+                cursor_->SetPosition(IntVector2(eventData[P_X].GetInt(), eventData[P_Y].GetInt()));
+            else if (cursor_->IsVisible())
             {
             {
+                // Relative mouse motion: move cursor only when visible
                 IntVector2 pos = cursor_->GetPosition();
                 IntVector2 pos = cursor_->GetPosition();
                 pos.x_ += eventData[P_DX].GetInt();
                 pos.x_ += eventData[P_DX].GetInt();
                 pos.y_ += eventData[P_DY].GetInt();
                 pos.y_ += eventData[P_DY].GetInt();

+ 3 - 0
bin/Data/LuaScripts/01_HelloWorld.lua

@@ -13,6 +13,9 @@ function Start()
     -- Create "Hello World" Text
     -- Create "Hello World" Text
     CreateText()
     CreateText()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Finally, hook-up this HelloWorld instance to handle update events
     -- Finally, hook-up this HelloWorld instance to handle update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/02_HelloGUI.lua

@@ -34,6 +34,9 @@ function Start()
 
 
     -- Create a draggable Fish
     -- Create a draggable Fish
     CreateDraggableFish()
     CreateDraggableFish()
+
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
 end
 end
 
 
 function InitControls()
 function InitControls()

+ 3 - 0
bin/Data/LuaScripts/03_Sprites.lua

@@ -19,6 +19,9 @@ function Start()
     -- Create the sprites to the user interface
     -- Create the sprites to the user interface
     CreateSprites()
     CreateSprites()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/04_StaticScene.lua

@@ -19,6 +19,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/05_AnimatingScene.lua

@@ -19,6 +19,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/06_SkeletalAnimation.lua

@@ -21,6 +21,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update and render post-update events
     -- Hook up to the frame update and render post-update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/07_Billboards.lua

@@ -22,6 +22,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update and render post-update events
     -- Hook up to the frame update and render post-update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 10 - 1
bin/Data/LuaScripts/08_Decals.lua

@@ -20,6 +20,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update and render post-update events
     -- Hook up to the frame update and render post-update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end
@@ -140,8 +143,14 @@ function SubscribeToEvents()
 end
 end
 
 
 function MoveCamera(timeStep)
 function MoveCamera(timeStep)
+    input.mouseVisible = input.mouseMode ~= MM_RELATIVE
+    mouseDown = input:GetMouseButtonDown(MOUSEB_RIGHT)
+
+    -- Override the MM_RELATIVE mouse grabbed settings, to allow interaction with UI
+    input.mouseGrabbed = mouseDown
+
     -- Right mouse button controls mouse cursor visibility: hide when pressed
     -- Right mouse button controls mouse cursor visibility: hide when pressed
-    ui.cursor.visible = not input:GetMouseButtonDown(MOUSEB_RIGHT)
+    ui.cursor.visible = not mouseDown
 
 
     -- Do not move if the UI has a focused element (the console)
     -- Do not move if the UI has a focused element (the console)
     if ui.focusElement ~= nil then
     if ui.focusElement ~= nil then

+ 3 - 0
bin/Data/LuaScripts/09_MultipleViewports.lua

@@ -20,6 +20,9 @@ function Start()
     -- Setup the viewports for displaying the scene
     -- Setup the viewports for displaying the scene
     SetupViewports()
     SetupViewports()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update and render post-update events
     -- Hook up to the frame update and render post-update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/10_RenderToTexture.lua

@@ -21,6 +21,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/11_Physics.lua

@@ -20,6 +20,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update and render post-update events
     -- Hook up to the frame update and render post-update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/12_PhysicsStressTest.lua

@@ -20,6 +20,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update and render post-update events
     -- Hook up to the frame update and render post-update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/13_Ragdolls.lua

@@ -19,6 +19,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update and render post-update events
     -- Hook up to the frame update and render post-update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/14_SoundEffects.lua

@@ -26,6 +26,9 @@ function Start()
 
 
     -- Create the user interface
     -- Create the user interface
     CreateUI()
     CreateUI()
+
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
 end
 end
 
 
 function CreateUI()
 function CreateUI()

+ 10 - 1
bin/Data/LuaScripts/15_Navigation.lua

@@ -25,6 +25,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update and render post-update events
     -- Hook up to the frame update and render post-update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end
@@ -159,8 +162,14 @@ function SubscribeToEvents()
 end
 end
 
 
 function MoveCamera(timeStep)
 function MoveCamera(timeStep)
+    input.mouseVisible = input.mouseMode ~= MM_RELATIVE
+    mouseDown = input:GetMouseButtonDown(MOUSEB_RIGHT)
+
+    -- Override the MM_RELATIVE mouse grabbed settings, to allow interaction with UI
+    input.mouseGrabbed = mouseDown
+
     -- Right mouse button controls mouse cursor visibility: hide when pressed
     -- Right mouse button controls mouse cursor visibility: hide when pressed
-    ui.cursor.visible = not input:GetMouseButtonDown(MOUSEB_RIGHT)
+    ui.cursor.visible = not mouseDown
 
 
     -- Do not move if the UI has a focused element (the console)
     -- Do not move if the UI has a focused element (the console)
     if ui.focusElement ~= nil then
     if ui.focusElement ~= nil then

+ 3 - 0
bin/Data/LuaScripts/16_Chat.lua

@@ -29,6 +29,9 @@ function Start()
     -- Create the user interface
     -- Create the user interface
     CreateUI()
     CreateUI()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Subscribe to UI and network events
     -- Subscribe to UI and network events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 10 - 1
bin/Data/LuaScripts/17_SceneReplication.lua

@@ -38,6 +38,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to necessary events
     -- Hook up to necessary events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end
@@ -222,8 +225,14 @@ function CreateControllableObject()
 end
 end
 
 
 function MoveCamera()
 function MoveCamera()
+    input.mouseVisible = input.mouseMode ~= MM_RELATIVE
+    mouseDown = input:GetMouseButtonDown(MOUSEB_RIGHT)
+
+    -- Override the MM_RELATIVE mouse grabbed settings, to allow interaction with UI
+    input.mouseGrabbed = mouseDown
+
     -- Right mouse button controls mouse cursor visibility: hide when pressed
     -- Right mouse button controls mouse cursor visibility: hide when pressed
-    ui.cursor.visible = not input:GetMouseButtonDown(MOUSEB_RIGHT)
+    ui.cursor.visible = not mouseDown
 
 
     -- Mouse sensitivity as degrees per pixel
     -- Mouse sensitivity as degrees per pixel
     local MOUSE_SENSITIVITY = 0.1
     local MOUSE_SENSITIVITY = 0.1

+ 3 - 0
bin/Data/LuaScripts/18_CharacterDemo.lua

@@ -41,6 +41,9 @@ function Start()
     -- Create the UI content
     -- Create the UI content
     CreateInstructions()
     CreateInstructions()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Subscribe to necessary events
     -- Subscribe to necessary events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 1
bin/Data/LuaScripts/19_VehicleDemo.lua

@@ -20,7 +20,6 @@ local MAX_WHEEL_ANGLE = 22.5
 local vehicleNode = nil
 local vehicleNode = nil
 
 
 function Start()
 function Start()
-
     -- Execute the common startup for samples
     -- Execute the common startup for samples
     SampleStart()
     SampleStart()
 
 
@@ -33,6 +32,9 @@ function Start()
     -- Create the UI content
     -- Create the UI content
     CreateInstructions()
     CreateInstructions()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Subscribe to necessary events
     -- Subscribe to necessary events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/20_HugeObjectCount.lua

@@ -24,6 +24,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/23_Water.lua

@@ -23,6 +23,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update event
     -- Hook up to the frame update event
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/24_Urho2DSprite.lua

@@ -20,6 +20,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/25_Urho2DParticle.lua

@@ -24,6 +24,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/26_ConsoleInput.lua

@@ -57,6 +57,9 @@ function Start()
     -- Show OS mouse cursor
     -- Show OS mouse cursor
     input.mouseVisible = true
     input.mouseVisible = true
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Open the operating system console window (for stdin / stdout) if not open yet
     -- Open the operating system console window (for stdin / stdout) if not open yet
     -- Do not open in fullscreen, as this would cause constant device loss
     -- Do not open in fullscreen, as this would cause constant device loss
     if not graphics.fullscreen then
     if not graphics.fullscreen then

+ 3 - 0
bin/Data/LuaScripts/27_Urho2DPhysics.lua

@@ -18,6 +18,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/28_Urho2DPhysicsRope.lua

@@ -19,6 +19,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/30_LightAnimation.lua

@@ -17,6 +17,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 3 - 0
bin/Data/LuaScripts/31_MaterialAnimation.lua

@@ -17,6 +17,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 2 - 0
bin/Data/LuaScripts/32_Urho2DConstraints.lua

@@ -20,6 +20,8 @@ function Start()
     CreateScene()
     CreateScene()
     input.mouseVisible = true -- Show mouse cursor
     input.mouseVisible = true -- Show mouse cursor
     CreateInstructions()
     CreateInstructions()
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end
 
 

+ 3 - 0
bin/Data/LuaScripts/33_Urho2DSpriterAnimation.lua

@@ -22,6 +22,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 8 - 5
bin/Data/LuaScripts/34_DynamicGeometry.lua

@@ -30,6 +30,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end
@@ -98,11 +101,11 @@ function CreateScene()
             table.insert(animatingBuffers, cloneModel:GetGeometry(0, 0):GetVertexBuffer(0))
             table.insert(animatingBuffers, cloneModel:GetGeometry(0, 0):GetVertexBuffer(0))
         end
         end
     end
     end
-    
+
     -- Finally create one model (pyramid shape) and a StaticModel to display it from scratch
     -- Finally create one model (pyramid shape) and a StaticModel to display it from scratch
     -- Note: there are duplicated vertices to enable face normals. We will calculate normals programmatically
     -- Note: there are duplicated vertices to enable face normals. We will calculate normals programmatically
     local numVertices = 18
     local numVertices = 18
-        
+
     local vertexData = {
     local vertexData = {
         -- Position          Normal
         -- Position          Normal
         0.0, 0.5, 0.0,       0.0, 0.0, 0.0,
         0.0, 0.5, 0.0,       0.0, 0.0, 0.0,
@@ -129,7 +132,7 @@ function CreateScene()
         -0.5, -0.5, 0.5,     0.0, 0.0, 0.0,
         -0.5, -0.5, 0.5,     0.0, 0.0, 0.0,
         -0.5, -0.5, -0.5,    0.0, 0.0, 0.0
         -0.5, -0.5, -0.5,    0.0, 0.0, 0.0
     }
     }
-    
+
     local indexData = {
     local indexData = {
         0, 1, 2,
         0, 1, 2,
         3, 4, 5,
         3, 4, 5,
@@ -280,8 +283,8 @@ function AnimateObjects(timeStep)
             -- If there are duplicate vertices, animate them in phase of the original
             -- If there are duplicate vertices, animate them in phase of the original
             local phase = startPhase + vertexDuplicates[j] * 10.0
             local phase = startPhase + vertexDuplicates[j] * 10.0
             local src = originalVertices[j]
             local src = originalVertices[j]
-            local dest = Vector3(src.x * (1.0 + 0.1 * Sin(phase)), 
-                src.y * (1.0 + 0.1 * Sin(phase + 60.0)), 
+            local dest = Vector3(src.x * (1.0 + 0.1 * Sin(phase)),
+                src.y * (1.0 + 0.1 * Sin(phase + 60.0)),
                 src.z * (1.0 + 0.1 * Sin(phase + 120.0)))
                 src.z * (1.0 + 0.1 * Sin(phase + 120.0)))
 
 
             -- Write position
             -- Write position

+ 4 - 1
bin/Data/LuaScripts/35_SignedDistanceFieldText.lua

@@ -20,6 +20,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end
@@ -84,7 +87,7 @@ function CreateScene()
             mushroomTitleText.textEffect = TE_STROKE
             mushroomTitleText.textEffect = TE_STROKE
             mushroomTitleText.effectColor = Color(0.5, 0.5, 0.5)
             mushroomTitleText.effectColor = Color(0.5, 0.5, 0.5)
         end
         end
-        
+
         mushroomTitleText:SetAlignment(HA_CENTER, VA_CENTER)
         mushroomTitleText:SetAlignment(HA_CENTER, VA_CENTER)
     end
     end
 
 

+ 3 - 0
bin/Data/LuaScripts/36_Urho2DTileMap.lua

@@ -19,6 +19,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end

+ 4 - 1
bin/Data/LuaScripts/37_UIDrag.lua

@@ -24,6 +24,9 @@ function Start()
     CreateGUI()
     CreateGUI()
     CreateInstructions()
     CreateInstructions()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Hook up to the frame update events
     -- Hook up to the frame update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end
@@ -162,7 +165,7 @@ function HandleUpdate(eventType, eventData)
         t:SetVisible(false)
         t:SetVisible(false)
         i = i + 1
         i = i + 1
     end
     end
-    
+
     if input:GetKeyPress(KEY_SPACE) then
     if input:GetKeyPress(KEY_SPACE) then
         elements = ui.root:GetChildrenWithTag("SomeTag")
         elements = ui.root:GetChildrenWithTag("SomeTag")
         for i, element in ipairs(elements) do
         for i, element in ipairs(elements) do

+ 10 - 1
bin/Data/LuaScripts/38_SceneAndUILoad.lua

@@ -19,6 +19,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Subscribe to global events for camera movement
     -- Subscribe to global events for camera movement
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end
@@ -104,8 +107,14 @@ function HandleUpdate(eventType, eventData)
 end
 end
 
 
 function MoveCamera(timeStep)
 function MoveCamera(timeStep)
+    input.mouseVisible = input.mouseMode ~= MM_RELATIVE
+    mouseDown = input:GetMouseButtonDown(MOUSEB_RIGHT)
+
+    -- Override the MM_RELATIVE mouse grabbed settings, to allow interaction with UI
+    input.mouseGrabbed = mouseDown
+
     -- Right mouse button controls mouse cursor visibility: hide when pressed
     -- Right mouse button controls mouse cursor visibility: hide when pressed
-    ui.cursor.visible = not input:GetMouseButtonDown(MOUSEB_RIGHT)
+    ui.cursor.visible = not mouseDown
 
 
     -- Do not move if the UI has a focused element
     -- Do not move if the UI has a focused element
     if ui.focusElement ~= nil then
     if ui.focusElement ~= nil then

+ 10 - 1
bin/Data/LuaScripts/39_CrowdNavigation.lua

@@ -26,6 +26,9 @@ function Start()
     -- Setup the viewport for displaying the scene
     -- Setup the viewport for displaying the scene
     SetupViewport()
     SetupViewport()
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE)
+
     -- Hook up to the frame update and render post-update events
     -- Hook up to the frame update and render post-update events
     SubscribeToEvents()
     SubscribeToEvents()
 end
 end
@@ -313,8 +316,14 @@ function Raycast(maxDistance)
 end
 end
 
 
 function MoveCamera(timeStep)
 function MoveCamera(timeStep)
+    input.mouseVisible = input.mouseMode ~= MM_RELATIVE
+    mouseDown = input:GetMouseButtonDown(MOUSEB_RIGHT)
+
+    -- Override the MM_RELATIVE mouse grabbed settings, to allow interaction with UI
+    input.mouseGrabbed = mouseDown
+
     -- Right mouse button controls mouse cursor visibility: hide when pressed
     -- Right mouse button controls mouse cursor visibility: hide when pressed
-    ui.cursor.visible = not input:GetMouseButtonDown(MOUSEB_RIGHT)
+    ui.cursor.visible = not mouseDown
 
 
     -- Do not move if the UI has a focused element (the console)
     -- Do not move if the UI has a focused element (the console)
     if ui.focusElement ~= nil then
     if ui.focusElement ~= nil then

+ 3 - 1
bin/Data/LuaScripts/40_Localization.lua

@@ -21,6 +21,9 @@ function Start()
 
 
     -- Init the user interface
     -- Init the user interface
     CreateGUI()
     CreateGUI()
+
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
 end
 end
 
 
 function InitLocalizationSystem()
 function InitLocalizationSystem()
@@ -173,4 +176,3 @@ function HandleChangeLanguage(eventType, eventData)
 
 
     -- A text on the button "Press this button" changes automatically
     -- A text on the button "Press this button" changes automatically
 end
 end
-

+ 3 - 0
bin/Data/LuaScripts/41_DatabaseDemo.lua

@@ -33,6 +33,9 @@ function Start()
     -- Show OS mouse cursor
     -- Show OS mouse cursor
     input.mouseVisible = true
     input.mouseVisible = true
 
 
+    -- Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE)
+
     -- Open the operating system console window (for stdin / stdout) if not open yet
     -- Open the operating system console window (for stdin / stdout) if not open yet
     -- Do not open in fullscreen, as this would cause constant device loss
     -- Do not open in fullscreen, as this would cause constant device loss
     if not graphics.fullscreen then
     if not graphics.fullscreen then

+ 63 - 7
bin/Data/LuaScripts/Utilities/Sample.lua

@@ -19,6 +19,7 @@ yaw = 0 -- Camera yaw angle
 pitch = 0 -- Camera pitch angle
 pitch = 0 -- Camera pitch angle
 TOUCH_SENSITIVITY = 2
 TOUCH_SENSITIVITY = 2
 debugHudMode = 0
 debugHudMode = 0
+useMouseMode_ = MM_ABSOLUTE
 
 
 function SampleStart()
 function SampleStart()
     if GetPlatform() == "Android" or GetPlatform() == "iOS" or input.touchEmulation then
     if GetPlatform() == "Android" or GetPlatform() == "iOS" or input.touchEmulation then
@@ -28,7 +29,6 @@ function SampleStart()
         -- On desktop platform, do not detect touch when we already got a joystick
         -- On desktop platform, do not detect touch when we already got a joystick
         SubscribeToEvent("TouchBegin", "HandleTouchBegin")
         SubscribeToEvent("TouchBegin", "HandleTouchBegin")
     end
     end
-
     -- Create logo
     -- Create logo
     CreateLogo()
     CreateLogo()
 
 
@@ -41,6 +41,9 @@ function SampleStart()
     -- Subscribe key down event
     -- Subscribe key down event
     SubscribeToEvent("KeyDown", "HandleKeyDown")
     SubscribeToEvent("KeyDown", "HandleKeyDown")
 
 
+    -- Subscribe key up event
+    SubscribeToEvent("KeyUp", "HandleKeyUp")
+
     -- Subscribe scene update event
     -- Subscribe scene update event
     SubscribeToEvent("SceneUpdate", "HandleSceneUpdate")
     SubscribeToEvent("SceneUpdate", "HandleSceneUpdate")
 end
 end
@@ -58,6 +61,27 @@ function InitTouchInput()
     input:SetScreenJoystickVisible(screenJoystickSettingsIndex, true)
     input:SetScreenJoystickVisible(screenJoystickSettingsIndex, true)
 end
 end
 
 
+function SampleInitMouseMode(mode)
+    useMouseMode_ = mode
+    if GetPlatform() ~= "Web" then
+        if useMouseMode_ == MM_FREE then
+            input.mouseVisible = true
+        end
+
+        if useMouseMode_ ~= MM_ABSOLUTE then
+            input.mouseMode = useMouseMode_
+
+            if console ~= nil and console.visible then
+                input:SetMouseMode(MM_ABSOLUTE, true)
+            end
+        end
+    else
+        input.mouseVisible = true
+        SubscribeToEvent("MouseDown", "HandleMouseModeRequest")
+        SubscribeToEvent("MouseModeChanged", "HandleMouseModeChange")
+    end
+end
+
 function SetLogoVisible(enable)
 function SetLogoVisible(enable)
     if logoSprite ~= nil then
     if logoSprite ~= nil then
         logoSprite.visible = enable
         logoSprite.visible = enable
@@ -122,19 +146,30 @@ function CreateConsoleAndDebugHud()
     debugHud.defaultStyle = uiStyle
     debugHud.defaultStyle = uiStyle
 end
 end
 
 
-function HandleKeyDown(eventType, eventData)
+function HandleKeyUp(eventType, eventData)
     local key = eventData["Key"]:GetInt()
     local key = eventData["Key"]:GetInt()
     -- Close console (if open) or exit when ESC is pressed
     -- Close console (if open) or exit when ESC is pressed
     if key == KEY_ESC then
     if key == KEY_ESC then
-        if not console:IsVisible() then
-            engine:Exit()
-        else
+        if console:IsVisible() then
             console:SetVisible(false)
             console:SetVisible(false)
+        else
+            if GetPlatform() == "Web" then
+                input.mouseVisible = true;
+                if (useMouseMode_ ~= MM_ABSOLUTE) then
+                    input.mouseMode = MM_FREE;
+                end
+            else
+                engine:Exit();
+            end
         end
         end
+    end
+end
 
 
-    elseif key == KEY_F1 then
-        console:Toggle()
+function HandleKeyDown(eventType, eventData)
+    local key = eventData["Key"]:GetInt()
 
 
+    if key == KEY_F1 then
+        console:Toggle()
     elseif key == KEY_F2 then
     elseif key == KEY_F2 then
         if debugHud:GetMode() == DEBUGHUD_SHOW_ALL_MEMORY or debugHud:GetMode() == 0 then
         if debugHud:GetMode() == DEBUGHUD_SHOW_ALL_MEMORY or debugHud:GetMode() == 0 then
             debugHud:SetMode(DEBUGHUD_SHOW_ALL)
             debugHud:SetMode(DEBUGHUD_SHOW_ALL)
@@ -261,6 +296,27 @@ function HandleTouchBegin(eventType, eventData)
     UnsubscribeFromEvent("TouchBegin")
     UnsubscribeFromEvent("TouchBegin")
 end
 end
 
 
+-- If the user clicks the canvas, attempt to switch to relative mouse mode on web platform
+function HandleMouseModeRequest(eventType, eventData)
+    if console ~= nil and console.visible then
+        return
+    end
+
+    if input.mouseMode == MM_ABSOLUTE then
+        input.mouseVisible = false
+    elseif useMouseMode_ == MM_FREE then
+        input.mouseVisible = true
+    end
+
+    input.mouseMode = useMouseMode_
+end
+
+-- If the user clicks the canvas, attempt to switch to relative mouse mode on web platform
+function HandleMouseModeChange(eventType, eventData)
+    mouseLocked = eventData["MouseLocked"]:GetBool()
+    input.mouseVisible = not mouseLocked;
+end
+
 -- Create empty XML patch instructions for screen joystick layout if none defined
 -- Create empty XML patch instructions for screen joystick layout if none defined
 function GetScreenJoystickPatchString()
 function GetScreenJoystickPatchString()
     return ""
     return ""

+ 3 - 0
bin/Data/Scripts/01_HelloWorld.as

@@ -14,6 +14,9 @@ void Start()
     // Create "Hello World" Text
     // Create "Hello World" Text
     CreateText();
     CreateText();
 
 
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE);
+
     // Finally, hook-up this HelloWorld instance to handle update events
     // Finally, hook-up this HelloWorld instance to handle update events
     SubscribeToEvents();
     SubscribeToEvents();
 }
 }

+ 3 - 0
bin/Data/Scripts/02_HelloGUI.as

@@ -35,6 +35,9 @@ void Start()
 
 
     // Create a draggable Fish
     // Create a draggable Fish
     CreateDraggableFish();
     CreateDraggableFish();
+
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE);
 }
 }
 
 
 void InitControls()
 void InitControls()

+ 3 - 0
bin/Data/Scripts/03_Sprites.as

@@ -21,6 +21,9 @@ void Start()
 
 
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
+
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_FREE);
 }
 }
 
 
 void CreateSprites()
 void CreateSprites()

+ 3 - 0
bin/Data/Scripts/04_StaticScene.as

@@ -20,6 +20,9 @@ void Start()
     // Setup the viewport for displaying the scene
     // Setup the viewport for displaying the scene
     SetupViewport();
     SetupViewport();
 
 
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE);
+
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
 }
 }

+ 3 - 0
bin/Data/Scripts/05_AnimatingScene.as

@@ -20,6 +20,9 @@ void Start()
     // Setup the viewport for displaying the scene
     // Setup the viewport for displaying the scene
     SetupViewport();
     SetupViewport();
 
 
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE);
+
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
 }
 }

+ 3 - 0
bin/Data/Scripts/06_SkeletalAnimation.as

@@ -22,6 +22,9 @@ void Start()
     // Setup the viewport for displaying the scene
     // Setup the viewport for displaying the scene
     SetupViewport();
     SetupViewport();
 
 
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE);
+
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
 }
 }

+ 3 - 0
bin/Data/Scripts/07_Billboards.as

@@ -20,6 +20,9 @@ void Start()
     // Setup the viewport for displaying the scene
     // Setup the viewport for displaying the scene
     SetupViewport();
     SetupViewport();
 
 
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE);
+
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
 }
 }

+ 10 - 1
bin/Data/Scripts/08_Decals.as

@@ -21,6 +21,9 @@ void Start()
     // Setup the viewport for displaying the scene
     // Setup the viewport for displaying the scene
     SetupViewport();
     SetupViewport();
 
 
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE);
+
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
 }
 }
@@ -147,8 +150,14 @@ void SubscribeToEvents()
 
 
 void MoveCamera(float timeStep)
 void MoveCamera(float timeStep)
 {
 {
+    input.mouseVisible = input.mouseMode != MM_RELATIVE;
+    bool mouseDown = input.mouseButtonDown[MOUSEB_RIGHT];
+
+    // Override the MM_RELATIVE mouse grabbed settings, to allow interaction with UI
+    input.mouseGrabbed = mouseDown;
+
     // Right mouse button controls mouse cursor visibility: hide when pressed
     // Right mouse button controls mouse cursor visibility: hide when pressed
-    ui.cursor.visible = !input.mouseButtonDown[MOUSEB_RIGHT];
+    ui.cursor.visible = !mouseDown;
 
 
     // Do not move if the UI has a focused element (the console)
     // Do not move if the UI has a focused element (the console)
     if (ui.focusElement !is null)
     if (ui.focusElement !is null)

+ 3 - 0
bin/Data/Scripts/09_MultipleViewports.as

@@ -21,6 +21,9 @@ void Start()
     // Setup the viewports for displaying the scene
     // Setup the viewports for displaying the scene
     SetupViewports();
     SetupViewports();
 
 
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE);
+
     // Hook up to the frame update and render post-update events
     // Hook up to the frame update and render post-update events
     SubscribeToEvents();
     SubscribeToEvents();
 }
 }

+ 3 - 0
bin/Data/Scripts/10_RenderToTexture.as

@@ -22,6 +22,9 @@ void Start()
     // Setup the viewport for displaying the scene
     // Setup the viewport for displaying the scene
     SetupViewport();
     SetupViewport();
 
 
+    // Set the mouse mode to use in the sample
+    SampleInitMouseMode(MM_RELATIVE);
+
     // Hook up to the frame update events
     // Hook up to the frame update events
     SubscribeToEvents();
     SubscribeToEvents();
 }
 }

部分文件因文件數量過多而無法顯示