Sample.lua 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. -- Common sample initialization as a framework for all samples.
  2. -- - Create Urho3D logo at screen
  3. -- - Set custom window title and icon
  4. -- - Create Console and Debug HUD, and use F1 and F2 key to toggle them
  5. -- - Toggle rendering options from the keys 1-8
  6. -- - Take screenshots with key 9
  7. -- - Handle Esc key down to hide Console or exit application
  8. -- - Init touch input on mobile platform using screen joysticks (patched for each individual sample)
  9. local logoSprite = nil
  10. scene_ = nil -- Scene
  11. screenJoystickIndex = M_MAX_UNSIGNED -- Screen joystick index for navigational controls (mobile platforms only)
  12. screenJoystickSettingsIndex = M_MAX_UNSIGNED -- Screen joystick index for settings (mobile platforms only)
  13. touchEnabled = false -- Flag to indicate whether touch input has been enabled
  14. paused = false -- Pause flag
  15. drawDebug = false -- Draw debug geometry flag
  16. cameraNode = nil -- Camera scene node
  17. yaw = 0 -- Camera yaw angle
  18. pitch = 0 -- Camera pitch angle
  19. TOUCH_SENSITIVITY = 2
  20. function SampleStart()
  21. if GetPlatform() == "Android" or GetPlatform() == "iOS" or input.touchEmulation then
  22. -- On mobile platform, enable touch by adding a screen joystick
  23. InitTouchInput()
  24. elseif input:GetNumJoysticks() == 0 then
  25. -- On desktop platform, do not detect touch when we already got a joystick
  26. SubscribeToEvent("TouchBegin", "HandleTouchBegin")
  27. end
  28. -- Create logo
  29. CreateLogo()
  30. -- Set custom window Title & Icon
  31. SetWindowTitleAndIcon()
  32. -- Create console and debug HUD
  33. CreateConsoleAndDebugHud()
  34. -- Subscribe key down event
  35. SubscribeToEvent("KeyDown", "HandleKeyDown")
  36. -- Subscribe scene update event
  37. SubscribeToEvent("SceneUpdate", "HandleSceneUpdate")
  38. end
  39. function InitTouchInput()
  40. touchEnabled = true
  41. local layout = cache:GetResource("XMLFile", "UI/ScreenJoystick_Samples.xml")
  42. local patchString = GetScreenJoystickPatchString()
  43. if patchString ~= "" then
  44. -- Patch the screen joystick layout further on demand
  45. local patchFile = XMLFile()
  46. if patchFile:FromString(patchString) then layout:Patch(patchFile) end
  47. end
  48. screenJoystickIndex = input:AddScreenJoystick(layout, cache:GetResource("XMLFile", "UI/DefaultStyle.xml"))
  49. input:SetScreenJoystickVisible(screenJoystickSettingsIndex, true)
  50. end
  51. function SetLogoVisible(enable)
  52. if logoSprite ~= nil then
  53. logoSprite.visible = enable
  54. end
  55. end
  56. function CreateLogo()
  57. -- Get logo texture
  58. local logoTexture = cache:GetResource("Texture2D", "Textures/LogoLarge.png")
  59. if logoTexture == nil then
  60. return
  61. end
  62. -- Create logo sprite and add to the UI layout
  63. logoSprite = ui.root:CreateChild("Sprite")
  64. -- Set logo sprite texture
  65. logoSprite:SetTexture(logoTexture)
  66. local textureWidth = logoTexture.width
  67. local textureHeight = logoTexture.height
  68. -- Set logo sprite scale
  69. logoSprite:SetScale(256 / textureWidth)
  70. -- Set logo sprite size
  71. logoSprite:SetSize(textureWidth, textureHeight)
  72. -- Set logo sprite hot spot
  73. logoSprite.hotSpot = IntVector2(0, textureHeight)
  74. -- Set logo sprite alignment
  75. logoSprite:SetAlignment(HA_LEFT, VA_BOTTOM);
  76. -- Make logo not fully opaque to show the scene underneath
  77. logoSprite.opacity = 0.75
  78. -- Set a low priority for the logo so that other UI elements can be drawn on top
  79. logoSprite.priority = -100
  80. end
  81. function SetWindowTitleAndIcon()
  82. local icon = cache:GetResource("Image", "Textures/UrhoIcon.png")
  83. graphics:SetWindowIcon(icon)
  84. graphics.windowTitle = "Urho3D Sample"
  85. end
  86. function CreateConsoleAndDebugHud()
  87. -- Get default style
  88. local uiStyle = cache:GetResource("XMLFile", "UI/DefaultStyle.xml")
  89. if uiStyle == nil then
  90. return
  91. end
  92. -- Create console
  93. engine:CreateConsole()
  94. console.defaultStyle = uiStyle
  95. console.background.opacity = 0.8
  96. -- Create debug HUD
  97. engine:CreateDebugHud()
  98. debugHud.defaultStyle = uiStyle
  99. end
  100. function HandleKeyDown(eventType, eventData)
  101. local key = eventData:GetInt("Key")
  102. -- Close console (if open) or exit when ESC is pressed
  103. if key == KEY_ESC then
  104. if not console:IsVisible() then
  105. engine:Exit()
  106. else
  107. console:SetVisible(false)
  108. end
  109. elseif key == KEY_F1 then
  110. console:Toggle()
  111. elseif key == KEY_F2 then
  112. debugHud:ToggleAll()
  113. end
  114. if ui.focusElement == nil then
  115. -- Preferences / Pause
  116. if key == KEY_SELECT and touchEnabled then
  117. paused = not paused
  118. if screenJoystickSettingsIndex == M_MAX_UNSIGNED then
  119. -- Lazy initialization
  120. screenJoystickSettingsIndex = input:AddScreenJoystick(cache:GetResource("XMLFile", "UI/ScreenJoystickSettings_Samples.xml"), cache:GetResource("XMLFile", "UI/DefaultStyle.xml"))
  121. else
  122. input:SetScreenJoystickVisible(screenJoystickSettingsIndex, paused)
  123. end
  124. -- Texture quality
  125. elseif key == KEY_1 then
  126. local quality = renderer.textureQuality
  127. quality = quality + 1
  128. if quality > QUALITY_HIGH then
  129. quality = QUALITY_LOW
  130. end
  131. renderer.textureQuality = quality
  132. -- Material quality
  133. elseif key == KEY_2 then
  134. local quality = renderer.materialQuality
  135. quality = quality + 1
  136. if quality > QUALITY_HIGH then
  137. quality = QUALITY_LOW
  138. end
  139. renderer.materialQuality = quality
  140. -- Specular lighting
  141. elseif key == KEY_3 then
  142. renderer.specularLighting = not renderer.specularLighting
  143. -- Shadow rendering
  144. elseif key == KEY_4 then
  145. renderer.drawShadows = not renderer.drawShadows
  146. -- Shadow map resolution
  147. elseif key == KEY_5 then
  148. local shadowMapSize = renderer.shadowMapSize
  149. shadowMapSize = shadowMapSize * 2
  150. if shadowMapSize > 2048 then
  151. shadowMapSize = 512
  152. end
  153. renderer.shadowMapSize = shadowMapSize
  154. -- Shadow depth and filtering quality
  155. elseif key == KEY_6 then
  156. local quality = renderer.shadowQuality
  157. quality = quality + 1
  158. if quality > SHADOWQUALITY_HIGH_24BIT then
  159. quality = SHADOWQUALITY_LOW_16BIT
  160. end
  161. renderer.shadowQuality = quality
  162. -- Occlusion culling
  163. elseif key == KEY_7 then
  164. local occlusion = renderer.maxOccluderTriangles > 0
  165. occlusion = not occlusion
  166. if occlusion then
  167. renderer.maxOccluderTriangles = 5000
  168. else
  169. renderer.maxOccluderTriangles = 0
  170. end
  171. -- Instancing
  172. elseif key == KEY_8 then
  173. renderer.dynamicInstancing = not renderer.dynamicInstancing
  174. -- Take screenshot
  175. elseif key == KEY_9 then
  176. local screenshot = Image()
  177. graphics:TakeScreenShot(screenshot)
  178. local timeStamp = Time:GetTimeStamp()
  179. timeStamp = string.gsub(timeStamp, "[:. ]", "_")
  180. -- Here we save in the Data folder with date and time appended
  181. screenshot:SavePNG(fileSystem:GetProgramDir() .. "Data/Screenshot_" .. timeStamp .. ".png")
  182. end
  183. end
  184. end
  185. function HandleSceneUpdate(eventType, eventData)
  186. -- Move the camera by touch, if the camera node is initialized by descendant sample class
  187. if touchEnabled and cameraNode then
  188. for i=0, input:GetNumTouches()-1 do
  189. local state = input:GetTouch(i)
  190. if not state.touchedElement then -- Touch on empty space
  191. if state.delta.x or state.delta.y then
  192. local camera = cameraNode:GetComponent("Camera")
  193. if not camera then return end
  194. yaw = yaw + TOUCH_SENSITIVITY * camera.fov / graphics.height * state.delta.x
  195. pitch = pitch + TOUCH_SENSITIVITY * camera.fov / graphics.height * state.delta.y
  196. -- Construct new orientation for the camera scene node from yaw and pitch; roll is fixed to zero
  197. cameraNode:SetRotation(Quaternion(pitch, yaw, 0))
  198. else
  199. -- Move the cursor to the touch position
  200. local cursor = ui:GetCursor()
  201. if cursor and cursor:IsVisible() then cursor:SetPosition(state.position) end
  202. end
  203. end
  204. end
  205. end
  206. end
  207. function HandleTouchBegin(eventType, eventData)
  208. -- On some platforms like Windows the presence of touch input can only be detected dynamically
  209. InitTouchInput()
  210. UnsubscribeFromEvent("TouchBegin")
  211. end
  212. -- Create empty XML patch instructions for screen joystick layout if none defined
  213. function GetScreenJoystickPatchString()
  214. return ""
  215. end