/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
using UnityEditor;
using System.IO;
///
/// From the selected transform, takes a cubemap screenshot that can be submitted with the application
/// as a screenshot (or additionally used for reflection shaders).
///
class OVRScreenshotWizard : ScriptableWizard
{
public enum TexFormat
{
JPEG, // 512kb at 1k x 1k resolution vs
PNG, // 5.3mb
}
public enum SaveMode {
SaveCubemapScreenshot,
SaveUnityCubemap,
SaveBoth,
}
public GameObject renderFrom = null;
public int size = 2048;
public SaveMode saveMode = SaveMode.SaveUnityCubemap;
public string cubeMapFolder = "Assets/Textures/Cubemaps";
public TexFormat textureFormat = TexFormat.PNG;
///
/// Validates the user's input
///
void OnWizardUpdate()
{
helpString = "Select a game object positioned in the place where\nyou want to render the cubemap screenshot from: ";
isValid = (renderFrom != null);
}
///
/// Create the asset path if it is not available.
/// Assuming the newFolderPath is stated with "Assets", which is a requirement.
///
static bool CreateAssetPath( string newFolderPath )
{
const int maxFoldersCount = 32;
string currentPath;
string[] pathFolders;
pathFolders = newFolderPath.Split (new char[]{ '/' }, maxFoldersCount);
if (!string.Equals ("Assets", pathFolders [0], System.StringComparison.OrdinalIgnoreCase))
{
Debug.LogError( "Folder path has to be started with \" Assets \" " );
return false;
}
currentPath = "Assets";
for (int i = 1; i < pathFolders.Length; i++)
{
if (!string.IsNullOrEmpty(pathFolders[i]))
{
string newPath = currentPath + "/" + pathFolders[i];
if (!AssetDatabase.IsValidFolder(newPath))
AssetDatabase.CreateFolder(currentPath, pathFolders[i]);
currentPath = newPath;
}
}
Debug.Log( "Created path: " + currentPath );
return true;
}
///
/// Renders the cubemap
///
void OnWizardCreate()
{
if ( !AssetDatabase.IsValidFolder( cubeMapFolder ) )
{
if (!CreateAssetPath(cubeMapFolder))
{
Debug.LogError( "Created path failed: " + cubeMapFolder );
return;
}
}
bool existingCamera = true;
bool existingCameraStateSave = true;
Camera camera = renderFrom.GetComponent();
if (camera == null)
{
camera = renderFrom.AddComponent();
camera.farClipPlane = 10000f;
existingCamera = false;
}
else
{
existingCameraStateSave = camera.enabled;
camera.enabled = true;
}
// find the last screenshot saved
if (cubeMapFolder[cubeMapFolder.Length-1] != '/')
{
cubeMapFolder += "/";
}
int idx = 0;
string[] fileNames = Directory.GetFiles(cubeMapFolder);
foreach(string fileName in fileNames)
{
if (!fileName.ToLower().EndsWith(".cubemap"))
{
continue;
}
string temp = fileName.Replace(cubeMapFolder + "vr_screenshot_", string.Empty);
temp = temp.Replace(".cubemap", string.Empty);
int tempIdx = 0;
if (int.TryParse( temp, out tempIdx ))
{
if (tempIdx > idx)
{
idx = tempIdx;
}
}
}
string pathName = string.Format("{0}vr_screenshot_{1}.cubemap", cubeMapFolder, (++idx).ToString("d2"));
Cubemap cubemap = new Cubemap(size, TextureFormat.RGB24, false);
// render into cubemap
if ((camera != null) && (cubemap != null))
{
// set up cubemap defaults
OVRCubemapCapture.RenderIntoCubemap(camera, cubemap);
if (existingCamera)
{
camera.enabled = existingCameraStateSave;
}
else
{
DestroyImmediate(camera);
}
// generate a regular texture as well?
if ( ( saveMode == SaveMode.SaveCubemapScreenshot ) || ( saveMode == SaveMode.SaveBoth ) )
{
GenerateTexture(cubemap, pathName);
}
if ( ( saveMode == SaveMode.SaveUnityCubemap ) || ( saveMode == SaveMode.SaveBoth ) )
{
Debug.Log( "Saving: " + pathName );
// by default the unity cubemap isn't saved
AssetDatabase.CreateAsset( cubemap, pathName );
// reimport as necessary
AssetDatabase.SaveAssets();
// select it in the project tree so developers can find it
EditorGUIUtility.PingObject( cubemap );
Selection.activeObject = cubemap;
}
AssetDatabase.Refresh();
}
}
///
/// Generates a NPOT 6x1 cubemap in the following format PX NX PY NY PZ NZ
///
void GenerateTexture(Cubemap cubemap, string pathName)
{
// Encode the texture and save it to disk
pathName = pathName.Replace(".cubemap", (textureFormat == TexFormat.PNG) ? ".png" : ".jpg" ).ToLower();
pathName = pathName.Replace( cubeMapFolder.ToLower(), "" );
string format = textureFormat.ToString();
string fullPath = EditorUtility.SaveFilePanel( string.Format( "Save Cubemap Screenshot as {0}", format ), "", pathName, format.ToLower() );
if ( !string.IsNullOrEmpty( fullPath ) )
{
Debug.Log( "Saving: " + fullPath );
OVRCubemapCapture.SaveCubemapCapture(cubemap, fullPath);
}
}
///
/// Unity Editor menu option to take a screenshot
///
[MenuItem("Oculus/Tools/OVR Screenshot Wizard", false, 100000)]
static void TakeOVRScreenshot()
{
OVRScreenshotWizard wizard = ScriptableWizard.DisplayWizard("OVR Screenshot Wizard", "Render Cubemap");
if (wizard != null)
{
if (Selection.activeGameObject != null)
wizard.renderFrom = Selection.activeGameObject;
else
wizard.renderFrom = Camera.main.gameObject;
wizard.isValid = (wizard.renderFrom != null);
}
}
}