Esempio n. 1
0
        /// <summary>
        /// Saves changes made to the currently loaded stage.
        /// </summary>
        /// <param name="autoCloseDialog">Defines whether or not the progress dialog should close on completion.</param>
        private void SaveStage(bool autoCloseDialog)
        {
            if (!isStageLoaded)
                return;

            ProgressDialog progress = new ProgressDialog("Saving stage: " + levelName, 5, true, autoCloseDialog);
            progress.Show(this);
            Application.DoEvents();

            IniLevelData level = ini.Levels[levelID];
            string syspath = Path.Combine(Environment.CurrentDirectory, ini.SystemPath);
            string modpath = ini.ModPath;
            SA1LevelAct levelact = new SA1LevelAct(level.LevelID);

            progress.SetTaskAndStep("Saving:", "Geometry...");

            if (LevelData.geo != null)
            {
                LevelData.geo.Tool = "SADXLVL2";
                LevelData.geo.SaveToFile(level.LevelGeometry, LandTableFormat.SA1);
            }

            progress.StepProgress();

            progress.Step = "Start positions...";
            Application.DoEvents();

            for (int i = 0; i < LevelData.StartPositions.Length; i++)
            {
                Dictionary<SA1LevelAct, SA1StartPosInfo> posini =
                    SA1StartPosList.Load(ini.Characters[LevelData.Characters[i]].StartPositions);

                if (posini.ContainsKey(levelact))
                    posini.Remove(levelact);

                if (LevelData.StartPositions[i].Position.X != 0 || LevelData.StartPositions[i].Position.Y != 0 ||
                    LevelData.StartPositions[i].Position.Z != 0 || LevelData.StartPositions[i].Rotation.Y != 0)
                {
                    posini.Add(levelact,
                        new SA1StartPosInfo()
                        {
                            Position = LevelData.StartPositions[i].Position,
                            YRotation = LevelData.StartPositions[i].Rotation.Y
                        });
                }
                posini.Save(ini.Characters[LevelData.Characters[i]].StartPositions);
            }

            progress.StepProgress();

            progress.Step = "Death zones...";
            Application.DoEvents();

            if (LevelData.DeathZones != null)
            {
                DeathZoneFlags[] dzini = new DeathZoneFlags[LevelData.DeathZones.Count];
                string path = Path.GetDirectoryName(level.DeathZones);
                for (int i = 0; i < LevelData.DeathZones.Count; i++)
                    dzini[i] = LevelData.DeathZones[i].Save(path, i);
                dzini.Save(level.DeathZones);
            }

            progress.StepProgress();

            #region Saving SET Items

            progress.Step = "SET items...";
            Application.DoEvents();

            if (LevelData.SETItems != null)
            {
                for (int i = 0; i < LevelData.SETItems.Length; i++)
                {
                    string setstr = Path.Combine(syspath, "SET" + LevelData.SETName + LevelData.SETChars[i] + ".bin");
                    if (modpath != null)
                        setstr = Path.Combine(modpath, setstr);

                    // TODO: Consider simply blanking the SET file instead of deleting it.
                    // Completely deleting it might be undesirable since Sonic's layout will be loaded
                    // in place of the missing file. And where mods are concerned, you could have conflicts
                    // with other mods if the file is deleted.
                    if (File.Exists(setstr))
                        File.Delete(setstr);
                    if (LevelData.SETItems[i].Count == 0)
                        continue;

                    List<byte> file = new List<byte>(LevelData.SETItems[i].Count*0x20 + 0x20);
                    file.AddRange(BitConverter.GetBytes(LevelData.SETItems[i].Count));
                    file.Align(0x20);

                    foreach (SETItem item in LevelData.SETItems[i])
                        file.AddRange(item.GetBytes());

                    File.WriteAllBytes(setstr, file.ToArray());
                }
            }

            progress.StepProgress();

            #endregion

            #region Saving CAM Items

            progress.Step = "CAM items...";
            Application.DoEvents();

            if (LevelData.CAMItems != null)
            {
                for (int i = 0; i < LevelData.CAMItems.Length; i++)
                {
                    string camString = Path.Combine(syspath, "CAM" + LevelData.SETName + LevelData.SETChars[i] + ".bin");
                    if (modpath != null)
                        camString = Path.Combine(modpath, camString);

                    // TODO: Handle this differently. File stream? If the user is using a symbolic link for example, we defeat the purpose by deleting it.
                    if (File.Exists(camString))
                        File.Delete(camString);

                    if (LevelData.CAMItems[i].Count == 0)
                        continue;

                    List<byte> file = new List<byte>(LevelData.CAMItems[i].Count*0x40 + 0x40); // setting up file size and header
                    file.AddRange(BitConverter.GetBytes(LevelData.CAMItems[i].Count));
                    file.Align(0x40);

                    foreach (CAMItem item in LevelData.CAMItems[i]) // outputting individual components
                        file.AddRange(item.GetBytes());

                    File.WriteAllBytes(camString, file.ToArray());
                }
            }

            progress.StepProgress();
            progress.SetTaskAndStep("Save complete!");
            Application.DoEvents();

            #endregion
        }
Esempio n. 2
0
        private void exportOBJToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog a = new SaveFileDialog
            {
                DefaultExt = "obj",
                Filter = "OBJ Files|*.obj"
            };
            if (a.ShowDialog() == DialogResult.OK)
            {
                using (StreamWriter objstream = new StreamWriter(a.FileName, false))
                using (StreamWriter mtlstream = new StreamWriter(Path.ChangeExtension(a.FileName, "mtl"), false))
                {
                    #region Material Exporting
                    string materialPrefix = LevelData.leveltexs;

                    objstream.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(a.FileName) + ".mtl");

                    int stepCount = LevelData.TextureBitmaps[LevelData.leveltexs].Length + LevelData.geo.COL.Count;
                    if (LevelData.geo.Anim != null)
                        stepCount += LevelData.geo.Anim.Count;

                    ProgressDialog progress = new ProgressDialog("Exporting stage: " + levelName, stepCount, true, false);
                    progress.Show(this);
                    progress.SetTaskAndStep("Exporting...");

                    // This is admittedly not an accurate representation of the materials used in the model - HOWEVER, it makes the materials more managable in MAX
                    // So we're doing it this way. In the future we should come back and add an option to do it this way or the original way.
                    for (int i = 0; i < LevelData.TextureBitmaps[LevelData.leveltexs].Length; i++)
                    {
                        mtlstream.WriteLine("newmtl {0}_material_{1}", materialPrefix, i);
                        mtlstream.WriteLine("Ka 1 1 1");
                        mtlstream.WriteLine("Kd 1 1 1");
                        mtlstream.WriteLine("Ks 0 0 0");
                        mtlstream.WriteLine("illum 1");

                        if (!string.IsNullOrEmpty(LevelData.leveltexs))
                        {
                            mtlstream.WriteLine("Map_Kd " + LevelData.TextureBitmaps[LevelData.leveltexs][i].Name + ".png");

                            // save texture
                            string mypath = Path.GetDirectoryName(a.FileName);
                            BMPInfo item = LevelData.TextureBitmaps[LevelData.leveltexs][i];
                            item.Image.Save(Path.Combine(mypath, item.Name + ".png"));
                        }

                        progress.Step = String.Format("Texture {0}/{1}", i + 1, LevelData.TextureBitmaps[LevelData.leveltexs].Length);
                        progress.StepProgress();
                        Application.DoEvents();
                    }
                    #endregion

                    int totalVerts = 0;
                    int totalNorms = 0;
                    int totalUVs = 0;

                    bool errorFlag = false;

                    for (int i = 0; i < LevelData.geo.COL.Count; i++)
                    {
                        Direct3D.Extensions.WriteModelAsObj(objstream, LevelData.geo.COL[i].Model, materialPrefix, new MatrixStack(),
                            ref totalVerts, ref totalNorms, ref totalUVs, ref errorFlag);

                        progress.Step = String.Format("Mesh {0}/{1}", i + 1, LevelData.geo.COL.Count);
                        progress.StepProgress();
                        Application.DoEvents();
                    }
                    if (LevelData.geo.Anim != null)
                    {
                        for (int i = 0; i < LevelData.geo.Anim.Count; i++)
                        {
                            Direct3D.Extensions.WriteModelAsObj(objstream, LevelData.geo.Anim[i].Model, materialPrefix, new MatrixStack(),
                                ref totalVerts, ref totalNorms, ref totalUVs, ref errorFlag);

                            progress.Step = String.Format("Animation {0}/{1}", i + 1, LevelData.geo.Anim.Count);
                            progress.StepProgress();
                            Application.DoEvents();
                        }
                    }

                    if (errorFlag)
                    {
                        MessageBox.Show("Error(s) encountered during export. Inspect the output file for more details.", "Failure",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                    progress.SetTaskAndStep("Export complete!");
                }
            }
        }