/**
 * Sets new system settings (optionally writes out to the ini). 
 */
void FSystemSettings::ApplyNewSettings( const FSystemSettingsData& NewSettings, bool bWriteToIni )
{
	// we can set any setting before the engine is initialized so don't bother restoring values.
	bool bEngineIsInitialized = GEngine != NULL;

	// if the engine is running, there are certain values we can't set immediately
	if (bEngineIsInitialized)
	{
		// apply settings to the runtime system.
		ApplySettingsAtRuntime(NewSettings, bWriteToIni);

		ApplyOverrides();
	}
	else
	{
		// if the engine is not initialized we don't need to worry about all the deferred settings etc. 
		// as we do above.
		// Set new settings. Would look prettier if we didn't derive from the Data class...
		(FSystemSettingsData&)(*this) = NewSettings;

		// If requested, save the settings to ini.
		if ( bWriteToIni )
		{
			SaveToIni();
		}

		ApplyOverrides();
	}
}
/**
 * Exec handler implementation.
 *
 * @param InWorld World context
 * @param Cmd	Command to parse
 * @param Ar	Output device to log to
 *
 * @return true if command was handled, false otherwise
 */
bool FSystemSettings::Exec( UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar )
{
	FSystemSettingsData OldSystemSettings = *this;

	// Keep track whether the command was handled or not.
	bool bHandledCommand = false;

	if( FParse::Command(&Cmd,TEXT("SCALE")) )
	{
		// Some of these settings are used in both threads so we need to stop the rendering thread before changing them.
		FlushRenderingCommands();

		if( FParse::Command(&Cmd,TEXT("LOWEND")) )
		{
			bHandledCommand	= HandleLowendCommand( Cmd, Ar );
		}
		else if( FParse::Command(&Cmd,TEXT("HIGHEND")) )
		{
			bHandledCommand	= HandleHighendCommand( Cmd, Ar );	
		}

		if (!bHandledCommand)
		{
			Ar.Logf(TEXT("Unrecognized system setting (note that console variables can be set much easier)"));
		}
		else
		{
			// Write the new settings to the INI.
			SaveToIni();
		}
	}

	return bHandledCommand;
}
void FSteamVRHMD::Shutdown()
{
	if (VRSystem != nullptr)
	{
		// save any runtime configuration changes to the .ini
		SaveToIni();

		// shut down our headset
		VRSystem = nullptr;
		SteamVRPlugin->SetVRSystem(nullptr);
		//vr::VR_Shutdown();
		(*VRShutdownFn)();
	}

	// unload OpenVR library
	UnloadOpenVRModule();
}
/**
 * Helper for ApplyNewSettings when the engine is running. Applies the changes needed for the runtime system.
 *
 * We can assume the game is running if this code is called.
 */
void FSystemSettings::ApplySettingsAtRuntime(const FSystemSettingsData& NewSettings, bool bWriteToIni)
{
	// Some of these settings are shared between threads, so we
	// must flush the rendering thread before changing anything.
	FlushRenderingCommands();

	// Track settings we might have to put back
	FExposedTextureLODSettings InMemoryTextureLODSettings = TextureLODSettings;

	// Read settings from .ini.  This is necessary because settings which need to wait for a restart
	// will be on disk but may not be in memory.  Therefore, we read from disk before capturing old
	// values to revert to.
	LoadFromIni();

	// see what settings are actually changing.
	// Ugly casts because system settings is multi-inherited from all the consituent classes for backwards compatibility

	// Texture Detail
	bool bTextureDetailChanged = (const FSystemSettingsDataTextureDetail&)(*this) != (const FSystemSettingsDataTextureDetail&)NewSettings;

	// Make a copy of the existing settings so we can compare for changes
	FSystemSettingsData OldData = *this;

	// Set new settings. Would look prettier if we didn't derive from the Data class...
	(FSystemSettingsData&)(*this) = NewSettings;

	// apply any runtime changes that need to be made
	bool bUpdateTextureStreamingSucceeded = false;
	if (bTextureDetailChanged)
	{
		bUpdateTextureStreamingSucceeded = UTexture::ForceUpdateTextureStreaming();
	}

	// If requested, save the settings to ini.
	if ( bWriteToIni )
	{
		SaveToIni();
	}

	// If texture detail settings couldn't be applied because we're loading seekfree,
	// revert the new settings to their previous in-memory values.
	if ( bTextureDetailChanged && !bUpdateTextureStreamingSucceeded )
	{
		TextureLODSettings = InMemoryTextureLODSettings;
	}
}