コード例 #1
0
/**
 * Called when a Leap Motion controller is plugged in, unplugged, or the device changes state.
 *
 * State changes include entering or leaving robust mode and low resource mode.
 * Note that there is no direct way to query whether the device is in these modes,
 * although you can use Controller::isLightingBad() to check if there are environmental
 * IR lighting problems.
 *
 * \include Listener_onDeviceChange.txt
 *
 * @param controller The Controller object invoking this callback function.
 * @since 1.2
 */
void CServerDriver_Leap::onDeviceChange(const Controller&controller)
{
    DriverLog("CServerDriver_Leap::onDeviceChange()\n");

    if (controller.isConnected())
    {
        bool backgroundModeAllowed = controller.config().getInt32("background_app_mode") == 2;
        if (!backgroundModeAllowed) {
            // TODO: Show dialog to request permission to allow background mode apps
            bool userPermission = true;
            if (userPermission) {
                controller.config().setInt32("background_app_mode", 2);
                controller.config().save();
            }
        }

        controller.setPolicy(Leap::Controller::POLICY_OPTIMIZE_HMD);
        controller.setPolicy(Leap::Controller::POLICY_BACKGROUND_FRAMES);

        // make sure we always get background frames even when we lose the focus to another
        // Leap-enabled application
        controller.setPolicy((Leap::Controller::PolicyFlag)(15));

        // allow other background applications to receive frames even when SteamVR has the focus.
        controller.setPolicy((Leap::Controller::PolicyFlag)(23));

        ScanForNewControllers(true);
    }
    else
    {
        for (auto it = m_vecControllers.begin(); it != m_vecControllers.end(); ++it)
            delete (*it);
        m_vecControllers.clear();
    }
}
コード例 #2
0
vr::EVRInitError CServerDriver_Hydra::Init( vr::IDriverLog * pDriverLog, vr::IServerDriverHost * pDriverHost, const char * pchUserDriverConfigDir, const char * pchDriverInstallDir )
{
	InitDriverLog( pDriverLog );
	m_pDriverHost = pDriverHost;
	m_strDriverInstallDir = pchDriverInstallDir;

	if ( sixenseInit() != SIXENSE_SUCCESS )
		return vr::VRInitError_Driver_Failed;

	// Will not immediately detect controllers at this point.  Sixense driver must be initializing
	// in its own thread...  It's okay to dynamically detect devices later, but if controllers are
	// the only devices (e.g. requireHmd=false) we must have GetTrackedDeviceCount() != 0 before returning.
	for ( int i = 0; i < 20; ++i )
	{
		ScanForNewControllers( false );
		if ( GetTrackedDeviceCount() )
			break;
		Sleep( 100 );
	}

	m_Thread = std::thread( ThreadEntry, this );

	return vr::VRInitError_None;
}
コード例 #3
0
void CServerDriver_Hydra::ThreadFunc()
{
	// We know the sixense SDK thread is running at "60 FPS", but we don't know when
	// those frames are.  To minimize latency, we sleep for slightly less than the
	// target rate, and detect when the frame has not advanced to wait a bit longer.
	auto longInterval = std::chrono::milliseconds( 16 );
	auto retryInterval = std::chrono::milliseconds( 2 );
	auto scanInterval = std::chrono::seconds( 1 );
	auto pollDeadline = std::chrono::steady_clock::now();
	auto scanDeadline = std::chrono::steady_clock::now() + scanInterval;

#ifdef _WIN32
	// Request at least 2ms timing granularity for the life of this process
	timeBeginPeriod( 2 );
#endif

	while ( !m_bStopRequested )
	{
		// Check for new controllers here because sixense API is modal
		// (e.g. sixenseSetActiveBase()) so it can't happen in parallel with pose updates
		if ( pollDeadline > scanDeadline )
		{
			ScanForNewControllers( true );
			scanDeadline += scanInterval;
		}

		bool bAnyActivated = false;
		bool bAllUpdated = true;
		for ( int base = 0; base < sixenseGetMaxBases(); ++base )
		{
			if ( !sixenseIsBaseConnected( base ) )
				continue;

			sixenseAllControllerData acd;

			sixenseSetActiveBase( base );
			if ( sixenseGetAllNewestData( &acd ) != SIXENSE_SUCCESS )
				continue;
			for ( int id = 0; id < sixenseGetMaxControllers(); ++id )
			{
				for ( auto it = m_vecControllers.begin(); it != m_vecControllers.end(); ++it )
				{
					CHydraHmdLatest *pHydra = *it;
					if ( pHydra->IsActivated() && pHydra->HasControllerId( base, id ) )
					{
						bAnyActivated = true;
						// Returns true if this is new data (so we can sleep for long interval)
						if ( !pHydra->Update( acd.controllers[id] ) )
						{
							bAllUpdated = false;
						}
						break;
					}
				}
			}
		}

		CheckForChordedSystemButtons();

		// If everyone just got new data, we can wait about 1/60s, else try again soon
		pollDeadline += !bAnyActivated ? scanInterval :
			               bAllUpdated ? longInterval : retryInterval;
		std::this_thread::sleep_until( pollDeadline );
	}

#ifdef _WIN32
	timeEndPeriod( 2 );
#endif
}