예제 #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
        }
예제 #2
0
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            #if !DEBUG
            try
            {
            #endif
                int steps = 10;
                if (d3ddevice == null)
                    ++steps;

                toolStrip1.Enabled = false;

                // HACK: Fixes Twinkle Circuit's geometry lingering if loaded before Sky Chase.
                // I'm sure the real problem is somewhere below, but this is sort of an all around cleanup.
                if (isStageLoaded)
                    LevelData.Clear();

                isStageLoaded = false;

                using (ProgressDialog progress = new ProgressDialog("Loading stage: " + levelName, steps))
                {
                    IniLevelData level = ini.Levels[levelID];

                    string syspath = Path.Combine(Environment.CurrentDirectory, ini.SystemPath);
                    string modpath = ini.ModPath;

                    SA1LevelAct levelact = new SA1LevelAct(level.LevelID);
                    LevelData.leveltexs = null;
                    cam = new EditorCamera(EditorOptions.RenderDrawDistance);

                    Invoke((Action<IWin32Window>)progress.Show, this);

                    if (d3ddevice == null)
                    {
                        progress.SetTask("Initializing Direct3D...");
                        Invoke((Action)InitializeDirect3D);
                        progress.StepProgress();
                    }

                    progress.SetTaskAndStep("Loading level data:", "Geometry");

                    if (string.IsNullOrEmpty(level.LevelGeometry))
                        LevelData.geo = null;
                    else
                    {
                        LevelData.geo = LandTable.LoadFromFile(level.LevelGeometry);
                        LevelData.LevelItems = new List<LevelItem>();
                        for (int i = 0; i < LevelData.geo.COL.Count; i++)
                            LevelData.LevelItems.Add(new LevelItem(LevelData.geo.COL[i], d3ddevice, i, selectedItems));
                    }

                    progress.StepProgress();
                    progress.SetStep("Textures");

                    LevelData.TextureBitmaps = new Dictionary<string, BMPInfo[]>();
                    LevelData.Textures = new Dictionary<string, Texture[]>();
                    if (LevelData.geo != null && !string.IsNullOrEmpty(LevelData.geo.TextureFileName))
                    {
                        BMPInfo[] TexBmps =
                            TextureArchive.GetTextures(Path.Combine(syspath, LevelData.geo.TextureFileName) + ".PVM");
                        Texture[] texs = new Texture[TexBmps.Length];
                        for (int j = 0; j < TexBmps.Length; j++)
                            texs[j] = new Texture(d3ddevice, TexBmps[j].Image, Usage.None, Pool.Managed);
                        if (!LevelData.TextureBitmaps.ContainsKey(LevelData.geo.TextureFileName))
                            LevelData.TextureBitmaps.Add(LevelData.geo.TextureFileName, TexBmps);
                        if (!LevelData.Textures.ContainsKey(LevelData.geo.TextureFileName))
                            LevelData.Textures.Add(LevelData.geo.TextureFileName, texs);
                        LevelData.leveltexs = LevelData.geo.TextureFileName;
                    }

                    progress.StepProgress();

                    #region Start Positions

                    progress.SetTaskAndStep("Setting up start positions...");

                    LevelData.StartPositions = new StartPosItem[LevelData.Characters.Length];
                    for (int i = 0; i < LevelData.StartPositions.Length; i++)
                    {
                        progress.SetStep(string.Format("{0}/{1}", (i + 1), LevelData.StartPositions.Length));

                        IniCharInfo character;
                        if (i == 0 && levelact.Level == SA1LevelIDs.PerfectChaos)
                            character = ini.Characters["SuperSonic"];
                        else
                            character = ini.Characters[LevelData.Characters[i]];

                        Dictionary<SA1LevelAct, SA1StartPosInfo> posini =
                            SA1StartPosList.Load(character.StartPositions);

                        Vertex pos = new Vertex();
                        int rot = 0;

                        if (posini.ContainsKey(levelact))
                        {
                            pos = posini[levelact].Position;
                            rot = posini[levelact].YRotation;
                        }
                        LevelData.StartPositions[i] = new StartPosItem(new ModelFile(character.Model).Model,
                            character.Textures, character.Height, pos, rot, d3ddevice, selectedItems);

                        LoadTextureList(character.TextureList, syspath);
                    }

                    progress.StepProgress();

                    #endregion

                    #region Death Zones

                    progress.SetTaskAndStep("Death Zones:", "Initializing...");

                    if (string.IsNullOrEmpty(level.DeathZones))
                        LevelData.DeathZones = null;
                    else
                    {
                        LevelData.DeathZones = new List<DeathZoneItem>();
                        DeathZoneFlags[] dzini = DeathZoneFlagsList.Load(level.DeathZones);
                        string path = Path.GetDirectoryName(level.DeathZones);
                        for (int i = 0; i < dzini.Length; i++)
                        {
                            progress.SetStep(String.Format("Loading model {0}/{1}", (i + 1), dzini.Length));

                            LevelData.DeathZones.Add(new DeathZoneItem(
                                new ModelFile(Path.Combine(path, i.ToString(System.Globalization.NumberFormatInfo.InvariantInfo) + ".sa1mdl"))
                                    .Model,
                                dzini[i].Flags, d3ddevice, selectedItems));
                        }
                    }

                    progress.StepProgress();

                    #endregion

                    #region Textures and Texture Lists

                    progress.SetTaskAndStep("Loading textures for:");

                    progress.SetStep("Common objects");
                    // Loads common object textures (e.g OBJ_REGULAR)
                    LoadTextureList(ini.ObjectTextureList, syspath);

                    progress.SetTaskAndStep("Loading stage texture lists...");

                    // Loads the textures in the texture list for this stage (e.g BEACH01)
                    foreach (string file in Directory.GetFiles(ini.LevelTextureLists))
                    {
                        LevelTextureList texini = LevelTextureList.Load(file);
                        if (texini.Level != levelact)
                            continue;

                        LoadTextureList(texini.TextureList, syspath);
                    }

                    progress.SetTaskAndStep("Loading textures for:", "Objects");
                    // Object texture list(s)
                    LoadTextureList(level.ObjectTextureList, syspath);

                    progress.SetStep("Stage");
                    // The stage textures... again? "Extra"?
                    if (level.Textures != null && level.Textures.Length > 0)
                        foreach (string tex in level.Textures)
                        {
                            LoadPVM(tex, syspath);

                            if (string.IsNullOrEmpty(LevelData.leveltexs))
                                LevelData.leveltexs = tex;
                        }

                    progress.StepProgress();

                    #endregion

                    #region Object Definitions / SET Layout

                    progress.SetTaskAndStep("Loading Object Definitions:", "Parsing...");

                    LevelData.ObjDefs = new List<ObjectDefinition>();
                    Dictionary<string, ObjectData> objdefini =
                        IniSerializer.Deserialize<Dictionary<string, ObjectData>>(ini.ObjectDefinitions);

                    if (!string.IsNullOrEmpty(level.ObjectList) && File.Exists(level.ObjectList))
                    {
                        List<ObjectData> objectErrors = new List<ObjectData>();
                        ObjectListEntry[] objlstini = ObjectList.Load(level.ObjectList, false);
                        Directory.CreateDirectory("dllcache").Attributes |= FileAttributes.Hidden;

                        for (int ID = 0; ID < objlstini.Length; ID++)
                        {
                            string codeaddr = objlstini[ID].CodeString;

                            if (!objdefini.ContainsKey(codeaddr))
                                codeaddr = "0";

                            ObjectData defgroup = objdefini[codeaddr];
                            ObjectDefinition def;

                            if (!string.IsNullOrEmpty(defgroup.CodeFile))
                            {
                                progress.SetStep("Compiling: " + defgroup.CodeFile);

                                // TODO: Split this out to a function
                                #region Compile object code files

                                string ty = defgroup.CodeType;
                                string dllfile = Path.Combine("dllcache", ty + ".dll");
                                DateTime modDate = DateTime.MinValue;
                                if (File.Exists(dllfile))
                                    modDate = File.GetLastWriteTime(dllfile);
                                string fp = defgroup.CodeFile.Replace('/', Path.DirectorySeparatorChar);
                                if (modDate >= File.GetLastWriteTime(fp) && modDate > File.GetLastWriteTime(Application.ExecutablePath))
                                    def =
                                        (ObjectDefinition)
                                            Activator.CreateInstance(
                                                Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, dllfile))
                                                    .GetType(ty));
                                else
                                {
                                    string ext = Path.GetExtension(fp);
                                    CodeDomProvider pr = null;
                                    switch (ext.ToLowerInvariant())
                                    {
                                        case ".cs":
                                            pr = new Microsoft.CSharp.CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
                                            break;
                                        case ".vb":
                                            pr = new Microsoft.VisualBasic.VBCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
                                            break;
                                    }
                                    if (pr != null)
                                    {
                                        CompilerParameters para =
                                            new CompilerParameters(new string[]
                                            {
                                                "System.dll", "System.Core.dll", "System.Drawing.dll", Assembly.GetAssembly(typeof (Vector3)).Location,
                                                Assembly.GetAssembly(typeof (Texture)).Location, Assembly.GetAssembly(typeof (D3DX)).Location,
                                                Assembly.GetExecutingAssembly().Location, Assembly.GetAssembly(typeof (LandTable)).Location,
                                                Assembly.GetAssembly(typeof (EditorCamera)).Location, Assembly.GetAssembly(typeof (SA1LevelAct)).Location,
                                                Assembly.GetAssembly(typeof (ObjectDefinition)).Location
                                            })
                                            {
                                                GenerateExecutable = false,
                                                GenerateInMemory = false,
                                                IncludeDebugInformation = true,
                                                OutputAssembly = Path.Combine(Environment.CurrentDirectory, dllfile)
                                            };
                                        CompilerResults res = pr.CompileAssemblyFromFile(para, fp);
                                        if (res.Errors.HasErrors)
                                        {
                                            // TODO: Merge with existing object error handler. I add too many ToDos.
                                            string errors = null;
                                            foreach (CompilerError item in res.Errors)
                                                errors += String.Format("\n\n{0}, {1}: {2}", item.Line, item.Column, item.ErrorText);

                                            MessageBox.Show("Failed to compile object code file:\n" + defgroup.CodeFile + errors,
                                                "Object compilation failure", MessageBoxButtons.OK, MessageBoxIcon.Error);

                                            def = new DefaultObjectDefinition();
                                        }
                                        else
                                        {
                                            def = (ObjectDefinition)Activator.CreateInstance(res.CompiledAssembly.GetType(ty));
                                        }
                                    }
                                    else
                                        def = new DefaultObjectDefinition();
                                }

                                #endregion
                            }
                            else
                            {
                                def = new DefaultObjectDefinition();
                            }

                            LevelData.ObjDefs.Add(def);

                            // The only reason .Model is checked for null is for objects that don't yet have any
                            // models defined for them. It would be annoying seeing that error all the time!
                            if (string.IsNullOrEmpty(defgroup.CodeFile) && !string.IsNullOrEmpty(defgroup.Model))
                            {
                                progress.SetStep("Loading: " + defgroup.Model);
                                // Otherwise, if the model file doesn't exist and/or no texture file is defined,
                                // load the "default object" instead ("?").
                                if (!File.Exists(defgroup.Model) || string.IsNullOrEmpty(defgroup.Texture) ||
                                    !LevelData.Textures.ContainsKey(defgroup.Texture))
                                {
                                    ObjectData error = new ObjectData { Name = defgroup.Name, Model = defgroup.Model, Texture = defgroup.Texture };
                                    objectErrors.Add(error);
                                    defgroup.Model = null;
                                }
                            }

                            def.Init(defgroup, objlstini[ID].Name, d3ddevice);
                            def.SetInternalName(objlstini[ID].Name);
                        }

                        // Loading SET Layout
                        progress.SetTaskAndStep("Loading SET items", "Initializing...");

                        if (LevelData.ObjDefs.Count > 0)
                        {
                            LevelData.SETName = level.SETName ?? level.LevelID;
                            string setstr = Path.Combine(syspath, "SET" + LevelData.SETName + "{0}.bin");
                            LevelData.SETItems = new List<SETItem>[LevelData.SETChars.Length];
                            for (int i = 0; i < LevelData.SETChars.Length; i++)
                            {
                                List<SETItem> list = new List<SETItem>();
                                byte[] setfile = null;

                                string formatted = string.Format(setstr, LevelData.SETChars[i]);

                                if (modpath != null && File.Exists(Path.Combine(modpath, formatted)))
                                    setfile = File.ReadAllBytes(Path.Combine(modpath, formatted));
                                else if (File.Exists(formatted))
                                    setfile = File.ReadAllBytes(formatted);

                                if (setfile != null)
                                {
                                    progress.SetTask("SET: " + formatted.Replace(Environment.CurrentDirectory, ""));

                                    int count = BitConverter.ToInt32(setfile, 0);
                                    int address = 0x20;
                                    for (int j = 0; j < count; j++)
                                    {
                                        progress.SetStep(string.Format("{0}/{1}", (j + 1), count));

                                        SETItem ent = new SETItem(setfile, address, selectedItems);
                                        list.Add(ent);
                                        address += 0x20;
                                    }
                                }
                                LevelData.SETItems[i] = list;
                            }
                        }
                        else
                        {
                            LevelData.SETItems = null;
                        }

                        // Checks if there have been any errors added to the error list and does its thing
                        // This thing is a mess. If anyone can think of a cleaner way to do this, be my guest.
                        if (objectErrors.Count > 0)
                        {
                            int count = objectErrors.Count;
                            List<string> errorStrings = new List<string> { "The following objects failed to load:" };

                            foreach (ObjectData o in objectErrors)
                            {
                                bool texEmpty = string.IsNullOrEmpty(o.Texture);
                                bool texExists = (!string.IsNullOrEmpty(o.Texture) && LevelData.Textures.ContainsKey(o.Texture));
                                errorStrings.Add("");
                                errorStrings.Add("Object:\t\t" + o.Name);
                                errorStrings.Add("\tModel:");
                                errorStrings.Add("\t\tName:\t" + o.Model);
                                errorStrings.Add("\t\tExists:\t" + File.Exists(o.Model));
                                errorStrings.Add("\tTexture:");
                                errorStrings.Add("\t\tName:\t" + ((texEmpty) ? "(N/A)" : o.Texture));
                                errorStrings.Add("\t\tExists:\t" + texExists);
                            }

                            // TODO: Proper logging. Who knows where this file may end up
                            File.WriteAllLines("SADXLVL2.log", errorStrings.ToArray());

                            MessageBox.Show(count + ((count == 1) ? " object" : " objects") + " failed to load their model(s).\n"
                                            +
                                            "\nThe level will still display, but the objects in question will not display their proper models." +
                                            "\n\nPlease check the log for details.",
                                "Error loading models", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                    else
                    {
                        LevelData.SETItems = null;
                    }

                    progress.StepProgress();

                    #endregion

                    #region CAM Layout

                    progress.SetTaskAndStep("Loading CAM items", "Initializing...");

                    string camstr = Path.Combine(syspath, "CAM" + LevelData.SETName + "{0}.bin");

                    LevelData.CAMItems = new List<CAMItem>[LevelData.SETChars.Length];
                    for (int i = 0; i < LevelData.SETChars.Length; i++)
                    {
                        List<CAMItem> list = new List<CAMItem>();
                        byte[] camfile = null;

                        string formatted = string.Format(camstr, LevelData.SETChars[i]);

                        if (modpath != null && File.Exists(Path.Combine(modpath, formatted)))
                            camfile = File.ReadAllBytes(Path.Combine(modpath, formatted));
                        else if (File.Exists(formatted))
                            camfile = File.ReadAllBytes(formatted);

                        if (camfile != null)
                        {
                            progress.SetTask("CAM: " + formatted.Replace(Environment.CurrentDirectory, ""));

                            int count = BitConverter.ToInt32(camfile, 0);
                            int address = 0x40;
                            for (int j = 0; j < count; j++)
                            {
                                progress.SetStep(string.Format("{0}/{1}", (j + 1), count));

                                CAMItem ent = new CAMItem(camfile, address, selectedItems);
                                list.Add(ent);
                                address += 0x40;
                            }
                        }

                        LevelData.CAMItems[i] = list;
                    }

                    CAMItem.Init(d3ddevice);

                    progress.StepProgress();

                    #endregion

                    #region Loading Level Effects

                    LevelData.leveleff = null;
                    if (!string.IsNullOrEmpty(level.Effects))
                    {
                        progress.SetTaskAndStep("Loading Level Effects...");

                        LevelDefinition def = null;
                        string ty = "SADXObjectDefinitions.Level_Effects." + Path.GetFileNameWithoutExtension(level.Effects);
                        string dllfile = Path.Combine("dllcache", ty + ".dll");
                        DateTime modDate = DateTime.MinValue;

                        if (File.Exists(dllfile))
                            modDate = File.GetLastWriteTime(dllfile);

                        string fp = level.Effects.Replace('/', Path.DirectorySeparatorChar);
                        if (modDate >= File.GetLastWriteTime(fp) && modDate > File.GetLastWriteTime(Application.ExecutablePath))
                        {
                            def =
                                (LevelDefinition)
                                    Activator.CreateInstance(
                                        Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, dllfile)).GetType(ty));
                        }
                        else
                        {
                            string ext = Path.GetExtension(fp);
                            CodeDomProvider pr = null;
                            switch (ext.ToLowerInvariant())
                            {
                                case ".cs":
                                    pr = new Microsoft.CSharp.CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
                                    break;
                                case ".vb":
                                    pr = new Microsoft.VisualBasic.VBCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
                                    break;
                            }
                            if (pr != null)
                            {
                                CompilerParameters para =
                                    new CompilerParameters(new string[]
                                {
                                    "System.dll", "System.Core.dll", "System.Drawing.dll", Assembly.GetAssembly(typeof (Vector3)).Location,
                                    Assembly.GetAssembly(typeof (Texture)).Location, Assembly.GetAssembly(typeof (D3DX)).Location,
                                    Assembly.GetExecutingAssembly().Location, Assembly.GetAssembly(typeof (LandTable)).Location,
                                    Assembly.GetAssembly(typeof (EditorCamera)).Location, Assembly.GetAssembly(typeof (SA1LevelAct)).Location,
                                    Assembly.GetAssembly(typeof (Item)).Location
                                })
                                    {
                                        GenerateExecutable = false,
                                        GenerateInMemory = false,
                                        IncludeDebugInformation = true,
                                        OutputAssembly = Path.Combine(Environment.CurrentDirectory, dllfile)
                                    };
                                CompilerResults res = pr.CompileAssemblyFromFile(para, fp);
                                if (!res.Errors.HasErrors)
                                    def = (LevelDefinition)Activator.CreateInstance(res.CompiledAssembly.GetType(ty));
                            }
                        }

                        if (def != null)
                            def.Init(level, levelact.Act, d3ddevice);

                        LevelData.leveleff = def;
                    }

                    progress.StepProgress();

                    #endregion

                    #region Loading Splines

                    LevelData.LevelSplines = new List<SplineData>();
                    SplineData.Init();

                    if (!string.IsNullOrEmpty(ini.Paths))
                    {
                        progress.SetTaskAndStep("Reticulating splines...");

                        String splineDirectory = Path.Combine(Path.Combine(Environment.CurrentDirectory, ini.Paths),
                            levelact.ToString());

                        if (Directory.Exists(splineDirectory))
                        {
                            List<string> pathFiles = new List<string>();

                            for (int i = 0; i < int.MaxValue; i++)
                            {
                                string path = string.Concat(splineDirectory, string.Format("/{0}.ini", i));
                                if (File.Exists(path))
                                {
                                    pathFiles.Add(path);
                                }
                                else
                                    break;
                            }

                            foreach (string pathFile in pathFiles) // looping through path files
                            {
                                SplineData newSpline = new SplineData(PathData.Load(pathFile), selectedItems);

                                newSpline.RebuildMesh(d3ddevice);

                                LevelData.LevelSplines.Add(newSpline);
                            }
                        }
                    }

                    progress.StepProgress();

                    #endregion

                    #region Stage Lights
                    progress.SetTaskAndStep("Loading lights...");

                    if ((stageLightList != null) && (stageLightList.Count > 0))
                    {
                        List<SA1StageLightData> lightList = new List<SA1StageLightData>();

                        foreach (SA1StageLightData lightData in stageLightList)
                        {
                            if ((lightData.Level == levelact.Level) && (lightData.Act == levelact.Act))
                                lightList.Add(lightData);
                        }

                        if (lightList.Count > 0)
                        {
                            for (int i = 0; i < d3ddevice.Lights.Count; i++) // clear all default lights
                            {
                                d3ddevice.Lights[i].Enabled = false;
                            }

                            for (int i = 0; i < lightList.Count; i++)
                            {
                                SA1StageLightData lightData = lightList[i];

                                d3ddevice.Lights[i].Enabled = true;
                                d3ddevice.Lights[i].Type = (lightData.UseDirection) ? LightType.Directional : LightType.Point;
                                d3ddevice.Lights[i].Diffuse = lightData.RGB.ToColor();
                                d3ddevice.Lights[i].DiffuseColor = new ColorValue(lightData.RGB.X, lightData.RGB.Y, lightData.RGB.Z, 1.0f);
                                d3ddevice.Lights[i].Ambient = lightData.AmbientRGB.ToColor();
                                d3ddevice.Lights[i].Specular = Color.Black;
                                d3ddevice.Lights[i].Direction = lightData.Direction.ToVector3();
                                d3ddevice.Lights[i].Range = lightData.Dif; // guessing here
                            }
                        }
                        else
                        {
                            MessageBox.Show("No lights were found for this stage. Using default lights instead.", "No lights found",
                                MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        }
                    }

                    progress.StepProgress();
                    #endregion

                    transformGizmo = new TransformGizmo();

                    Invoke((Action)progress.Close);
                }
            #if !DEBUG
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    ex.GetType().Name + ": " + ex.Message + "\nLog file has been saved to " + Path.Combine(Environment.CurrentDirectory, "SADXLVL2.log") + ".\nSend this to MainMemory on the Sonic Retro forums.",
                    "SADXLVL2 Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                File.WriteAllText("SADXLVL2.log", ex.ToString());
                initerror = true;
            }
            #endif
        }
예제 #3
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!");
                }
            }
        }