Camera tools

This commit is contained in:
Lillith Rose 2025-12-04 19:16:38 -05:00
parent 0a1852e0c9
commit e608e2a56b
17 changed files with 384 additions and 0 deletions

8
CamToImage/Runtime.meta Normal file
View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 14ddfe4ade1ec0945b8355ace2110882
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,14 @@
{
"name": "CamToImage",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 32d7f771e78b8bf41b2d888d99ac3867
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,99 @@
using System.IO;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace gay.lilyy.PlaneCam
{
[AddComponentMenu("LillithRosePup/Camera To Image")]
[RequireComponent(typeof(Camera))]
public class PlaneCam : MonoBehaviour, VRC.SDKBase.IEditorOnly
{
private const string DefaultOutputImagePath = "Output.png";
public string outputImagePath = DefaultOutputImagePath;
[Tooltip("If set to a value greater than 0, the image will be scaled so its longest side matches this value while maintaining aspect ratio")]
public int longestSide = 1024;
}
#if UNITY_EDITOR
[CustomEditor(typeof(PlaneCam))]
public class PlaneCamEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button("Capture Image"))
{
var camera = target as PlaneCam;
}
}
private void CaptureImage(PlaneCam camDef) {
var camera = camDef.GetComponent<Camera>();
float aspectRatio = camera.aspect;
int cameraWidth = camera.pixelWidth;
int cameraHeight = camera.pixelHeight;
int outputWidth, outputHeight;
if (aspectRatio > 1f)
{
outputHeight = cameraHeight;
outputWidth = Mathf.RoundToInt(cameraHeight * aspectRatio);
if (outputWidth > cameraWidth)
{
outputWidth = cameraWidth;
outputHeight = Mathf.RoundToInt(cameraWidth / aspectRatio);
}
}
else
{
outputWidth = cameraWidth;
outputHeight = Mathf.RoundToInt(cameraWidth / aspectRatio);
if (outputHeight > cameraHeight)
{
outputHeight = cameraHeight;
outputWidth = Mathf.RoundToInt(cameraHeight * aspectRatio);
}
}
// Scale to longest side if specified
if (camDef.longestSide > 0)
{
int currentLongestSide = Mathf.Max(outputWidth, outputHeight);
if (currentLongestSide != camDef.longestSide)
{
float scale = (float)camDef.longestSide / currentLongestSide;
outputWidth = Mathf.RoundToInt(outputWidth * scale);
outputHeight = Mathf.RoundToInt(outputHeight * scale);
}
}
var renderTexture = new RenderTexture(outputWidth, outputHeight, 24);
camera.targetTexture = renderTexture;
camera.Render();
var screenshot = new Texture2D(outputWidth, outputHeight, TextureFormat.ARGB32, false);
RenderTexture.active = renderTexture;
screenshot.ReadPixels(new Rect(0, 0, outputWidth, outputHeight), 0, 0);
screenshot.Apply();
RenderTexture.active = null;
camera.targetTexture = null;
renderTexture.Release();
var bytes = screenshot.EncodeToPNG();
File.WriteAllBytes("Assets/" + camDef.outputImagePath, bytes);
AssetDatabase.Refresh();
Debug.Log($"Image captured and saved to: Assets/{camDef.outputImagePath}. Aspect Ratio: {aspectRatio:F2} ({outputWidth}x{outputHeight})");
}
}
#endif
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 007ac06a66da7cb4b86fde9e783da04d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: