-
-
Save Nikspace2/7e9904522341ff3587fa to your computer and use it in GitHub Desktop.
Qubicle Updater for PicaVoxel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using PicaVoxel; | |
using System.IO; | |
using UnityEditor; | |
using UnityEngine; | |
/// <summary> | |
/// Custom Inspector for the .qb files to import faster. | |
/// It's not optimized it checks every time you select an object in the Project Panel but i don't know any other way to do it :D | |
/// I used your QubicleImportWindow. But i like it more this way. Check it out. | |
/// </summary> | |
[CustomEditor(typeof(Object), true)] | |
public class QubicleFileInspector : Editor | |
{ | |
// PicaVoxel QubicleImportW Values | |
static float voxelSize = 0.1f; | |
static string objectName = "Qubicle Import"; | |
static string ext = "qb"; | |
static bool showImport = false; | |
static Object m_lastObject = null; | |
private void OnEnable() | |
{ | |
voxelSize = 0.1f; | |
objectName = "Qubicle Import"; | |
} | |
/// <summary> | |
/// Override what the inspector shows | |
/// </summary> | |
public override void OnInspectorGUI() | |
{ | |
#region Checkc File Extension | |
// check if the object changes | |
bool objectChanged = false; | |
if(m_lastObject != target) | |
{ | |
showImport = false; | |
m_lastObject = target; | |
objectChanged = true; | |
} | |
// nothing to do | |
if(null == target) | |
{ | |
return; | |
} | |
// only read contents when the object changes | |
if(objectChanged) | |
{ | |
// Print the path of the created asset | |
string assetPath = AssetDatabase.GetAssetPath(target); | |
if(!string.IsNullOrEmpty(assetPath)) | |
{ | |
// get the file extension | |
string extension = Path.GetExtension(assetPath); | |
if(string.IsNullOrEmpty(extension)) | |
{ | |
extension = string.Empty; | |
} | |
else | |
{ | |
extension = extension.ToLower(); | |
} | |
if(ext.Equals(extension)) | |
{ | |
showImport = true; | |
} | |
} | |
} | |
#endregion Checkc File Extension | |
// Show Importer GUI | |
if(showImport) | |
{ | |
GUI.enabled = true; | |
ImporterStyles.ShowTitle("Qubicle Import"); | |
EditorGUILayout.Space(); | |
objectName = EditorGUILayout.TextField("Volume name: ", objectName); | |
EditorGUILayout.Space(); | |
voxelSize = EditorGUILayout.FloatField("Voxel size: ", voxelSize); | |
EditorGUILayout.Space(); | |
if(ImporterStyles.BigOrangeButton("Import in Scene")) | |
QubicleImporter.QubicleImport(AssetDatabase.GetAssetPath(target), objectName, voxelSize); | |
GUI.enabled = false; | |
} | |
} | |
} | |
/// <summary> | |
/// Custom Editor Styles | |
/// Because we've got style baby. | |
/// </summary> | |
public static class ImporterStyles | |
{ | |
static GUIStyle whiteBoldButtonStyle; | |
static GUIStyle topLanguageBox; | |
public static GUIStyle WhiteBoldButtonStyle | |
{ | |
get | |
{ | |
if(whiteBoldButtonStyle == null) | |
{ | |
whiteBoldButtonStyle = new GUIStyle("button"); | |
whiteBoldButtonStyle.normal.textColor = Color.white; | |
whiteBoldButtonStyle.active.textColor = Color.white; | |
whiteBoldButtonStyle.fontStyle = FontStyle.Bold; | |
} | |
return whiteBoldButtonStyle; | |
} | |
} | |
public static bool BigOrangeButton(string content) | |
{ | |
GUI.backgroundColor = new Color(0.87f, 0.45f, 0.14f); | |
bool result = GUILayout.Button(content, WhiteBoldButtonStyle, GUILayout.Height(30)); | |
GUI.backgroundColor = new Color(1f, 1f, 1f); | |
return result; | |
} | |
public static void ShowTitle(string title) | |
{ | |
EditorGUILayout.BeginHorizontal("box", GUILayout.Height(20)); | |
GUILayout.FlexibleSpace(); | |
GUILayout.Label(title, EditorStyles.boldLabel); | |
GUILayout.FlexibleSpace(); | |
EditorGUILayout.EndHorizontal(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using UnityEngine; | |
/// <summary> | |
/// Just a reference MonoBehaviour to keep the selected values | |
/// on the custom Inspector. | |
/// </summary> | |
public class QubicleUpdater : MonoBehaviour | |
{ | |
public Object qubicleFile; | |
public Dictionary<int, string> qubicleVolumes; | |
public uint selectedVolume = 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using PicaVoxel; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using UnityEditor; | |
using UnityEngine; | |
/// <summary> | |
/// The Qubicle Updater main file | |
/// </summary> | |
[RequireComponent(typeof(Volume))] | |
[CustomEditor(typeof(QubicleUpdater))] | |
public class QubicleUpdaterEditor : Editor | |
{ | |
private QubicleUpdater quibicleUpdater; | |
public bool changeName = true; | |
public bool changePivotPoint = true; | |
public bool changeTransform = true; | |
private void OnEnable() | |
{ | |
quibicleUpdater = (QubicleUpdater)target; | |
} | |
private void CleanVales() | |
{ | |
quibicleUpdater.selectedVolume = 0; | |
} | |
public override void OnInspectorGUI() | |
{ | |
quibicleUpdater.qubicleFile = (UnityEngine.Object)EditorGUILayout.ObjectField("Qubicle File :", quibicleUpdater.qubicleFile, typeof(UnityEngine.Object)); | |
EditorGUI.BeginDisabledGroup((Path.GetExtension(AssetDatabase.GetAssetPath(quibicleUpdater.qubicleFile)) != ".qb")); | |
if(GUILayout.Button("Refresh File")) | |
{ | |
ReadQubicle(); | |
} | |
EditorGUI.EndDisabledGroup(); | |
if(quibicleUpdater.qubicleFile == null) | |
{ | |
CleanVales(); | |
return; | |
} | |
else | |
{ | |
ReadQubicle(); | |
} | |
if(quibicleUpdater.qubicleVolumes.Count != 0) | |
{ | |
quibicleUpdater.selectedVolume = (uint)EditorGUILayout.Popup("Quibicle Volume", (int)quibicleUpdater.selectedVolume, quibicleUpdater.qubicleVolumes.Values.ToArray()); | |
} | |
changeName = EditorGUILayout.Toggle("Change Name : ", changeName); | |
changePivotPoint = EditorGUILayout.Toggle("Change Pivot Point : ", changePivotPoint); | |
changeTransform = EditorGUILayout.Toggle("Change Transform Point : ", changeTransform); | |
if(GUILayout.Button("Update Volume")) | |
{ | |
UpdateQubicle(); | |
} | |
EditorGUILayout.Space(); | |
} | |
public void ReadQubicle() | |
{ | |
float voxelSize = quibicleUpdater.GetComponent<Volume>().VoxelSize; | |
string fn = AssetDatabase.GetAssetPath(quibicleUpdater.qubicleFile); | |
using(BinaryReader stream = new BinaryReader(new FileStream(fn, FileMode.Open))) | |
{ | |
UpdateQubicle(false, stream, Path.GetFileNameWithoutExtension(fn), voxelSize); | |
} | |
} | |
public void UpdateQubicle() | |
{ | |
float voxelSize = quibicleUpdater.GetComponent<Volume>().VoxelSize; | |
string fn = AssetDatabase.GetAssetPath(quibicleUpdater.qubicleFile); | |
using(BinaryReader stream = new BinaryReader(new FileStream(fn, FileMode.Open))) | |
{ | |
UpdateQubicle(true, stream, Path.GetFileNameWithoutExtension(fn), voxelSize); | |
} | |
} | |
private void UpdateQubicle(bool isUpdateing, BinaryReader stream, string volumeName, float voxelSize) | |
{ | |
quibicleUpdater.qubicleVolumes = new Dictionary<int, string>(); | |
#region Qubicle Fields | |
uint sizex = 0; | |
uint sizey = 0; | |
uint sizez = 0; | |
// uint version; | |
uint colorFormat; | |
uint zAxisOrientation; | |
uint compressed; | |
// uint visibilityMaskEncoded; | |
uint numMatrices; | |
uint i; | |
uint j; | |
uint x; | |
uint y; | |
uint z; | |
int posX; | |
int posY; | |
int posZ; | |
uint[, ,] matrix; | |
List<uint[, ,]> matrixList = new List<uint[, ,]>(); | |
uint index; | |
uint data; | |
uint count; | |
const uint CODEFLAG = 2; | |
const uint NEXTSLICEFLAG = 6; | |
#endregion Qubicle Fields | |
//version = stream.ReadUInt32(); | |
stream.ReadUInt32(); | |
colorFormat = stream.ReadUInt32(); | |
zAxisOrientation = stream.ReadUInt32(); | |
compressed = stream.ReadUInt32(); | |
//visibilityMaskEncoded = stream.ReadUInt32(); | |
stream.ReadUInt32(); | |
numMatrices = stream.ReadUInt32(); | |
for(i = 0; i < numMatrices; i++) // for each matrix stored in file | |
{ | |
// Your Importer code | |
#region ReadAllMatrices | |
// read matrix name | |
byte nameLength = stream.ReadByte(); | |
string name = new string(stream.ReadChars(nameLength)); | |
// read matrix size | |
sizex = stream.ReadUInt32(); | |
sizey = stream.ReadUInt32(); | |
sizez = stream.ReadUInt32(); | |
// read matrix position (in this example the position is irrelevant) | |
posX = stream.ReadInt32(); | |
posY = stream.ReadInt32(); | |
posZ = stream.ReadInt32(); | |
// create matrix and add to matrix list | |
matrix = new uint[sizex, sizey, sizez]; | |
matrixList.Add(matrix); | |
if(compressed == 0) // if uncompressd | |
{ | |
for(z = 0; z < sizez; z++) | |
for(y = 0; y < sizey; y++) | |
for(x = 0; x < sizex; x++) | |
matrix[x, y, z] = stream.ReadUInt32(); | |
} | |
else // if compressed | |
{ | |
z = 0; | |
while(z < sizez) | |
{ | |
index = 0; | |
while(true) | |
{ | |
data = stream.ReadUInt32(); | |
if(data == NEXTSLICEFLAG) | |
break; | |
else if(data == CODEFLAG) | |
{ | |
count = stream.ReadUInt32(); | |
data = stream.ReadUInt32(); | |
for(j = 0; j < count; j++) | |
{ | |
x = index % sizex; // mod = modulo e.g. 12 mod 8 = 4 | |
y = index / sizex; // div = integer division e.g. 12 div 8 = 1 | |
index++; | |
matrix[x, y, z] = data; | |
} | |
} | |
else | |
{ | |
x = index % sizex; | |
y = index / sizex; | |
index++; | |
matrix[x, y, z] = data; | |
} | |
} | |
z++; | |
} | |
} | |
#endregion ReadAllMatrices | |
if(!isUpdateing) | |
{ | |
// Add them matrices to the list | |
quibicleUpdater.qubicleVolumes.Add((int)i, (name != "") ? name : volumeName); | |
} | |
else | |
{ | |
// Update to the selected matrix | |
if(i == quibicleUpdater.selectedVolume) | |
{ | |
/// NOTE | |
// I skipped the splitting because it never worked for me even at your Importer i always get ArgumentException | |
// so i changed MAX_VOLUME_DIMENSION to be able to import bigger matrices. | |
// Single volume | |
var newObject = quibicleUpdater.gameObject; | |
//newObject.transform.localPosition = Vector3.zero; | |
if(newObject != null) | |
{ | |
// Change the Name if we want. | |
if(changeName) | |
newObject.name = name != "" ? name : volumeName; | |
Volume voxelVolume = newObject.GetComponent<Volume>(); | |
voxelVolume.Material = PicaVoxel.EditorUtility.PicaVoxelDiffuseMaterial; | |
// Here is that it would be nice a method like | |
// voxelVolume.Replace(newFrame); or something like that. | |
// or something that deletes the necessary Chucks and replace the ones that are needed. | |
// The only reason i am not doing it my self is that i want it to be independent. I don't want to change your code. | |
// That my dirty method | |
DeleteOldFrame(newObject.GetComponent<Volume>()); | |
voxelVolume.GenerateBasic(FillMode.None); | |
voxelVolume.XSize = Convert.ToInt32(sizex); | |
voxelVolume.YSize = Convert.ToInt32(sizey); | |
voxelVolume.ZSize = Convert.ToInt32(sizez); | |
voxelVolume.Frames[0].XSize = Convert.ToInt32(sizex); | |
voxelVolume.Frames[0].YSize = Convert.ToInt32(sizey); | |
voxelVolume.Frames[0].ZSize = Convert.ToInt32(sizez); | |
voxelVolume.Frames[0].Voxels = new Voxel[sizex * sizey * sizez]; | |
voxelVolume.VoxelSize = voxelSize; | |
if(zAxisOrientation == 0) | |
{ | |
// Change the PivotPoint if we want. | |
if(changePivotPoint) | |
{ | |
voxelVolume.Pivot = new Vector3(sizex, 0, 0) * voxelSize; | |
voxelVolume.UpdatePivot(); | |
} | |
} | |
for(z = 0; z < sizez; z++) | |
for(y = 0; y < sizey; y++) | |
for(x = 0; x < sizex; x++) | |
{ | |
Color col = QubicleImporter.UIntToColor(matrix[x, y, z], colorFormat); | |
if(matrix[x, y, z] != 0) | |
voxelVolume.Frames[0].Voxels[(zAxisOrientation == 0 ? sizex - 1 - x : x) + sizex * (y + sizey * z)] = new Voxel() | |
{ | |
Active = true, | |
Color = col, | |
Value = 128 | |
}; | |
} | |
voxelVolume.UpdateAllChunks(); | |
voxelVolume.SaveForSerialize(); | |
// Change the Transform if we want. | |
if(changeTransform) | |
{ | |
newObject.transform.position = (new Vector3((zAxisOrientation == 0 ? -posX : posX), posY, posZ) * voxelSize); | |
} | |
} | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// Delete old Frames from the Volume | |
/// </summary> | |
/// <param name="volume"></param> | |
private void DeleteOldFrame(Volume volume) | |
{ | |
for(int i = volume.Frames.Count - 1; i >= 0; i--) | |
{ | |
DestroyImmediate(volume.Frames[i].gameObject); | |
volume.Frames.RemoveAt(i); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment