using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Threading; using System.Globalization; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Diagnostics; using System.Drawing.Text; using OpenTK; using OpenTK.Graphics.OpenGL; using ManagedFbx; using static Unity_Studio.UnityStudio; namespace Unity_Studio { partial class UnityStudioForm : Form { private AssetPreloadData lastSelectedItem; private AssetPreloadData lastLoadedAsset; private string[] fileTypes = { "globalgamemanagers", "maindata.", "level*.", "*.assets", "*.sharedAssets", "CustomAssetBundle-*", "CAB-*", "BuildPlayer-*" }; private FMOD.System system; private FMOD.Sound sound; private FMOD.Channel channel; private FMOD.SoundGroup masterSoundGroup; private FMOD.MODE loopMode = FMOD.MODE.LOOP_OFF; private uint FMODlenms; private float FMODVolume = 0.8f; private float FMODfrequency; private Bitmap imageTexture; #region OpenTK variables int pgmID; int vsID; int fsID; int attributeVertexPosition; int attributeNormalDirection; int attributeVertexColor; int uniformViewMatrix; int vao; int vboPositions; int vboNormals; int vboColors; int vboViewMatrix; int eboElements; OpenTK.Vector3[] vertexData; OpenTK.Vector3[] normalData; OpenTK.Vector4[] colorData; Matrix4[] viewMatrixData; int[] indiceData; bool wireFrameView; #endregion //asset list sorting helpers private int firstSortColumn = -1; private int secondSortColumn; private bool reverseSort; private bool enableFiltering; //tree search private int nextGObject; private List treeSrcResults = new List(); private PrivateFontCollection pfc = new PrivateFontCollection(); [DllImport("gdi32.dll")] private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts); private void loadFile_Click(object sender, System.EventArgs e) { if (openFileDialog1.ShowDialog() == DialogResult.OK) { resetForm(); mainPath = Path.GetDirectoryName(openFileDialog1.FileNames[0]); ThreadPool.QueueUserWorkItem(state => { if (openFileDialog1.FilterIndex == 1 || openFileDialog1.FilterIndex == 3) { MergeSplitAssets(mainPath); //unityFiles.AddRange(openFileDialog1.FileNames); foreach (var i in openFileDialog1.FileNames) { unityFiles.Add(i); unityFilesHash.Add(Path.GetFileName(i)); } SetProgressBarValue(0); SetProgressBarMaximum(unityFiles.Count); //use a for loop because list size can change for (int f = 0; f < unityFiles.Count; f++) { StatusStripUpdate("Loading " + Path.GetFileName(unityFiles[f])); LoadAssetsFile(unityFiles[f]); ProgressBarPerformStep(); } } else { SetProgressBarValue(0); SetProgressBarMaximum(unityFiles.Count); foreach (var filename in openFileDialog1.FileNames) { LoadBundleFile(filename); ProgressBarPerformStep(); } } BuildAssetStrucutres(); unityFilesHash.Clear(); assetsfileListHash.Clear(); }); } } private void loadFolder_Click(object sender, System.EventArgs e) { /*FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog(); folderBrowserDialog1.Description = "Load all Unity assets from folder and subfolders"; folderBrowserDialog1.ShowNewFolderButton = false; //folderBrowserDialog1.SelectedPath = "E:\\Assets\\Unity"; folderBrowserDialog1.SelectedPath = "E:\\Assets\\Unity\\WebPlayer\\Porsche\\92AAF1\\defaultGeometry";*/ if (openFolderDialog1.ShowDialog() == DialogResult.OK) { //mainPath = folderBrowserDialog1.SelectedPath; mainPath = openFolderDialog1.FileName; if (Path.GetFileName(mainPath) == "Select folder") { mainPath = Path.GetDirectoryName(mainPath); } if (Directory.Exists(mainPath)) { resetForm(); //TODO find a way to read data directly instead of merging files MergeSplitAssets(mainPath); for (int t = 0; t < fileTypes.Length; t++) { string[] fileNames = Directory.GetFiles(mainPath, fileTypes[t], SearchOption.AllDirectories); #region sort specific types alphanumerically if (fileNames.Length > 0 && (t == 1 || t == 2)) { var sortedList = fileNames.ToList(); sortedList.Sort((s1, s2) => { string pattern = "([A-Za-z\\s]*)([0-9]*)"; string h1 = Regex.Match(Path.GetFileNameWithoutExtension(s1), pattern).Groups[1].Value; string h2 = Regex.Match(Path.GetFileNameWithoutExtension(s2), pattern).Groups[1].Value; if (h1 != h2) return h1.CompareTo(h2); string t1 = Regex.Match(Path.GetFileNameWithoutExtension(s1), pattern).Groups[2].Value; string t2 = Regex.Match(Path.GetFileNameWithoutExtension(s2), pattern).Groups[2].Value; if (t1 != "" && t2 != "") return int.Parse(t1).CompareTo(int.Parse(t2)); return 0; }); foreach (var i in sortedList) { unityFiles.Add(i); unityFilesHash.Add(Path.GetFileName(i)); } } #endregion else { foreach (var i in fileNames) { unityFiles.Add(i); unityFilesHash.Add(Path.GetFileName(i)); } } } unityFiles = unityFiles.Distinct().ToList(); progressBar1.Value = 0; progressBar1.Maximum = unityFiles.Count; ThreadPool.QueueUserWorkItem(delegate { //use a for loop because list size can change for (int f = 0; f < unityFiles.Count; f++) { var fileName = unityFiles[f]; StatusStripUpdate("Loading " + Path.GetFileName(fileName)); LoadAssetsFile(fileName); ProgressBarPerformStep(); } unityFilesHash.Clear(); assetsfileListHash.Clear(); BuildAssetStrucutres(); }); } else { StatusStripUpdate("Selected path deos not exist."); } } } private void extractBundleToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog openBundleDialog = new OpenFileDialog(); openBundleDialog.Filter = "Unity bundle files|*.unity3d; *.unity3d.lz4; *.assetbundle; *.bundle; *.bytes|All files (use at your own risk!)|*.*"; openBundleDialog.FilterIndex = 1; openBundleDialog.RestoreDirectory = true; openBundleDialog.Multiselect = true; if (openBundleDialog.ShowDialog() == DialogResult.OK) { progressBar1.Value = 0; progressBar1.Maximum = openBundleDialog.FileNames.Length; int extractedCount = 0; ThreadPool.QueueUserWorkItem(delegate { foreach (var fileName in openBundleDialog.FileNames) { extractedCount += extractBundleFile(fileName); ProgressBarPerformStep(); } StatusStripUpdate("Finished extracting " + extractedCount + " files."); }); } } private void extractFolderToolStripMenuItem_Click(object sender, EventArgs e) { int extractedCount = 0; List bundleFiles = new List(); /*FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog(); folderBrowserDialog1.Description = "Extract all Unity bundles from folder and subfolders"; folderBrowserDialog1.ShowNewFolderButton = false;*/ if (openFolderDialog1.ShowDialog() == DialogResult.OK) { string startPath = openFolderDialog1.FileName; if (Path.GetFileName(startPath) == "Select folder") { startPath = Path.GetDirectoryName(startPath); } string[] fileTypes = new string[6] { "*.unity3d", "*.unity3d.lz4", "*.assetbundle", "*.assetbundle-*", "*.bundle", "*.bytes" }; foreach (var fileType in fileTypes) { string[] fileNames = Directory.GetFiles(startPath, fileType, SearchOption.AllDirectories); bundleFiles.AddRange(fileNames); } progressBar1.Value = 0; progressBar1.Maximum = bundleFiles.Count; ThreadPool.QueueUserWorkItem(delegate { foreach (var fileName in bundleFiles) { extractedCount += extractBundleFile(fileName); ProgressBarPerformStep(); } StatusStripUpdate("Finished extracting " + extractedCount + " files."); }); } } private void BuildAssetStrucutres() { bool optionLoadAssetsMenuItem = !dontLoadAssetsMenuItem.Checked; bool optionDisplayAll = displayAll.Checked; bool optionBuildHierarchyMenuItem = !dontBuildHierarchyMenuItem.Checked; bool optionBuildClassStructuresMenuItem = buildClassStructuresMenuItem.Checked; BuildAssetStructures(optionLoadAssetsMenuItem, optionDisplayAll, optionBuildHierarchyMenuItem, optionBuildClassStructuresMenuItem); BeginInvoke(new Action(() => { if (productName != "") { this.Text = "Unity Studio - " + productName + " - " + assetsfileList[0].m_Version + " - " + assetsfileList[0].platformStr; } else if (assetsfileList.Count > 0) { this.Text = "Unity Studio - no productName - " + assetsfileList[0].m_Version + " - " + assetsfileList[0].platformStr; } if (!dontLoadAssetsMenuItem.Checked) { assetListView.VirtualListSize = visibleAssets.Count; resizeAssetListColumns(); } if (!dontBuildHierarchyMenuItem.Checked) { sceneTreeView.BeginUpdate(); sceneTreeView.Nodes.AddRange(fileNodes.ToArray()); fileNodes.Clear(); sceneTreeView.EndUpdate(); } if (buildClassStructuresMenuItem.Checked) { classesListView.BeginUpdate(); foreach (var version in AllClassStructures) { ListViewGroup versionGroup = new ListViewGroup(version.Key); classesListView.Groups.Add(versionGroup); foreach (var uclass in version.Value) { uclass.Value.Group = versionGroup; classesListView.Items.Add(uclass.Value); } } classesListView.EndUpdate(); } StatusStripUpdate("Finished loading " + assetsfileList.Count + " files with " + (assetListView.Items.Count + sceneTreeView.Nodes.Count) + " exportable assets."); treeSearch.Select(); saveFolderDialog1.InitialDirectory = mainPath; })); } private void UnityStudioForm_KeyDown(object sender, KeyEventArgs e) { if (e.Control && e.Alt && e.KeyCode == Keys.D) { debugMenuItem.Visible = !debugMenuItem.Visible; buildClassStructuresMenuItem.Checked = debugMenuItem.Visible; dontLoadAssetsMenuItem.Checked = debugMenuItem.Visible; dontBuildHierarchyMenuItem.Checked = debugMenuItem.Visible; if (tabControl1.TabPages.Contains(tabPage3)) { tabControl1.TabPages.Remove(tabPage3); } else { tabControl1.TabPages.Add(tabPage3); } } if (glControl1.Visible == true) { // --> Right if (e.KeyCode == Keys.D) { if (e.Shift && e.KeyCode == Keys.D) //Move { viewMatrixData[0] *= Matrix4.CreateTranslation(0.1f, 0, 0); } else //Rotate { viewMatrixData[0] *= Matrix4.CreateRotationY(0.1f); } GL.UniformMatrix4(uniformViewMatrix, false, ref viewMatrixData[0]); glControl1.Invalidate(); } // <-- Left if (e.KeyCode == Keys.A) { if (e.Shift && e.KeyCode == Keys.A) //Move { viewMatrixData[0] *= Matrix4.CreateTranslation(-0.1f, 0, 0); } else //Rotate { viewMatrixData[0] *= Matrix4.CreateRotationY(-0.1f); } GL.UniformMatrix4(uniformViewMatrix, false, ref viewMatrixData[0]); glControl1.Invalidate(); } // Up if (e.KeyCode == Keys.W) { if (e.Control && e.KeyCode == Keys.W) //Toggle WireFrame { wireFrameView = !wireFrameView; glControl1.Invalidate(); } else if (e.Shift && e.KeyCode == Keys.W) //Move { viewMatrixData[0] *= Matrix4.CreateTranslation(0, 0.1f, 0); } else //Rotate { viewMatrixData[0] *= Matrix4.CreateRotationX(0.1f); } GL.UniformMatrix4(uniformViewMatrix, false, ref viewMatrixData[0]); glControl1.Invalidate(); } // Down if (e.KeyCode == Keys.S) { if (e.Shift && e.KeyCode == Keys.S) //Move { viewMatrixData[0] *= Matrix4.CreateTranslation(0, -0.1f, 0); } else //Rotate { viewMatrixData[0] *= Matrix4.CreateRotationX(-0.1f); } GL.UniformMatrix4(uniformViewMatrix, false, ref viewMatrixData[0]); glControl1.Invalidate(); } // Zoom Out if (e.KeyCode == Keys.Q) { viewMatrixData[0] *= Matrix4.CreateScale(0.9f); GL.UniformMatrix4(uniformViewMatrix, false, ref viewMatrixData[0]); glControl1.Invalidate(); } // Zoom In if (e.KeyCode == Keys.E) { viewMatrixData[0] *= Matrix4.CreateScale(1.1f); GL.UniformMatrix4(uniformViewMatrix, false, ref viewMatrixData[0]); glControl1.Invalidate(); } // Toggle Timer if (e.KeyCode == Keys.T) { timerOpenTK.Enabled = !timerOpenTK.Enabled; } } } private void dontLoadAssetsMenuItem_CheckedChanged(object sender, EventArgs e) { if (dontLoadAssetsMenuItem.Checked) { dontBuildHierarchyMenuItem.Checked = true; dontBuildHierarchyMenuItem.Enabled = false; } else { dontBuildHierarchyMenuItem.Enabled = true; } } private void exportClassStructuresMenuItem_Click(object sender, EventArgs e) { if (AllClassStructures.Count > 0) { if (saveFolderDialog1.ShowDialog() == DialogResult.OK) { progressBar1.Value = 0; progressBar1.Maximum = AllClassStructures.Count; var savePath = saveFolderDialog1.FileName; if (Path.GetFileName(savePath) == "Select folder or write folder name to create") { savePath = Path.GetDirectoryName(saveFolderDialog1.FileName); } foreach (var version in AllClassStructures) { if (version.Value.Count > 0) { string versionPath = savePath + "\\" + version.Key; Directory.CreateDirectory(versionPath); foreach (var uclass in version.Value) { string saveFile = versionPath + "\\" + uclass.Key + " " + uclass.Value.Text + ".txt"; using (StreamWriter TXTwriter = new StreamWriter(saveFile)) { TXTwriter.Write(uclass.Value.membersstr); } } } progressBar1.PerformStep(); } StatusStripUpdate("Finished exporting class structures"); progressBar1.Value = 0; } } } private void enablePreview_Check(object sender, EventArgs e) { if (lastLoadedAsset != null) { switch (lastLoadedAsset.Type2) { case 28: { if (enablePreview.Checked && imageTexture != null) { previewPanel.BackgroundImage = imageTexture; } else { previewPanel.BackgroundImage = Properties.Resources.preview; previewPanel.BackgroundImageLayout = ImageLayout.Center; } } break; case 48: case 49: case 114: textPreviewBox.Visible = !textPreviewBox.Visible; break; case 128: fontPreviewBox.Visible = !fontPreviewBox.Visible; break; case 83: { FMODpanel.Visible = !FMODpanel.Visible; if (sound != null && channel != null) { FMOD.RESULT result; bool playing = false; result = channel.isPlaying(out playing); if (result == FMOD.RESULT.OK && playing) { result = channel.stop(); FMODreset(); } } else if (FMODpanel.Visible) { PreviewAsset(lastLoadedAsset); } break; } } } else if (lastSelectedItem != null && enablePreview.Checked) { lastLoadedAsset = lastSelectedItem; PreviewAsset(lastLoadedAsset); } Properties.Settings.Default["enablePreview"] = enablePreview.Checked; Properties.Settings.Default.Save(); } private void displayAssetInfo_Check(object sender, EventArgs e) { if (displayInfo.Checked && assetInfoLabel.Text != null) { assetInfoLabel.Visible = true; } else { assetInfoLabel.Visible = false; } Properties.Settings.Default["displayInfo"] = displayInfo.Checked; Properties.Settings.Default.Save(); } private void MenuItem_CheckedChanged(object sender, EventArgs e) { Properties.Settings.Default[((ToolStripMenuItem)sender).Name] = ((ToolStripMenuItem)sender).Checked; Properties.Settings.Default.Save(); } private void assetGroupOptions_SelectedIndexChanged(object sender, EventArgs e) { Properties.Settings.Default["assetGroupOption"] = ((ToolStripComboBox)sender).SelectedIndex; Properties.Settings.Default.Save(); } private void showExpOpt_Click(object sender, EventArgs e) { ExportOptions exportOpt = new ExportOptions(); exportOpt.ShowDialog(); } private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { AboutBox aboutWindow = new AboutBox(); aboutWindow.ShowDialog(); } private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) { e.Item = visibleAssets[e.ItemIndex]; } private void tabPageSelected(object sender, TabControlEventArgs e) { switch (e.TabPageIndex) { case 0: treeSearch.Select(); break; case 1: resizeAssetListColumns(); //required because the ListView is not visible on app launch classPreviewPanel.Visible = false; previewPanel.Visible = true; listSearch.Select(); break; case 2: previewPanel.Visible = false; classPreviewPanel.Visible = true; break; } } private void treeSearch_MouseEnter(object sender, EventArgs e) { treeTip.Show("Search with * ? widcards. Enter to scroll through results, Ctrl+Enter to select all results.", treeSearch, 5000); } private void treeSearch_Enter(object sender, EventArgs e) { if (treeSearch.Text == " Search ") { treeSearch.Text = ""; treeSearch.ForeColor = System.Drawing.SystemColors.WindowText; } } private void treeSearch_Leave(object sender, EventArgs e) { if (treeSearch.Text == "") { treeSearch.Text = " Search "; treeSearch.ForeColor = System.Drawing.SystemColors.GrayText; } } private void recurseTreeCheck(TreeNodeCollection start) { foreach (GameObject GObject in start) { if (GObject.Text.Like(treeSearch.Text)) { GObject.Checked = !GObject.Checked; if (GObject.Checked) { GObject.EnsureVisible(); } } else { recurseTreeCheck(GObject.Nodes); } } } private void treeSearch_TextChanged(object sender, EventArgs e) { treeSrcResults.Clear(); nextGObject = 0; } private void treeSearch_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { if (treeSrcResults.Count == 0) { foreach (var aFile in assetsfileList) { foreach (var GObject in aFile.GameObjectList.Values) { if (GObject.Text.Like(treeSearch.Text)) { treeSrcResults.Add(GObject); } } } } if (e.Control) //toggle all matching nodes { sceneTreeView.BeginUpdate(); //loop TreeView recursively to avoid children already checked by parent recurseTreeCheck(sceneTreeView.Nodes); sceneTreeView.EndUpdate(); } else //make visible one by one { if (treeSrcResults.Count > 0) { if (nextGObject >= treeSrcResults.Count) { nextGObject = 0; } treeSrcResults[nextGObject].EnsureVisible(); sceneTreeView.SelectedNode = treeSrcResults[nextGObject]; nextGObject++; } } } } private void sceneTreeView_AfterCheck(object sender, TreeViewEventArgs e) { foreach (GameObject childNode in e.Node.Nodes) { childNode.Checked = e.Node.Checked; } } private void resizeAssetListColumns() { assetListView.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.HeaderSize); assetListView.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.ColumnContent); assetListView.AutoResizeColumn(2, ColumnHeaderAutoResizeStyle.HeaderSize); assetListView.AutoResizeColumn(2, ColumnHeaderAutoResizeStyle.ColumnContent); var vscrollwidth = SystemInformation.VerticalScrollBarWidth; var hasvscroll = (visibleAssets.Count / (float)assetListView.Height) > 0.0567f; columnHeaderName.Width = assetListView.Width - columnHeaderType.Width - columnHeaderSize.Width - (hasvscroll ? (5 + vscrollwidth) : 5); } private void tabPage2_Resize(object sender, EventArgs e) { resizeAssetListColumns(); } private void listSearch_Enter(object sender, EventArgs e) { if (listSearch.Text == " Filter ") { listSearch.Text = ""; listSearch.ForeColor = System.Drawing.SystemColors.WindowText; enableFiltering = true; } } private void listSearch_Leave(object sender, EventArgs e) { if (listSearch.Text == "") { enableFiltering = false; listSearch.Text = " Filter "; listSearch.ForeColor = System.Drawing.SystemColors.GrayText; } } private void ListSearchTextChanged(object sender, EventArgs e) { if (enableFiltering) { assetListView.BeginUpdate(); assetListView.SelectedIndices.Clear(); //visibleListAssets = exportableAssets.FindAll(ListAsset => ListAsset.Text.StartsWith(ListSearch.Text, System.StringComparison.CurrentCultureIgnoreCase)); visibleAssets = exportableAssets.FindAll(ListAsset => ListAsset.Text.IndexOf(listSearch.Text, System.StringComparison.CurrentCultureIgnoreCase) >= 0); assetListView.VirtualListSize = visibleAssets.Count; assetListView.EndUpdate(); } } private void assetListView_ColumnClick(object sender, ColumnClickEventArgs e) { if (firstSortColumn != e.Column) { //sorting column has been changed reverseSort = false; secondSortColumn = firstSortColumn; } else { reverseSort = !reverseSort; } firstSortColumn = e.Column; assetListView.BeginUpdate(); assetListView.SelectedIndices.Clear(); switch (e.Column) { case 0: visibleAssets.Sort(delegate (AssetPreloadData a, AssetPreloadData b) { int xdiff = reverseSort ? b.Text.CompareTo(a.Text) : a.Text.CompareTo(b.Text); if (xdiff != 0) return xdiff; else return secondSortColumn == 1 ? a.TypeString.CompareTo(b.TypeString) : a.Size.CompareTo(b.Size); }); break; case 1: visibleAssets.Sort(delegate (AssetPreloadData a, AssetPreloadData b) { int xdiff = reverseSort ? b.TypeString.CompareTo(a.TypeString) : a.TypeString.CompareTo(b.TypeString); if (xdiff != 0) return xdiff; else return secondSortColumn == 2 ? a.Size.CompareTo(b.Size) : a.Text.CompareTo(b.Text); }); break; case 2: visibleAssets.Sort(delegate (AssetPreloadData a, AssetPreloadData b) { int xdiff = reverseSort ? b.Size.CompareTo(a.Size) : a.Size.CompareTo(b.Size); if (xdiff != 0) return xdiff; else return secondSortColumn == 1 ? a.TypeString.CompareTo(b.TypeString) : a.Text.CompareTo(b.Text); }); break; } assetListView.EndUpdate(); resizeAssetListColumns(); } private void selectAsset(object sender, ListViewItemSelectionChangedEventArgs e) { previewPanel.BackgroundImage = Properties.Resources.preview; previewPanel.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; assetInfoLabel.Visible = false; assetInfoLabel.Text = null; textPreviewBox.Visible = false; fontPreviewBox.Visible = false; pfc.Dispose(); FMODpanel.Visible = false; glControl1.Visible = false; lastLoadedAsset = null; StatusStripUpdate(""); FMODreset(); lastSelectedItem = (AssetPreloadData)e.Item; if (e.IsSelected) { assetInfoLabel.Text = lastSelectedItem.InfoText; if (displayInfo.Checked && assetInfoLabel.Text != null) { assetInfoLabel.Visible = true; } //only display the label if asset has info text if (enablePreview.Checked) { lastLoadedAsset = lastSelectedItem; PreviewAsset(lastLoadedAsset); } } } private void classesListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { if (e.IsSelected) { classTextBox.Text = ((ClassStruct)classesListView.SelectedItems[0]).membersstr; } } private void PreviewAsset(AssetPreloadData asset) { switch (asset.Type2) { #region Texture2D case 28: //Texture2D { if (imageTexture != null) imageTexture.Dispose(); var m_Texture2D = new Texture2D(asset, true); imageTexture = m_Texture2D.ConvertToBitmap(true); if (imageTexture != null) { previewPanel.BackgroundImage = imageTexture; if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height) previewPanel.BackgroundImageLayout = ImageLayout.Zoom; else previewPanel.BackgroundImageLayout = ImageLayout.Center; } else { StatusStripUpdate("Unsupported image for preview. Can only export the texture file."); } break; } #endregion #region AudioClip case 83: //AudioClip { AudioClip m_AudioClip = new AudioClip(asset, true); FMOD.RESULT result; FMOD.CREATESOUNDEXINFO exinfo = new FMOD.CREATESOUNDEXINFO(); exinfo.cbsize = Marshal.SizeOf(exinfo); exinfo.length = (uint)m_AudioClip.m_Size; result = system.createSound(m_AudioClip.m_AudioData, (FMOD.MODE.OPENMEMORY | loopMode), ref exinfo, out sound); if (ERRCHECK(result)) { break; } FMOD.Sound subsound; result = sound.getSubSound(0, out subsound); if (result == FMOD.RESULT.OK) { sound = subsound; } result = sound.getLength(out FMODlenms, FMOD.TIMEUNIT.MS); if (ERRCHECK(result)) { break; } result = system.playSound(sound, null, true, out channel); if (ERRCHECK(result)) { break; } FMODpanel.Visible = true; result = channel.getFrequency(out FMODfrequency); if (ERRCHECK(result)) { break; } FMODinfoLabel.Text = FMODfrequency + " Hz"; FMODtimerLabel.Text = "0:0.0 / " + (FMODlenms / 1000 / 60) + ":" + (FMODlenms / 1000 % 60) + "." + (FMODlenms / 10 % 100); break; } #endregion #region Shader case 48: { Shader m_TextAsset = new Shader(asset, true); string m_Script_Text = Encoding.UTF8.GetString(m_TextAsset.m_Script); m_Script_Text = Regex.Replace(m_Script_Text, "(? 0) { //textPreviewBox.Font = new Font(pfc.Families[0], 16, FontStyle.Regular); //textPreviewBox.Text = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWYZ\r\n1234567890.:,;'\"(!?)+-*/=\r\nThe quick brown fox jumps over the lazy dog. 1234567890"; fontPreviewBox.SelectionStart = 0; fontPreviewBox.SelectionLength = 80; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 16, FontStyle.Regular); fontPreviewBox.SelectionStart = 81; fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 12, FontStyle.Regular); fontPreviewBox.SelectionStart = 138; fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 18, FontStyle.Regular); fontPreviewBox.SelectionStart = 195; fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 24, FontStyle.Regular); fontPreviewBox.SelectionStart = 252; fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 36, FontStyle.Regular); fontPreviewBox.SelectionStart = 309; fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 48, FontStyle.Regular); fontPreviewBox.SelectionStart = 366; fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 60, FontStyle.Regular); fontPreviewBox.SelectionStart = 423; fontPreviewBox.SelectionLength = 55; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 72, FontStyle.Regular); fontPreviewBox.Visible = true; } break; } } StatusStripUpdate("Unsupported font for preview. Try to export."); break; } #endregion #region Mesh case 43: //Mesh { glControl1.Visible = true; viewMatrixData = new Matrix4[] { Matrix4.Identity * Matrix4.CreateTranslation( 0.0f, -1.0f, 0.0f ) * Matrix4.CreateRotationY(-90.0f)}; var m_Mesh = new Mesh(asset, true); if (m_Mesh.m_VertexCount > 0) { #region Vertices int count = 3; if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4) { count = 4; } vertexData = new OpenTK.Vector3[m_Mesh.m_VertexCount]; for (int v = 0; v < m_Mesh.m_VertexCount; v++) { vertexData[v] = new OpenTK.Vector3( m_Mesh.m_Vertices[v * count], m_Mesh.m_Vertices[v * count + 1], m_Mesh.m_Vertices[v * count + 2]); } #endregion #region Indicies indiceData = new int[m_Mesh.m_Indices.Count]; for (int i = 0; i < m_Mesh.m_Indices.Count; i = i + 3) { indiceData[i] = (int)m_Mesh.m_Indices[i]; indiceData[i + 1] = (int)m_Mesh.m_Indices[i + 1]; indiceData[i + 2] = (int)m_Mesh.m_Indices[i + 2]; } #endregion #region Normals if (m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0) { if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3) { count = 3; } else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4) { count = 4; } normalData = new OpenTK.Vector3[m_Mesh.m_VertexCount]; for (int n = 0; n < m_Mesh.m_VertexCount; n++) { normalData[n] = new OpenTK.Vector3( m_Mesh.m_Normals[n * count], m_Mesh.m_Normals[n * count + 1], m_Mesh.m_Normals[n * count + 2]); } } #endregion #region Colors if (m_Mesh.m_Colors == null) { colorData = new OpenTK.Vector4[m_Mesh.m_VertexCount]; for (int c = 0; c < m_Mesh.m_VertexCount; c++) { colorData[c] = new OpenTK.Vector4( 0.5f, 0.5f, 0.5f, 1.0f); } } else if (m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 3) { colorData = new OpenTK.Vector4[m_Mesh.m_VertexCount]; for (int c = 0; c < m_Mesh.m_VertexCount; c++) { colorData[c] = new OpenTK.Vector4( m_Mesh.m_Colors[c * 4], m_Mesh.m_Colors[c * 4 + 1], m_Mesh.m_Colors[c * 4 + 2], 1.0f); } } else { colorData = new OpenTK.Vector4[m_Mesh.m_VertexCount]; for (int c = 0; c < m_Mesh.m_VertexCount; c++) { colorData[c] = new OpenTK.Vector4( m_Mesh.m_Colors[c * 4], m_Mesh.m_Colors[c * 4 + 1], m_Mesh.m_Colors[c * 4 + 2], m_Mesh.m_Colors[c * 4 + 3]); } } #endregion } createVAO(); StatusStripUpdate("Using OpenGL Version: " + GL.GetString(StringName.Version) + " | 'T'=Start/Stop Rotation | 'WASD'=Manual Rotate | " + "'Shift WASD'=Move | 'Q/E'=Zoom | 'Ctl W' =Wireframe"); } break; #endregion default: { StatusStripUpdate("Only supported export the raw file."); break; } } } private void FMODinit() { FMODreset(); FMOD.RESULT result; uint version = 0; result = FMOD.Factory.System_Create(out system); if (ERRCHECK(result)) { return; } result = system.getVersion(out version); ERRCHECK(result); if (version < FMOD.VERSION.number) { MessageBox.Show("Error! You are using an old version of FMOD " + version.ToString("X") + ". This program requires " + FMOD.VERSION.number.ToString("X") + "."); Application.Exit(); } result = system.init(1, FMOD.INITFLAGS.NORMAL, (IntPtr)null); if (ERRCHECK(result)) { return; } //result = system.getMasterChannelGroup(out channelGroup); //if (ERRCHECK(result)) { return; } result = system.getMasterSoundGroup(out masterSoundGroup); if (ERRCHECK(result)) { return; } result = masterSoundGroup.setVolume(FMODVolume); if (ERRCHECK(result)) { return; } } private void FMODreset() { timer.Stop(); FMODprogressBar.Value = 0; FMODtimerLabel.Text = "0:00.0 / 0:00.0"; FMODstatusLabel.Text = "Stopped"; FMODinfoLabel.Text = ""; if (sound != null) { var result = sound.release(); if (result != FMOD.RESULT.OK) { StatusStripUpdate("FMOD error! " + result + " - " + FMOD.Error.String(result)); } sound = null; } } private void FMODplayButton_Click(object sender, EventArgs e) { FMOD.RESULT result; if (sound != null && channel != null) { timer.Start(); bool playing = false; result = channel.isPlaying(out playing); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { if (ERRCHECK(result)) { return; } } if (playing) { result = channel.stop(); if (ERRCHECK(result)) { return; } result = system.playSound(sound, null, false, out channel); if (ERRCHECK(result)) { return; } FMODpauseButton.Text = "Pause"; } else { result = system.playSound(sound, null, false, out channel); if (ERRCHECK(result)) { return; } FMODstatusLabel.Text = "Playing"; //FMODinfoLabel.Text = FMODfrequency.ToString(); if (FMODprogressBar.Value > 0) { uint newms = FMODlenms / 1000 * (uint)FMODprogressBar.Value; result = channel.setPosition(newms, FMOD.TIMEUNIT.MS); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { if (ERRCHECK(result)) { return; } } } } } } private void FMODpauseButton_Click(object sender, EventArgs e) { FMOD.RESULT result; if (sound != null && channel != null) { bool playing = false; bool paused = false; result = channel.isPlaying(out playing); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { if (ERRCHECK(result)) { return; } } if (playing) { result = channel.getPaused(out paused); if (ERRCHECK(result)) { return; } result = channel.setPaused(!paused); if (ERRCHECK(result)) { return; } //FMODstatusLabel.Text = (!paused ? "Paused" : playing ? "Playing" : "Stopped"); //FMODpauseButton.Text = (!paused ? "Resume" : playing ? "Pause" : "Pause"); if (paused) { FMODstatusLabel.Text = (playing ? "Playing" : "Stopped"); FMODpauseButton.Text = "Pause"; timer.Start(); } else { FMODstatusLabel.Text = "Paused"; FMODpauseButton.Text = "Resume"; timer.Stop(); } } } } private void FMODstopButton_Click(object sender, EventArgs e) { FMOD.RESULT result; if (channel != null) { bool playing = false; result = channel.isPlaying(out playing); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { if (ERRCHECK(result)) { return; } } if (playing) { result = channel.stop(); if (ERRCHECK(result)) { return; } //channel = null; //don't FMODreset, it will nullify the sound timer.Stop(); FMODprogressBar.Value = 0; FMODtimerLabel.Text = "0:00.0 / 0:00.0"; FMODstatusLabel.Text = "Stopped"; FMODpauseButton.Text = "Pause"; } } } private void FMODloopButton_CheckedChanged(object sender, EventArgs e) { FMOD.RESULT result; if (FMODloopButton.Checked) { loopMode = FMOD.MODE.LOOP_NORMAL; } else { loopMode = FMOD.MODE.LOOP_OFF; } if (sound != null) { result = sound.setMode(loopMode); if (ERRCHECK(result)) { return; } } if (channel != null) { bool playing = false; result = channel.isPlaying(out playing); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { if (ERRCHECK(result)) { return; } } bool paused = false; result = channel.getPaused(out paused); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { if (ERRCHECK(result)) { return; } } if (playing || paused) { result = channel.setMode(loopMode); if (ERRCHECK(result)) { return; } } } } private void FMODvolumeBar_ValueChanged(object sender, EventArgs e) { FMOD.RESULT result; FMODVolume = Convert.ToSingle(FMODvolumeBar.Value) / 10; result = masterSoundGroup.setVolume(FMODVolume); if (ERRCHECK(result)) { return; } } private void FMODprogressBar_Scroll(object sender, EventArgs e) { if (channel != null) { uint newms = FMODlenms / 1000 * (uint)FMODprogressBar.Value; FMODtimerLabel.Text = (newms / 1000 / 60) + ":" + (newms / 1000 % 60) + "." + (newms / 10 % 100) + "/" + (FMODlenms / 1000 / 60) + ":" + (FMODlenms / 1000 % 60) + "." + (FMODlenms / 10 % 100); } } private void FMODprogressBar_MouseDown(object sender, MouseEventArgs e) { timer.Stop(); } private void FMODprogressBar_MouseUp(object sender, MouseEventArgs e) { if (channel != null) { FMOD.RESULT result; uint newms = FMODlenms / 1000 * (uint)FMODprogressBar.Value; result = channel.setPosition(newms, FMOD.TIMEUNIT.MS); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { if (ERRCHECK(result)) { return; } } bool playing = false; result = channel.isPlaying(out playing); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { if (ERRCHECK(result)) { return; } } if (playing) { timer.Start(); } } } private void timer_Tick(object sender, EventArgs e) { FMOD.RESULT result; uint ms = 0; bool playing = false; bool paused = false; if (channel != null) { result = channel.getPosition(out ms, FMOD.TIMEUNIT.MS); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { ERRCHECK(result); } result = channel.isPlaying(out playing); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { ERRCHECK(result); } result = channel.getPaused(out paused); if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE)) { ERRCHECK(result); } } //statusBar.Text = "Time " + (ms / 1000 / 60) + ":" + (ms / 1000 % 60) + ":" + (ms / 10 % 100) + "/" + (lenms / 1000 / 60) + ":" + (lenms / 1000 % 60) + ":" + (lenms / 10 % 100) + " : " + (paused ? "Paused " : playing ? "Playing" : "Stopped"); FMODtimerLabel.Text = (ms / 1000 / 60) + ":" + (ms / 1000 % 60) + "." + (ms / 10 % 100) + " / " + (FMODlenms / 1000 / 60) + ":" + (FMODlenms / 1000 % 60) + "." + (FMODlenms / 10 % 100); FMODprogressBar.Value = (int)(ms * 1000 / FMODlenms); FMODstatusLabel.Text = (paused ? "Paused " : playing ? "Playing" : "Stopped"); if (system != null && channel != null) { system.update(); } } private bool ERRCHECK(FMOD.RESULT result) { if (result != FMOD.RESULT.OK) { //FMODinit(); FMODreset(); StatusStripUpdate("FMOD error! " + result + " - " + FMOD.Error.String(result)); //Environment.Exit(-1); return true; } else { return false; } } private void all3DObjectssplitToolStripMenuItem_Click(object sender, EventArgs e) { if (sceneTreeView.Nodes.Count > 0) { if (saveFolderDialog1.ShowDialog() == DialogResult.OK) { var savePath = saveFolderDialog1.FileName; if (Path.GetFileName(savePath) == "Select folder or write folder name to create") { savePath = Path.GetDirectoryName(saveFolderDialog1.FileName); } savePath = savePath + "\\"; switch ((bool)Properties.Settings.Default["showExpOpt"]) { case true: ExportOptions exportOpt = new ExportOptions(); if (exportOpt.ShowDialog() == DialogResult.OK) { goto case false; } break; case false: { progressBar1.Value = 0; progressBar1.Maximum = sceneTreeView.Nodes.Count; //防止主界面假死 ThreadPool.QueueUserWorkItem(delegate { sceneTreeView.Invoke(new Action(() => { //挂起控件防止更新 sceneTreeView.BeginUpdate(); //先取消所有Node的选中 foreach (TreeNode i in sceneTreeView.Nodes) { i.Checked = false; } })); //遍历根节点 foreach (TreeNode i in sceneTreeView.Nodes) { if (i.Nodes.Count > 0) { //遍历一级子节点 foreach (TreeNode j in i.Nodes) { //加上时间,因为可能有重名的object var filename = j.Text + DateTime.Now.ToString("_mm_ss_ffff"); //选中它和它的子节点 sceneTreeView.Invoke(new Action(() => j.Checked = true)); //导出FBX WriteFBX(savePath + filename + ".fbx", false); //取消选中 sceneTreeView.Invoke(new Action(() => j.Checked = false)); } } ProgressBarPerformStep(); } //取消挂起 sceneTreeView.Invoke(new Action(() => sceneTreeView.EndUpdate())); if (openAfterExport.Checked) { Process.Start(savePath); } }); break; } } } } else { StatusStripUpdate("No Objects available for export"); } } private void Export3DObjects_Click(object sender, EventArgs e) { if (sceneTreeView.Nodes.Count > 0) { bool exportSwitch = (((ToolStripItem)sender).Name == "exportAll3DMenuItem") ? true : false; var timestamp = DateTime.Now; saveFileDialog1.FileName = productName + timestamp.ToString("_yy_MM_dd__HH_mm_ss"); //extension will be added by the file save dialog if (saveFileDialog1.ShowDialog() == DialogResult.OK) { switch ((bool)Properties.Settings.Default["showExpOpt"]) { case true: ExportOptions exportOpt = new ExportOptions(); if (exportOpt.ShowDialog() == DialogResult.OK) { goto case false; } break; case false: switch (saveFileDialog1.FilterIndex) { case 1: WriteFBX(saveFileDialog1.FileName, exportSwitch); break; case 2: break; } if (openAfterExport.Checked && File.Exists(saveFileDialog1.FileName)) { try { Process.Start(saveFileDialog1.FileName); } catch { } } break; } } } else { StatusStripUpdate("No Objects available for export"); } } private void ExportAssets_Click(object sender, EventArgs e) { if (exportableAssets.Count > 0 && saveFolderDialog1.ShowDialog() == DialogResult.OK) { timer.Stop(); List toExportAssets = null; if (((ToolStripItem)sender).Name == "exportAllAssetsMenuItem") { toExportAssets = exportableAssets; } else if (((ToolStripItem)sender).Name == "exportFilteredAssetsMenuItem") { toExportAssets = visibleAssets; } else if (((ToolStripItem)sender).Name == "exportSelectedAssetsMenuItem") { toExportAssets = new List(assetListView.SelectedIndices.Count); foreach (var i in assetListView.SelectedIndices.OfType()) { toExportAssets.Add((AssetPreloadData)assetListView.Items[i]); } } int assetGroupSelectedIndex = assetGroupOptions.SelectedIndex; ThreadPool.QueueUserWorkItem(delegate { var savePath = saveFolderDialog1.FileName; if (Path.GetFileName(savePath) == "Select folder or write folder name to create") { savePath = Path.GetDirectoryName(saveFolderDialog1.FileName); } int toExport = toExportAssets.Count; int exportedCount = 0; SetProgressBarValue(0); SetProgressBarMaximum(toExport); //looping assetsFiles will optimize HDD access //but will also have a small performance impact when exporting only a couple of selected assets foreach (var asset in toExportAssets) { string exportpath = savePath + "\\"; if (assetGroupSelectedIndex == 1) { exportpath += Path.GetFileNameWithoutExtension(asset.sourceFile.filePath) + "_export\\"; } else if (assetGroupSelectedIndex == 0) { exportpath = savePath + "\\" + asset.TypeString + "\\"; } StatusStripUpdate("Exporting " + asset.TypeString + ": " + asset.Text); //AudioClip and Texture2D extensions are set when the list is built //so their overwrite tests can be done without loading them again switch (asset.Type2) { case 28: if (ExportTexture(asset, exportpath, true)) { exportedCount++; } break; case 83: if (ExportAudioClip(asset, exportpath + asset.Text, asset.extension)) { exportedCount++; } break; case 48: Shader m_Shader = new Shader(asset, true); if (!ExportFileExists(exportpath + asset.Text + asset.extension)) { ExportShader(m_Shader, exportpath + asset.Text + ".txt"); exportedCount++; } break; case 49: TextAsset m_TextAsset = new TextAsset(asset, true); if (!ExportFileExists(exportpath + asset.Text + asset.extension)) { ExportText(m_TextAsset, exportpath + asset.Text + asset.extension); exportedCount++; } break; case 114: MonoBehaviour m_MonoBehaviour = new MonoBehaviour(asset, true); if (!ExportFileExists(exportpath + asset.Text + asset.extension)) { ExportMonoBehaviour(m_MonoBehaviour, exportpath + asset.Text + asset.extension); exportedCount++; } break; case 128: unityFont m_Font = new unityFont(asset, true); if (!ExportFileExists(exportpath + asset.Text + asset.extension)) { ExportFont(m_Font, exportpath + asset.Text + asset.extension); exportedCount++; } break; case 43: //Mesh Mesh m_Mesh = new Mesh(asset, true); if (!ExportFileExists(exportpath + asset.Text + asset.extension)) { ExportMesh(m_Mesh, exportpath + asset.Text); exportedCount++; } break; default: if (!ExportFileExists(exportpath + asset.Text + asset.extension)) { ExportRawFile(asset, exportpath + asset.Text + asset.extension); exportedCount++; } break; } ProgressBarPerformStep(); } string statusText = ""; switch (exportedCount) { case 0: statusText = "Nothing exported."; break; default: statusText = "Finished exporting " + exportedCount + " assets."; break; } if (toExport > exportedCount) { statusText += " " + (toExport - exportedCount) + " assets skipped (not extractable or files already exist)"; } StatusStripUpdate(statusText); if (openAfterExport.Checked && exportedCount > 0) { Process.Start(savePath); } }); } else { StatusStripUpdate("No exportable assets loaded"); } } private void SetProgressBarValue(int value) { if (InvokeRequired) { BeginInvoke(new Action(() => { progressBar1.Value = value; })); } else { progressBar1.Value = value; } } private void SetProgressBarMaximum(int value) { if (InvokeRequired) { BeginInvoke(new Action(() => { progressBar1.Maximum = value; })); } else { progressBar1.Maximum = value; } } private void ProgressBarPerformStep() { if (InvokeRequired) { BeginInvoke(new Action(() => { progressBar1.PerformStep(); })); } else { progressBar1.PerformStep(); } } private void StatusStripUpdate(string statusText) { if (InvokeRequired) { BeginInvoke(new Action(() => { toolStripStatusLabel1.Text = statusText; })); } else { toolStripStatusLabel1.Text = statusText; } } private void ProgressBarMaximumAdd(int value) { if (InvokeRequired) { BeginInvoke(new Action(() => { progressBar1.Maximum += value; })); } else { progressBar1.Maximum += value; } } public UnityStudioForm() { Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); InitializeComponent(); displayAll.Checked = (bool)Properties.Settings.Default["displayAll"]; displayInfo.Checked = (bool)Properties.Settings.Default["displayInfo"]; enablePreview.Checked = (bool)Properties.Settings.Default["enablePreview"]; openAfterExport.Checked = (bool)Properties.Settings.Default["openAfterExport"]; assetGroupOptions.SelectedIndex = (int)Properties.Settings.Default["assetGroupOption"]; FMODinit(); //UI UnityStudio.SetProgressBarValue = SetProgressBarValue; UnityStudio.SetProgressBarMaximum = SetProgressBarMaximum; UnityStudio.ProgressBarPerformStep = ProgressBarPerformStep; UnityStudio.StatusStripUpdate = StatusStripUpdate; UnityStudio.ProgressBarMaximumAdd = ProgressBarMaximumAdd; } private void timerOpenTK_Tick(object sender, EventArgs e) { if (glControl1.Visible == true) { viewMatrixData[0] *= Matrix4.CreateRotationY(-0.1f); GL.UniformMatrix4(uniformViewMatrix, false, ref viewMatrixData[0]); glControl1.Invalidate(); } } private void initOpenTK() { GL.Viewport(0, 0, glControl1.ClientSize.Width, glControl1.ClientSize.Height); GL.ClearColor(Color.CadetBlue); pgmID = GL.CreateProgram(); loadShader("vs.glsl", ShaderType.VertexShader, pgmID, out vsID); loadShader("fs.glsl", ShaderType.FragmentShader, pgmID, out fsID); GL.LinkProgram(pgmID); GL.UseProgram(pgmID); attributeVertexPosition = GL.GetAttribLocation(pgmID, "vertexPosition"); attributeNormalDirection = GL.GetAttribLocation(pgmID, "normalDirection"); attributeVertexColor = GL.GetAttribLocation(pgmID, "vertexColor"); uniformViewMatrix = GL.GetUniformLocation(pgmID, "viewMatrix"); glControl1.Visible = false; } private void loadShader(string filename, ShaderType type, int program, out int address) { address = GL.CreateShader(type); using (StreamReader sr = new StreamReader(filename)) { GL.ShaderSource(address, sr.ReadToEnd()); } GL.CompileShader(address); GL.AttachShader(program, address); GL.DeleteShader(address); } private void createVBO(int vboAddress, OpenTK.Vector3[] data, int address) { GL.GenBuffers(1, out vboAddress); GL.BindBuffer(BufferTarget.ArrayBuffer, vboAddress); GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(data.Length * OpenTK.Vector3.SizeInBytes), data, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(address, 3, VertexAttribPointerType.Float, false, 0, 0); GL.EnableVertexAttribArray(address); } private void createVBO(int vboAddress, OpenTK.Vector4[] data, int address) { GL.GenBuffers(1, out vboAddress); GL.BindBuffer(BufferTarget.ArrayBuffer, vboAddress); GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(data.Length * OpenTK.Vector4.SizeInBytes), data, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(address, 4, VertexAttribPointerType.Float, false, 0, 0); GL.EnableVertexAttribArray(address); } private void createVBO(int vboAddress, Matrix4[] data, int address) { GL.GenBuffers(1, out vboAddress); GL.UniformMatrix4(address, false, ref data[0]); } private void createEBO(int address, int[] data) { GL.GenBuffers(1, out address); GL.BindBuffer(BufferTarget.ElementArrayBuffer, address); GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(data.Length * sizeof(int)), data, BufferUsageHint.StaticDraw); } private void createVAO() { timerOpenTK.Stop(); GL.DeleteVertexArray(vao); GL.GenVertexArrays(1, out vao); GL.BindVertexArray(vao); createVBO(vboPositions, vertexData, attributeVertexPosition); createVBO(vboNormals, normalData, attributeNormalDirection); createVBO(vboColors, colorData, attributeVertexColor); createVBO(vboViewMatrix, viewMatrixData, uniformViewMatrix); createEBO(eboElements, indiceData); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindVertexArray(0); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); initOpenTK(); } private void glControl1_Paint(object sender, PaintEventArgs e) { glControl1.MakeCurrent(); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.Enable(EnableCap.DepthTest); GL.DepthFunc(DepthFunction.Less); GL.BindVertexArray(vao); if (wireFrameView == true) { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); //Wireframe } else { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } GL.DrawElements(BeginMode.Triangles, indiceData.Length, DrawElementsType.UnsignedInt, 0); GL.BindVertexArray(0); GL.Flush(); glControl1.SwapBuffers(); } private void resetForm() { /*Properties.Settings.Default["uniqueNames"] = uniqueNamesMenuItem.Checked; Properties.Settings.Default["enablePreview"] = enablePreviewMenuItem.Checked; Properties.Settings.Default["displayInfo"] = displayAssetInfoMenuItem.Checked; Properties.Settings.Default.Save();*/ base.Text = "Unity Studio"; unityFiles.Clear(); assetsfileList.Clear(); exportableAssets.Clear(); visibleAssets.Clear(); assetsfileandstream.Clear(); sceneTreeView.Nodes.Clear(); assetListView.VirtualListSize = 0; assetListView.Items.Clear(); //assetListView.Groups.Clear(); classesListView.Items.Clear(); classesListView.Groups.Clear(); previewPanel.BackgroundImage = Properties.Resources.preview; previewPanel.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; assetInfoLabel.Visible = false; assetInfoLabel.Text = null; textPreviewBox.Visible = false; fontPreviewBox.Visible = false; glControl1.Visible = false; lastSelectedItem = null; lastLoadedAsset = null; firstSortColumn = -1; secondSortColumn = 0; reverseSort = false; enableFiltering = false; //FMODinit(); FMODreset(); } } }