using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.IO; using Switch_Toolbox.Library.Forms; using Switch_Toolbox.Library; using System.Windows.Forms; using FirstPlugin.Turbo.CourseMuuntStructs; using GL_EditorFramework.EditorDrawables; using OpenTK; using OpenTK.Graphics.OpenGL; using aampv1 = AampV1Library; using aampv2 = AampV2Library; using Switch_Toolbox.Library.Rendering; namespace FirstPlugin.Forms { public partial class TurboMunntEditor : UserControl, IViewportContainer { Viewport viewport; GLControl2D viewport2D; bool IsLoaded = false; public TurboMunntEditor() { InitializeComponent(); stTabControl1.myBackColor = FormThemes.BaseTheme.FormBackColor; treeView1.BackColor = FormThemes.BaseTheme.FormBackColor; treeView1.ForeColor = FormThemes.BaseTheme.FormForeColor; viewport = new Viewport(); viewport.Dock = DockStyle.Fill; viewport.scene.SelectionChanged += Scene_SelectionChanged; stPanel4.Controls.Add(viewport); viewport2D = new GLControl2D(); viewport2D.Dock = DockStyle.Fill; stPanel3.Controls.Add(viewport2D); } public Viewport GetViewport() => viewport; public void UpdateViewport() { if (viewport != null) viewport.UpdateViewport(); } public AnimationPanel GetAnimationPanel() => null; CourseMuuntScene scene; public void LoadCourseInfo(System.Collections.IEnumerable by, string FilePath) { string CourseFolder = System.IO.Path.GetDirectoryName(FilePath); scene = new CourseMuuntScene(by); //Add collsion (switch) if (File.Exists($"{CourseFolder}/course_kcl.szs")) scene.AddRenderableKcl($"{CourseFolder}/course_kcl.szs"); //Add collsion (wii u) if (File.Exists($"{CourseFolder}/course.kcl")) scene.AddRenderableKcl($"{CourseFolder}/course.kcl"); //Add probe lighting config (wii u) if (File.Exists($"{CourseFolder}/course.bglpbd")) scene.AddParameterArchive($"{CourseFolder}/course.bglpbd"); //Add probe lighting config (switch) if (File.Exists($"{CourseFolder}/course_bglpbd.szs")) scene.AddParameterArchive($"{CourseFolder}/course_bglpbd.szs"); //Add course model if (File.Exists($"{CourseFolder}/course_model.szs")) scene.AddRenderableBfres($"{CourseFolder}/course_model.szs"); foreach (AAMP aamp in scene.ParameterArchives) { if (aamp.aampFileV1 != null) LoadParameters(aamp.aampFileV1); else if (aamp.aampFileV2 != null) LoadParameters(aamp.aampFileV2); else throw new Exception("Failed to load parameter file " + aamp.FileName); } viewport.AddDrawable(new GL_EditorFramework.EditorDrawables.SingleObject(new OpenTK.Vector3(0))); viewport.LoadObjects(); treeView1.Nodes.Add("Scene"); if (scene.LapPaths.Count > 0) { AddPathDrawable("Lap Path", scene.LapPaths,Color.Blue); } if (scene.GravityPaths.Count > 0) { AddPathDrawable("Gravity Path", scene.GravityPaths, Color.Purple); } if (scene.EnemyPaths.Count > 0) { AddPathDrawable("Enemy Path", scene.EnemyPaths, Color.Red); } if (scene.GlidePaths.Count > 0) { AddPathDrawable("Glide Path", scene.GlidePaths, Color.Orange); } if (scene.ItemPaths.Count > 0) { AddPathDrawable("Item Path", scene.ItemPaths, Color.Yellow); } if (scene.PullPaths.Count > 0) { AddPathDrawable("Pull Path", scene.PullPaths, Color.GreenYellow); } if (scene.SteerAssistPaths.Count > 0) { AddPathDrawable("Steer Assist Path", scene.SteerAssistPaths, Color.Green); } if (scene.Paths.Count > 0) { AddPathDrawable("Path", scene.Paths, Color.Black); } if (scene.ObjPaths.Count > 0) { // AddPathDrawable("Object Path", scene.ObjPaths, Color.DarkSeaGreen); } if (scene.JugemPaths.Count > 0) { AddPathDrawable("Jugem Path", scene.JugemPaths, Color.DarkSeaGreen); } if (scene.IntroCameras.Count > 0) { AddPathDrawable("IntroCamera", scene.IntroCameras, Color.Pink); } foreach (var kcl in scene.KclObjects) { // viewport.AddDrawable(kcl.Renderer); // treeView1.Nodes.Add(kcl); // kcl.Checked = true; } foreach (var bfres in scene.BfresObjects) { // viewport.AddDrawable(bfres.BFRESRender); // treeView1.Nodes.Add(bfres); // bfres.Checked = true; } IsLoaded = true; } ProbeLighting probeLightingConfig; private void LoadParameters(aampv1.AampFile aamp) { if (aamp.EffectType == "Probe Data") { probeLightingConfig = new ProbeLighting(); viewport.AddDrawable(probeLightingConfig); treeView1.Nodes.Add(new ProbeLightingWrapper(probeLightingConfig)); uint index = 0; foreach (var val in aamp.RootNode.childParams) { var entry = new ProbeLighting.Entry(); entry.Index = index; probeLightingConfig.Entries.Add(entry); foreach (var param in val.paramObjects) { switch (param.HashString) { case "param_obj": foreach (var data in param.paramEntries) { if (data.HashString == "index") entry.Index = (uint)data.Value; if (data.HashString == "type") entry.Type = (uint)data.Value; } break; case "grid": entry.Grid = LoadGridData(param.paramEntries); break; case "sh_index_buffer": LoadIndexBuffer(param.paramEntries, entry); break; case "sh_data_buffer": LoadDataBuffer(param.paramEntries, entry); break; } } } foreach (var entry in probeLightingConfig.Entries) { Console.WriteLine(entry.Name); Console.WriteLine($"IndexType {entry.IndexType}"); Console.WriteLine($"DataType {entry.DataType}"); Console.WriteLine($"MaxIndexNum {entry.MaxIndexNum}"); Console.WriteLine($"UsedIndexNum {entry.UsedIndexNum}"); Console.WriteLine($"MaxShDataNum {entry.MaxShDataNum}"); Console.WriteLine($"UsedShDataNum {entry.UsedShDataNum}"); Console.WriteLine($"AABB_Max_Position {entry.Grid.AABB_Max_Position}"); Console.WriteLine($"AABB_Min_Position {entry.Grid.AABB_Min_Position}"); Console.WriteLine($"Voxel_Step_Position {entry.Grid.Voxel_Step_Position}"); Console.WriteLine($"DataBuffer {entry.DataBuffer.Length}"); Console.WriteLine($"IndexBuffer {entry.IndexBuffer.Length}"); } } } private void LoadDataBuffer(aampv1.ParamEntry[] paramEntries, ProbeLighting.Entry probeEntry) { foreach (var entry in paramEntries) { if (entry.HashString == "type") probeEntry.DataType = (uint)entry.Value; if (entry.HashString == "used_data_num") probeEntry.UsedShDataNum = (uint)entry.Value; if (entry.HashString == "max_sh_data_num") probeEntry.MaxShDataNum = (uint)entry.Value; if (entry.HashString == "data_buffer") { if (entry.ParamType == aampv1.ParamType.BufferFloat) probeEntry.DataBuffer = (float[])entry.Value; } } } private void LoadIndexBuffer(aampv1.ParamEntry[] paramEntries, ProbeLighting.Entry probeEntry) { foreach (var entry in paramEntries) { if (entry.HashString == "type") probeEntry.IndexType = (uint)entry.Value; if (entry.HashString == "used_index_num") probeEntry.UsedIndexNum = (uint)entry.Value; if (entry.HashString == "max_index_num") probeEntry.MaxIndexNum = (uint)entry.Value; if (entry.HashString == "index_buffer") { if (entry.ParamType == aampv1.ParamType.BufferUint) probeEntry.IndexBuffer = (uint[])entry.Value; } } } private ProbeLighting.Grid LoadGridData(aampv1.ParamEntry[] paramEntries) { ProbeLighting.Grid grid = new ProbeLighting.Grid(); foreach (var entry in paramEntries) { if (entry.HashString == "aabb_min_pos") grid.AABB_Max_Position = Utils.ToVec3((Syroot.Maths.Vector3F)entry.Value); if (entry.HashString == "aabb_max_pos") grid.AABB_Min_Position = Utils.ToVec3((Syroot.Maths.Vector3F)entry.Value); if (entry.HashString == "voxel_step_pos") grid.Voxel_Step_Position = Utils.ToVec3((Syroot.Maths.Vector3F)entry.Value); } return grid; } private void LoadParameters(aampv2.AampFile aamp) { } private void AddPathDrawable(string Name, IEnumerable Groups, Color color, bool CanConnect = true) { } private void AddPathDrawable(string Name, IEnumerable Groups, Color color, bool CanConnect = true) { //Create a connectable object to connect each point var renderablePathConnected = new RenderableConnectedPaths(color); if (Name == "Lap Path" || Name == "Gravity Path") renderablePathConnected.Use4PointConnection = true; if (CanConnect) { viewport.AddDrawable(renderablePathConnected); } //Load a node wrapper to the tree var pathNode = new PathCollectionNode(Name); treeView1.Nodes.Add(pathNode); int groupIndex = 0; foreach (var group in Groups) { if (CanConnect) renderablePathConnected.AddGroup(group); var groupNode = new PathGroupNode($"{Name} Group{groupIndex++}"); pathNode.Nodes.Add(groupNode); int pointIndex = 0; foreach (var path in group.PathPoints) { var pontNode = new PathPointNode($"{Name} Point{pointIndex++}"); pontNode.PathPoint = path; groupNode.Nodes.Add(pontNode); path.OnPathMoved = OnPathMoved; viewport.AddDrawable(path.RenderablePoint); } } } private void OnPathMoved() { stPropertyGrid1.Refresh(); } private void Scene_SelectionChanged(object sender, EventArgs e) { foreach (EditableObject o in viewport.scene.objects) { if (o.IsSelected() && o is RenderablePathPoint) { stPropertyGrid1.LoadProperty(((RenderablePathPoint)o).NodeObject, OnPropertyChanged); } } } private void OnPropertyChanged() { } private void viewIntroCameraToolStripMenuItem_Click(object sender, EventArgs e) { //Sort list by camera number/id scene.IntroCameras.Sort((x, y) => x.CameraNum.CompareTo(y.CameraNum)); foreach (var camera in scene.IntroCameras) { var pathMove = scene.Paths[camera.Camera_Path]; var pathLookAt = scene.Paths[camera.Camera_AtPath]; //The time elapsed for each point int PathTime = camera.CameraTime / pathMove.PathPoints.Count; //Go through each point for (int p = 0; p < pathMove.PathPoints.Count; p++) { //If lookat path is higher than the move path, break if (pathLookAt.PathPoints.Count >= p) break; //Set our points var pathMovePoint = pathMove.PathPoints[p]; var pathLookAtPoint = pathLookAt.PathPoints[p]; for (int frame = 0; frame < PathTime; frame++) { if (viewport.GL_ControlModern != null) { viewport.GL_ControlModern.CameraEye = pathLookAtPoint.Translate; viewport.GL_ControlModern.CameraTarget = pathMovePoint.Translate; viewport.UpdateViewport(); } } } } } private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) { List newSelection = new List(); TreeNode node = treeView1.SelectedNode; if (node == null) return; if (node.Text == "Scene") { stPropertyGrid1.LoadProperty(scene, OnPropertyChanged); } else if (node is PathCollectionNode) { foreach (var group in ((PathCollectionNode)node).Nodes) { foreach (var point in ((PathGroupNode)group).Nodes) { newSelection.Add(((PathPointNode)point).PathPoint.RenderablePoint); } } } else if (node is PathGroupNode) { foreach (var point in ((PathGroupNode)node).Nodes) { newSelection.Add(((PathPointNode)point).PathPoint.RenderablePoint); } } else if (node is PathPointNode) { newSelection.Add(((PathPointNode)node).PathPoint.RenderablePoint); } if (newSelection.Count > 0) { viewport.scene.SelectedObjects = newSelection; viewport.UpdateViewport(); } } bool IsParentChecked = false; private void treeView1_AfterCheck(object sender, TreeViewEventArgs e) { if (!IsLoaded || IsParentChecked) return; IsParentChecked = true; CheckChildNodes(e.Node, e.Node.Checked); IsParentChecked = false; //Update viewport on the last node checked viewport.UpdateViewport(); } private void CheckChildNodes(TreeNode node, bool IsChecked) { OnNodeChecked(node, IsChecked); foreach (TreeNode n in node.Nodes) { n.Checked = IsChecked; OnNodeChecked(n, IsChecked); if (n.Nodes.Count > 0) { CheckChildNodes(n, IsChecked); } } } private void OnNodeChecked(TreeNode node, bool IsChecked) { if (node is PathPointNode) ((PathPointNode)node).OnChecked(IsChecked); } } }