-- Common sample initialization as a framework for all samples. -- - Create Urho3D logo at screen -- - Set custom window title and icon -- - Create Console and Debug HUD, and use F1 and F2 key to toggle them -- - Toggle rendering options from the keys 1-8 -- - Take screenshots with key 9 -- - Handle Esc key down to hide Console or exit application -- - Init touch input on mobile platform using screen joysticks (patched for each individual sample) local logoSprite = nil scene_ = nil -- Scene screenJoystickIndex = M_MAX_UNSIGNED -- Screen joystick index for navigational controls (mobile platforms only) screenJoystickSettingsIndex = M_MAX_UNSIGNED -- Screen joystick index for settings (mobile platforms only) touchEnabled = false -- Flag to indicate whether touch input has been enabled paused = false -- Pause flag drawDebug = false -- Draw debug geometry flag cameraNode = nil -- Camera scene node yaw = 0 -- Camera yaw angle pitch = 0 -- Camera pitch angle TOUCH_SENSITIVITY = 2 function SampleStart() if GetPlatform() == "Android" or GetPlatform() == "iOS" or input.touchEmulation then -- On mobile platform, enable touch by adding a screen joystick InitTouchInput() elseif input:GetNumJoysticks() == 0 then -- On desktop platform, do not detect touch when we already got a joystick SubscribeToEvent("TouchBegin", "HandleTouchBegin") end -- Create logo CreateLogo() -- Set custom window Title & Icon SetWindowTitleAndIcon() -- Create console and debug HUD CreateConsoleAndDebugHud() -- Subscribe key down event SubscribeToEvent("KeyDown", "HandleKeyDown") -- Subscribe scene update event SubscribeToEvent("SceneUpdate", "HandleSceneUpdate") end function InitTouchInput() touchEnabled = true local layout = cache:GetResource("XMLFile", "UI/ScreenJoystick_Samples.xml") local patchString = GetScreenJoystickPatchString() if patchString ~= "" then -- Patch the screen joystick layout further on demand local patchFile = XMLFile() if patchFile:FromString(patchString) then layout:Patch(patchFile) end end screenJoystickIndex = input:AddScreenJoystick(layout, cache:GetResource("XMLFile", "UI/DefaultStyle.xml")) input:SetScreenJoystickVisible(screenJoystickSettingsIndex, true) end function SetLogoVisible(enable) if logoSprite ~= nil then logoSprite.visible = enable end end function CreateLogo() -- Get logo texture local logoTexture = cache:GetResource("Texture2D", "Textures/LogoLarge.png") if logoTexture == nil then return end -- Create logo sprite and add to the UI layout logoSprite = ui.root:CreateChild("Sprite") -- Set logo sprite texture logoSprite:SetTexture(logoTexture) local textureWidth = logoTexture.width local textureHeight = logoTexture.height -- Set logo sprite scale logoSprite:SetScale(256 / textureWidth) -- Set logo sprite size logoSprite:SetSize(textureWidth, textureHeight) -- Set logo sprite hot spot logoSprite.hotSpot = IntVector2(0, textureHeight) -- Set logo sprite alignment logoSprite:SetAlignment(HA_LEFT, VA_BOTTOM); -- Make logo not fully opaque to show the scene underneath logoSprite.opacity = 0.75 -- Set a low priority for the logo so that other UI elements can be drawn on top logoSprite.priority = -100 end function SetWindowTitleAndIcon() local icon = cache:GetResource("Image", "Textures/UrhoIcon.png") graphics:SetWindowIcon(icon) graphics.windowTitle = "Urho3D Sample" end function CreateConsoleAndDebugHud() -- Get default style local uiStyle = cache:GetResource("XMLFile", "UI/DefaultStyle.xml") if uiStyle == nil then return end -- Create console engine:CreateConsole() console.defaultStyle = uiStyle console.background.opacity = 0.8 -- Create debug HUD engine:CreateDebugHud() debugHud.defaultStyle = uiStyle end function HandleKeyDown(eventType, eventData) local key = eventData:GetInt("Key") -- Close console (if open) or exit when ESC is pressed if key == KEY_ESC then if not console:IsVisible() then engine:Exit() else console:SetVisible(false) end elseif key == KEY_F1 then console:Toggle() elseif key == KEY_F2 then debugHud:ToggleAll() end if ui.focusElement == nil then -- Preferences / Pause if key == KEY_SELECT and touchEnabled then paused = not paused if screenJoystickSettingsIndex == M_MAX_UNSIGNED then -- Lazy initialization screenJoystickSettingsIndex = input:AddScreenJoystick(cache:GetResource("XMLFile", "UI/ScreenJoystickSettings_Samples.xml"), cache:GetResource("XMLFile", "UI/DefaultStyle.xml")) else input:SetScreenJoystickVisible(screenJoystickSettingsIndex, paused) end -- Texture quality elseif key == KEY_1 then local quality = renderer.textureQuality quality = quality + 1 if quality > QUALITY_HIGH then quality = QUALITY_LOW end renderer.textureQuality = quality -- Material quality elseif key == KEY_2 then local quality = renderer.materialQuality quality = quality + 1 if quality > QUALITY_HIGH then quality = QUALITY_LOW end renderer.materialQuality = quality -- Specular lighting elseif key == KEY_3 then renderer.specularLighting = not renderer.specularLighting -- Shadow rendering elseif key == KEY_4 then renderer.drawShadows = not renderer.drawShadows -- Shadow map resolution elseif key == KEY_5 then local shadowMapSize = renderer.shadowMapSize shadowMapSize = shadowMapSize * 2 if shadowMapSize > 2048 then shadowMapSize = 512 end renderer.shadowMapSize = shadowMapSize -- Shadow depth and filtering quality elseif key == KEY_6 then local quality = renderer.shadowQuality quality = quality + 1 if quality > SHADOWQUALITY_HIGH_24BIT then quality = SHADOWQUALITY_LOW_16BIT end renderer.shadowQuality = quality -- Occlusion culling elseif key == KEY_7 then local occlusion = renderer.maxOccluderTriangles > 0 occlusion = not occlusion if occlusion then renderer.maxOccluderTriangles = 5000 else renderer.maxOccluderTriangles = 0 end -- Instancing elseif key == KEY_8 then renderer.dynamicInstancing = not renderer.dynamicInstancing -- Take screenshot elseif key == KEY_9 then local screenshot = Image() graphics:TakeScreenShot(screenshot) local timeStamp = Time:GetTimeStamp() timeStamp = string.gsub(timeStamp, "[:. ]", "_") -- Here we save in the Data folder with date and time appended screenshot:SavePNG(fileSystem:GetProgramDir() .. "Data/Screenshot_" .. timeStamp .. ".png") end end end function HandleSceneUpdate(eventType, eventData) -- Move the camera by touch, if the camera node is initialized by descendant sample class if touchEnabled and cameraNode then for i=0, input:GetNumTouches()-1 do local state = input:GetTouch(i) if not state.touchedElement then -- Touch on empty space if state.delta.x or state.delta.y then local camera = cameraNode:GetComponent("Camera") if not camera then return end yaw = yaw + TOUCH_SENSITIVITY * camera.fov / graphics.height * state.delta.x pitch = pitch + TOUCH_SENSITIVITY * camera.fov / graphics.height * state.delta.y -- Construct new orientation for the camera scene node from yaw and pitch; roll is fixed to zero cameraNode:SetRotation(Quaternion(pitch, yaw, 0)) else -- Move the cursor to the touch position local cursor = ui:GetCursor() if cursor and cursor:IsVisible() then cursor:SetPosition(state.position) end end end end end end function HandleTouchBegin(eventType, eventData) -- On some platforms like Windows the presence of touch input can only be detected dynamically InitTouchInput() UnsubscribeFromEvent("TouchBegin") end -- Create empty XML patch instructions for screen joystick layout if none defined function GetScreenJoystickPatchString() return "" end