//============================== // VRMenuEventHandler::DispatchToPath bool VRMenuEventHandler::DispatchToPath( OvrGuiSys & guiSys, VrFrame const & vrFrame, VRMenuEvent const & event, Array< menuHandle_t > const & path, bool const log ) const { // send to the focus path only -- this list should be parent -> child order for ( int i = 0; i < path.GetSizeI(); ++i ) { VRMenuObject * obj = guiSys.GetVRMenuMgr().ToObject( path[i] ); char const * const indent = " "; // set to if ( obj != NULL && DispatchToComponents( guiSys, vrFrame, event, obj ) ) { if ( log ) { LOG( "%sDispatchToPath: %s, object '%s' consumed event.", &indent[64 - i * 2], VRMenuEvent::EventTypeNames[event.EventType], ( obj != NULL ? obj->GetText().ToCStr() : "<null>" ) ); } return true; // consumed by a component } if ( log ) { LOG( "%sDispatchToPath: %s, object '%s' passed event.", &indent[64 - i * 2], VRMenuEvent::EventTypeNames[event.EventType], obj != NULL ? obj->GetText().ToCStr() : "<null>" ); } } return false; }
//============================== // OvrSliderComponent::OnInit eMsgStatus OvrSliderComponent::OnInit( OvrGuiSys & guiSys, VrFrame const & vrFrame, VRMenuObject * self, VRMenuEvent const & event ) { OVR_UNUSED( vrFrame ); OVR_UNUSED( event ); // find the starting offset of the caret //LOG( "OvrSliderComponent - VRMENU_EVENT_INIT" ); VRMenuObject * caret = guiSys.GetVRMenuMgr().ToObject( self->ChildHandleForId( guiSys.GetVRMenuMgr(), ScrubberId ) ); if ( caret != NULL ) { CaretBasePose = caret->GetLocalPose(); } SetCaretPoseFromFrac( guiSys.GetVRMenuMgr(), self, SliderFrac ); UpdateText( guiSys.GetVRMenuMgr(), self, BubbleId ); return MSG_STATUS_ALIVE; }
//============================== // FindTargetPath static void FindTargetPath( OvrGuiSys & guiSys, menuHandle_t const curHandle, Array< menuHandle_t > & targetPath ) { VRMenuObject * obj = guiSys.GetVRMenuMgr().ToObject( curHandle ); if ( obj != NULL ) { FindTargetPath( guiSys, obj->GetParentHandle(), targetPath ); targetPath.PushBack( curHandle ); } }
//============================== // OvrSliderComponent::OnFrameUpdate eMsgStatus OvrSliderComponent::OnFrameUpdate( OvrGuiSys & guiSys, VrFrame const & vrFrame, VRMenuObject * self, VRMenuEvent const & event ) { OVR_UNUSED( event ); if ( TouchDown ) { UpdateText( guiSys.GetVRMenuMgr(), self, BubbleId ); UpdateText( guiSys.GetVRMenuMgr(), self, TextId ); } if ( BubbleFadeOutTime > 0.0 ) { if ( vrapi_GetTimeInSeconds() >= BubbleFadeOutTime ) { BubbleFadeOutTime = -1.0; BubbleFader.StartFadeOut(); } } VRMenuObject * bubble = guiSys.GetVRMenuMgr().ToObject( self->ChildHandleForId( guiSys.GetVRMenuMgr(), BubbleId ) ); if ( bubble != NULL ) { float const fadeTime = 0.5f; float const fadeRate = 1.0 / fadeTime; BubbleFader.Update( fadeRate, vrFrame.DeltaSeconds ); Vector4f color = bubble->GetColor(); color.w = BubbleFader.GetFinalAlpha(); bubble->SetColor( color ); Vector4f textColor = bubble->GetTextColor(); textColor.w = color.w; bubble->SetTextColor( textColor ); } return MSG_STATUS_ALIVE; }
//============================== // VRMenuEventHandler::HandleEvents void VRMenuEventHandler::HandleEvents( OvrGuiSys & guiSys, VrFrame const & vrFrame, menuHandle_t const rootHandle, Array< VRMenuEvent > const & events ) const { VRMenuObject * root = guiSys.GetVRMenuMgr().ToObject( rootHandle ); if ( root == NULL ) { return; } // find the list of all objects that are in the focused path Array< menuHandle_t > focusPath; FindTargetPath( guiSys, rootHandle, FocusedHandle, focusPath ); Array< menuHandle_t > targetPath; for ( int i = 0; i < events.GetSizeI(); ++i ) { VRMenuEvent const & event = events[i]; switch ( event.DispatchType ) { case EVENT_DISPATCH_BROADCAST: { // broadcast to everything BroadcastEvent( guiSys, vrFrame, event, root ); } break; case EVENT_DISPATCH_FOCUS: // send to the focus path only -- this list should be parent -> child order DispatchToPath( guiSys, vrFrame, event, focusPath, false ); break; case EVENT_DISPATCH_TARGET: if ( targetPath.GetSizeI() == 0 || event.TargetHandle != targetPath.Back() ) { targetPath.Clear(); FindTargetPath( guiSys, rootHandle, event.TargetHandle, targetPath ); } DispatchToPath( guiSys, vrFrame, event, targetPath, false ); break; default: OVR_ASSERT( !"unknown dispatch type" ); break; } } }
//============================== // VRMenuEventHandler::BroadcastEvent bool VRMenuEventHandler::BroadcastEvent( OvrGuiSys & guiSys, VrFrame const & vrFrame, VRMenuEvent const & event, VRMenuObject * receiver ) const { ASSERT_WITH_TAG( receiver != NULL, "VrMenu" ); // allow parent components to handle first if ( DispatchToComponents( guiSys, vrFrame, event, receiver ) ) { return true; } // if the parent did not consume, dispatch to children int numChildren = receiver->NumChildren(); for ( int i = 0; i < numChildren; ++i ) { menuHandle_t childHandle = receiver->GetChildHandleForIndex( i ); VRMenuObject * child = guiSys.GetVRMenuMgr().ToObject( childHandle ); if ( child != NULL && BroadcastEvent( guiSys, vrFrame, event, child ) ) { return true; // consumed by child } } return false; }
OvrVideoMenu::OvrVideoMenu( OvrGuiSys & guiSys, OvrMetaData & metaData, float radius ) : VRMenu( MENU_NAME ) , MetaData( metaData ) , LoadingIconHandle( 0 ) , AttributionHandle( 0 ) , BrowserButtonHandle( 0 ) , VideoControlButtonHandle( 0 ) , Radius( radius ) , ButtonCoolDown( 0.0f ) , OpenTime( 0.0 ) { // Init with empty root Init( guiSys, 0.0f, VRMenuFlags_t() ); // Create Attribution info view Array< VRMenuObjectParms const * > parms; Array< VRMenuComponent* > comps; VRMenuId_t attributionPanelId( ID_CENTER_ROOT.Get() + 10 ); comps.PushBack( new OvrVideoMenuRootComponent( *this ) ); Quatf rot( DOWN, 0.0f ); Vector3f dir( -FWD ); Posef panelPose( rot, dir * Radius ); Vector3f panelScale( 1.0f ); const VRMenuFontParms fontParms( true, true, false, false, true, 0.525f, 0.45f, 1.0f ); VRMenuObjectParms attrParms( VRMENU_STATIC, comps, VRMenuSurfaceParms(), "Attribution Panel", panelPose, panelScale, Posef(), Vector3f( 1.0f ), fontParms, attributionPanelId, VRMenuObjectFlags_t(), VRMenuObjectInitFlags_t( VRMENUOBJECT_INIT_FORCE_POSITION ) ); parms.PushBack( &attrParms ); AddItems( guiSys, parms, GetRootHandle(), false ); parms.Clear(); comps.Clear(); AttributionHandle = HandleForId( guiSys.GetVRMenuMgr(), attributionPanelId ); VRMenuObject * attributionObject = guiSys.GetVRMenuMgr().ToObject( AttributionHandle ); OVR_ASSERT( attributionObject != NULL ); //Browser button float const ICON_HEIGHT = 80.0f * VRMenuObject::DEFAULT_TEXEL_SCALE; Array< VRMenuSurfaceParms > surfParms; Posef browserButtonPose( Quatf(), UP * ICON_HEIGHT * 2.0f ); comps.PushBack( new OvrDefaultComponent( Vector3f( 0.0f, 0.0f, 0.05f ), 1.05f, 0.25f, 0.0f, Vector4f( 1.0f ), Vector4f( 1.0f ) ) ); comps.PushBack( new OvrButton_OnUp( this, ID_BROWSER_BUTTON ) ); comps.PushBack( new OvrSurfaceToggleComponent( ) ); surfParms.PushBack( VRMenuSurfaceParms( "browser", "apk:///assets/nav_home_off.png", SURFACE_TEXTURE_DIFFUSE, NULL, SURFACE_TEXTURE_MAX, NULL, SURFACE_TEXTURE_MAX ) ); surfParms.PushBack( VRMenuSurfaceParms( "browser", "apk:///assets/nav_home_on.png", SURFACE_TEXTURE_DIFFUSE, NULL, SURFACE_TEXTURE_MAX, NULL, SURFACE_TEXTURE_MAX ) ); VRMenuObjectParms browserButtonParms( VRMENU_BUTTON, comps, surfParms, "", browserButtonPose, Vector3f( 1.0f ), Posef(), Vector3f( 1.0f ), fontParms, ID_BROWSER_BUTTON, VRMenuObjectFlags_t( VRMENUOBJECT_DONT_HIT_TEXT ), VRMenuObjectInitFlags_t( VRMENUOBJECT_INIT_FORCE_POSITION ) ); parms.PushBack( &browserButtonParms ); AddItems( guiSys, parms, AttributionHandle, false ); parms.Clear(); comps.Clear(); surfParms.Clear(); BrowserButtonHandle = attributionObject->ChildHandleForId( guiSys.GetVRMenuMgr(), ID_BROWSER_BUTTON ); VRMenuObject * browserButtonObject = guiSys.GetVRMenuMgr().ToObject( BrowserButtonHandle ); OVR_ASSERT( browserButtonObject != NULL ); OVR_UNUSED( browserButtonObject ); //Video control button Posef videoButtonPose( Quatf(), DOWN * ICON_HEIGHT * 2.0f ); comps.PushBack( new OvrDefaultComponent( Vector3f( 0.0f, 0.0f, 0.05f ), 1.05f, 0.25f, 0.0f, Vector4f( 1.0f ), Vector4f( 1.0f ) ) ); comps.PushBack( new OvrButton_OnUp( this, ID_VIDEO_BUTTON ) ); comps.PushBack( new OvrSurfaceToggleComponent( ) ); surfParms.PushBack( VRMenuSurfaceParms( "browser", "apk:///assets/nav_restart_off.png", SURFACE_TEXTURE_DIFFUSE, NULL, SURFACE_TEXTURE_MAX, NULL, SURFACE_TEXTURE_MAX ) ); surfParms.PushBack( VRMenuSurfaceParms( "browser", "apk:///assets/nav_restart_on.png", SURFACE_TEXTURE_DIFFUSE, NULL, SURFACE_TEXTURE_MAX, NULL, SURFACE_TEXTURE_MAX ) ); VRMenuObjectParms controlButtonParms( VRMENU_BUTTON, comps, surfParms, "", videoButtonPose, Vector3f( 1.0f ), Posef(), Vector3f( 1.0f ), fontParms, ID_VIDEO_BUTTON, VRMenuObjectFlags_t( VRMENUOBJECT_DONT_HIT_TEXT ), VRMenuObjectInitFlags_t( VRMENUOBJECT_INIT_FORCE_POSITION ) ); parms.PushBack( &controlButtonParms ); AddItems( guiSys, parms, AttributionHandle, false ); parms.Clear(); comps.Clear(); VideoControlButtonHandle = attributionObject->ChildHandleForId( guiSys.GetVRMenuMgr(), ID_VIDEO_BUTTON ); VRMenuObject * controlButtonObject = guiSys.GetVRMenuMgr().ToObject( VideoControlButtonHandle ); OVR_ASSERT( controlButtonObject != NULL ); OVR_UNUSED( controlButtonObject ); }
//============================== // VRMenuEventHandler::Frame void VRMenuEventHandler::Frame( OvrGuiSys & guiSys, VrFrame const & vrFrame, menuHandle_t const & rootHandle, Posef const & menuPose, Array< VRMenuEvent > & events ) { VRMenuObject * root = guiSys.GetVRMenuMgr().ToObject( rootHandle ); if ( root == NULL ) { return; } // find the object the gaze is touching and update gaze focus const Matrix4f viewMatrix = guiSys.GetApp()->GetLastViewMatrix(); const Vector3f viewPos( GetViewMatrixPosition( viewMatrix ) ); const Vector3f viewFwd( GetViewMatrixForward( viewMatrix ) ); HitTestResult result; menuHandle_t hitHandle = root->HitTest( guiSys, menuPose, viewPos, viewFwd, ContentFlags_t( CONTENT_SOLID ), result ); result.RayStart = viewPos; result.RayDir = viewFwd; VRMenuObject * hit = hitHandle.IsValid() ? guiSys.GetVRMenuMgr().ToObject( hitHandle ) : NULL; /* if ( hit != NULL ) { guiSys.GetApp()->ShowInfoText( 0.0f, "%s", hit->GetText().ToCStr() ); } */ bool focusChanged = ( hitHandle != FocusedHandle ); if ( focusChanged ) { // focus changed VRMenuObject * oldFocus = guiSys.GetVRMenuMgr().ToObject( FocusedHandle ); if ( oldFocus != NULL ) { // setup event for item losing the focus VRMenuEvent event( VRMENU_EVENT_FOCUS_LOST, EVENT_DISPATCH_TARGET, FocusedHandle, Vector3f( 0.0f ), result ); events.PushBack( event ); } if ( hit != NULL ) { if ( ( hit->GetFlags() & VRMENUOBJECT_FLAG_NO_FOCUS_GAINED ) == 0 ) { // set up event for item gaining the focus VRMenuEvent event( VRMENU_EVENT_FOCUS_GAINED, EVENT_DISPATCH_FOCUS, hitHandle, Vector3f( 0.0f ), result ); events.PushBack( event ); } } FocusedHandle = hitHandle; } if ( ( vrFrame.Input.buttonPressed & BUTTON_SWIPE_UP ) != 0 ) { VRMenuEvent event( VRMENU_EVENT_SWIPE_UP, EVENT_DISPATCH_FOCUS, FocusedHandle, Vector3f( 0.0f ), result ); events.PushBack( event ); } if ( ( vrFrame.Input.buttonPressed & BUTTON_SWIPE_DOWN ) != 0 ) { VRMenuEvent event( VRMENU_EVENT_SWIPE_DOWN, EVENT_DISPATCH_FOCUS, FocusedHandle, Vector3f( 0.0f ), result ); events.PushBack( event ); } if ( ( vrFrame.Input.buttonPressed & BUTTON_SWIPE_FORWARD ) != 0 ) { VRMenuEvent event( VRMENU_EVENT_SWIPE_FORWARD, EVENT_DISPATCH_FOCUS, FocusedHandle, Vector3f( 0.0f ), result ); events.PushBack( event ); } if ( ( vrFrame.Input.buttonPressed & BUTTON_SWIPE_BACK ) != 0 ) { VRMenuEvent event( VRMENU_EVENT_SWIPE_BACK, EVENT_DISPATCH_FOCUS, FocusedHandle, Vector3f( 0.0f ), result ); events.PushBack( event ); } bool touchPressed = ( vrFrame.Input.buttonPressed & ( BUTTON_TOUCH | BUTTON_A ) ) != 0; bool touchReleased = !touchPressed && ( vrFrame.Input.buttonReleased & ( BUTTON_TOUCH | BUTTON_A ) ) != 0; bool touchDown = ( vrFrame.Input.buttonState & BUTTON_TOUCH ) != 0; // Need to update this for keyboard events as well for ( int i = 0; i < vrFrame.Input.NumKeyEvents; i++ ) { if ( vrFrame.Input.KeyEvents[i].KeyCode == OVR_KEY_RETURN ) { switch ( vrFrame.Input.KeyEvents[i].EventType ) { case KEY_EVENT_DOWN: touchPressed = true; break; case KEY_EVENT_UP: touchReleased = true; break; default: break; } } } /* // report swipe data char const * swipeNames[5] = { "none", "down", "up", "back", "forward" }; int swipeUpDown = ( vrFrame.Input.buttonPressed & BUTTON_SWIPE_UP ) ? 2 : 0; swipeUpDown = ( vrFrame.Input.buttonPressed & BUTTON_SWIPE_DOWN ) ? 1 : swipeUpDown; int swipeForwardBack = ( vrFrame.Input.buttonPressed & BUTTON_SWIPE_FORWARD ) ? 4 : 0; swipeForwardBack = ( vrFrame.Input.buttonPressed & BUTTON_SWIPE_BACK ) ? 3 : swipeForwardBack; guiSys.GetApp()->ShowInfoText( 1.0f, "touch %s\n( %s, %s )\n( %.2f, %.2f )\n( %.2f, %.2f )", touchDown ? swipeNames[1] : swipeNames[2], swipeNames[swipeUpDown], swipeNames[swipeForwardBack], vrFrame.Input.touch[0], vrFrame.Input.touch[1], vrFrame.Input.touchRelative[0], vrFrame.Input.touchRelative[1] ); */ // if nothing is focused, send events to the root if ( touchPressed ) { VRMenuEvent event( VRMENU_EVENT_TOUCH_DOWN, EVENT_DISPATCH_FOCUS, FocusedHandle, Vector3f( 0.0f ), result ); events.PushBack( event ); } if ( touchReleased ) { VRMenuEvent event( VRMENU_EVENT_TOUCH_UP, EVENT_DISPATCH_FOCUS, FocusedHandle, Vector3f( vrFrame.Input.touchRelative, 0.0f ), result ); events.PushBack( event ); } if ( touchDown ) { if ( vrFrame.Input.touchRelative.LengthSq() > Mathf::SmallestNonDenormal ) { VRMenuEvent event( VRMENU_EVENT_TOUCH_RELATIVE, EVENT_DISPATCH_FOCUS, FocusedHandle, Vector3f( vrFrame.Input.touchRelative, 0.0f ), result ); events.PushBack( event ); } VRMenuEvent event( VRMENU_EVENT_TOUCH_ABSOLUTE, EVENT_DISPATCH_FOCUS, FocusedHandle, Vector3f( vrFrame.Input.touch, 0.0f ), result ); events.PushBack( event ); } { // always post the frame event to the root VRMenuEvent event( VRMENU_EVENT_FRAME_UPDATE, EVENT_DISPATCH_BROADCAST, menuHandle_t(), Vector3f( 0.0f ), result ); events.PushBack( event ); } }
//============================== // OvrSliderComponent::OnTouchUp eMsgStatus OvrSliderComponent::OnTouchUp( OvrGuiSys & guiSys, VrFrame const & vrFrame, VRMenuObject * self, VRMenuEvent const & event ) { OVR_UNUSED( guiSys ); OVR_UNUSED( vrFrame ); OVR_UNUSED( self ); OVR_UNUSED( event ); BubbleFadeOutTime = vrapi_GetTimeInSeconds() + 1.5; //LOG( "event.FloatValue = ( %.8f, %.8f )", event.FloatValue.x, event.FloatValue.y ); // project on to the normalized slide delta so that the movement on the pad matches the orientation of the slider Vector2f slideDelta( LocalSlideDelta.x, LocalSlideDelta.y ); slideDelta.Normalize(); Vector2f touchXY( event.FloatValue.x, event.FloatValue.y ); float dot = slideDelta.Dot( touchXY ); if ( fabsf( dot ) < 0.7071f ) { // if we're more than 45 degrees off axis, don't move at all dot = 0.0f; } else { // move as if we were perfectly aligned with the slider direction if ( dot < 0.0f ) { dot = -1.0f; } else { dot = 1.0f; } } LastDot = dot; if ( LastDot != 0.0f ) { float range = MaxValue - MinValue; float cur = floor( SliderFrac * range ) + MinValue; if ( LastDot < 0.0f ) { SliderFrac = ( cur + 1.0f ) * ( 1.0f / range ); } else { SliderFrac = ( cur - 1.0f ) * ( 1.0f / range ); } SliderFrac = Alg::Clamp( SliderFrac, 0.0f, 1.0f ); SetCaretPoseFromFrac( guiSys.GetVRMenuMgr(), self, SliderFrac ); Menu.OnItemEvent( guiSys, RootId, event ); // update the bubble text UpdateText( guiSys.GetVRMenuMgr(), self, BubbleId ); } LastDot = 0.0f; return MSG_STATUS_CONSUMED; }