Esempio n. 1
0
        public IPXPmx Import(string path, IPERunArgs args)
        {
            try
            {
                if (File.Exists(path + ".log"))
                {
                    File.Delete(path + ".log");
                }
            }
            catch { }

            IPXPmxBuilder builder = PEStaticBuilder.Pmx;

            ImportForm form = new ImportForm(path, args);

            // This call blocks the thread until the dialog is closed.
            DialogResult dialogResult = form.ShowDialog();

            if (dialogResult == DialogResult.OK)
            {
                // DialogResult.OK does not mean a successful outcome, only that the user has initiated the process and then the form was closed for whatever reason.
                // The outcome of the actual import operation is indicated by ImportForm.ImportResult.
                switch (form.ImportResult.Result)
                {
                case ImportResult.ResultType.Success:
                    WriteLogFile(path + ".log", string.Format("Import operation was completed successfully with {0} errors and {1} warnings.", form.ImportResult.ErrorCount, form.ImportResult.WarningCount));
                    return((IPXPmx)form.ImportResult.Pmx);

                case ImportResult.ResultType.Fail:
                    MessageBox.Show(string.Format("The import operation has failed.\n\n{0}", form.ImportResult.Pmx as Exception));
                    WriteLogFile(path + ".log", string.Format("Import operation has failed with {0} errors and {1} warnings.", form.ImportResult.ErrorCount, form.ImportResult.WarningCount));
                    break;

                case ImportResult.ResultType.Cancel:
                    MessageBox.Show("The operation was cancelled by the user.");
                    WriteLogFile(path + ".log", "The operation was cancelled by the user.");
                    break;

                default:
                    MessageBox.Show("The import operation was halted before a valid result was obtained.");
                    WriteLogFile(path + ".log", "The import operation was halted for an unknown reason before a valid result was obtained.");
                    break;
                }
            }
            else
            {
                MessageBox.Show("Test");
            }

            // If control reaches this point, then the import operation was not completed successfully and there is no valid data to return to the application.
            return(null);
        }
Esempio n. 2
0
        public void RegistToPmx(IPXPmx pmx, IPXPmxBuilder bld, FileFormat.MQOFile mqo, WorkVertexDict dict, BackgroundWorker bw)
        {
            int N = list.Length;

            for (int i = 0; i < N; i++)
            {
                bw.ReportProgress(100 * i / N, "面の登録中");
                list[i].ForEach(f =>
                {
                    var xf     = bld.Face();
                    xf.Vertex1 = dict.GetVertex(f.V0);
                    xf.Vertex2 = dict.GetVertex(f.V1);
                    xf.Vertex3 = dict.GetVertex(f.V2);
                    pmx.Material[i].Faces.Add(xf);
                });
            }
        }
Esempio n. 3
0
        private async void executeButton_Click(object sender, EventArgs e)
        {
            cancelButton.Enabled = true;
            IPXPmx        pmx     = _args.Host.Connector.Pmx.GetCurrentState();
            IPXPmxBuilder builder = _args.Host.Builder.Pmx;
            XmlDocument   doc     = new XmlDocument();

            doc.Load(pathText.Text);

            RunnerResult result = await Task.Run(() => { return(Runner.Execute(doc, pmx, builder, _progress)); });

            if (result == RunnerResult.Success)
            {
                UpdatePmx(pmx);
            }
            cancelButton.Enabled = false;
        }
Esempio n. 4
0
        // Generate straight bone chain
        public static IPXBone[] GenerateChain(IPXPmxBuilder builder, int count, Vector3 distance, Vector3 center, string name, string nameE)
        {
            IPXBone[] bones = new IPXBone[count];

            for (int i = 0; i < count; ++i)
            {
                IPXBone bone = builder.Bone();
                bone.Name     = name.Replace("#", i.ToString()).Replace("&", (i + 1).ToString());
                bone.NameE    = nameE.Replace("#", i.ToString()).Replace("&", (i + 1).ToString());
                bone.Position = center + (distance * i);
                if (i > 0)
                {
                    bone.Parent        = bones[i - 1];
                    bone.Parent.ToBone = bone;
                }
                bones[i] = bone;
            }

            return(bones);
        }
Esempio n. 5
0
        // Create segmented bone chain
        public static IPXBone[] GenerateSegmentedChain(IPXPmxBuilder builder, int count, Vector3[] points, string name, string nameE)
        {
            IPXBone[] bones        = new IPXBone[count];
            int       segmentCount = points.Length - 1;
            float     totalLength  = 0;

            float[] segmentLengths = new float[segmentCount];

            // Determine the lengths of segments
            for (int i = 0; i < segmentCount; ++i)
            {
                float length = points[i].Distance(points[i + 1]);
                segmentLengths[i] = length;
                totalLength      += length;
            }

            // Determine the number of links that can fit into each segment
            float avgDist = totalLength / count;

            int[] bonesPerSegment = new int[segmentCount];
            int   remaining       = count;

            for (int i = 0; i < segmentCount - 1; ++i)
            {
                bonesPerSegment[i] = Mathf.RoundToInt(segmentLengths[i] / avgDist);
                remaining         -= bonesPerSegment[i];
            }
            // Put any remaining bones into the last segment
            bonesPerSegment[segmentCount - 1] = remaining;

            // Create the bones
            for (int i = 0; i < segmentCount; ++i)
            {
                System.Windows.Forms.MessageBox.Show($"{i}\t{segmentLengths[i]}");
            }

            return(bones);
        }
Esempio n. 6
0
        public void RegistToPmx(IPXPmx pmx, IPXPmxBuilder bld, FileFormat.MQOFile mqo, BackgroundWorker bw)
        {
            int N = dict.Count;

            for (int i = 0; i < N; i++)
            {
                bw.ReportProgress(100 * i / N, "頂点の登録中");
                var       wv   = dict[i];
                IPXVertex v    = bld.Vertex();
                var       mObj = mqo.Object[wv.ObjID];
                var       mv   = mObj.Vertex[wv.VertID];
                v.Position.X = (float)(mv.X);
                v.Position.Y = (float)(mv.Y);
                v.Position.Z = -(float)(mv.Z);
                FileFormat.MQOUV muv = mObj.UV[wv.UvID];
                v.UV.U     = (float)muv.U;
                v.UV.V     = (float)muv.V;
                v.Normal.X = (float)mObj.Normal[wv.NormID].X;
                v.Normal.Y = (float)mObj.Normal[wv.NormID].Y;
                v.Normal.Z = -(float)mObj.Normal[wv.NormID].Z;
                wv.vertex  = v;
                pmx.Vertex.Add(v);
            }
        }
Esempio n. 7
0
        // Create uneven bone chain along spline
        public static IPXBone[] GenerateSplineChain(IPXPmxBuilder builder, int count, Vector3[] points, string name, string nameE)
        {
            IPXBone[] bones = new IPXBone[count];

            // Construct a cubic Bézier curve from the points
            // Place a link at every t = (1 / count) point
            float dt = 1.0f / count;

            for (int i = 0; i < count; ++i)
            {
                IPXBone bone = builder.Bone();
                bone.Name     = name.Replace("#", i.ToString()).Replace("&", (i + 1).ToString());
                bone.NameE    = nameE.Replace("#", i.ToString()).Replace("&", (i + 1).ToString());
                bone.Position = Mathf.Curve.BezierPoint(dt * i, points);
                if (i > 0)
                {
                    bone.Parent        = bones[i - 1];
                    bone.Parent.ToBone = bone;
                }
                bones[i] = bone;
            }

            return(bones);
        }
Esempio n. 8
0
        //DoWorkイベントハンドラ
        private void ProgressDialog_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bw = (BackgroundWorker)sender;

            bw.ReportProgress(0, "ファイル読み込み中(バーは動きません (^-^;)");
            using (FileFormat.MQOFile mqo = FileFormat.MQOFile.load(mqopath, true)) // 三角面化して読み込む
            {
                if (mqo == null) throw new Exception("読み込み失敗。おそらくmqoファイルの構文エラー。");

                if (mqo.Object.Count == 0) throw new Exception("オブジェクトが空です。");

                // pmx作成
                bld = PEStaticBuilder.Pmx;
                pmx = bld.Pmx();
                pmx.Clear();

                // モデル名は最初のオブジェクト名を利用する
                pmx.ModelInfo.ModelName = mqo.Object[0].Name;

                // 材質
                int mc = mqo.Material.Count;
                if (mc == 0) throw new Exception("材質がありません。少なくとも1つ材質が必要です。");

                int cw = 100 / mc;
                int pc = 0;
                mqo.Material.ForEach(m =>
                {
                    bw.ReportProgress(cw * pc++, "材質の変換中");
                    IPXMaterial pm = bld.Material();
                    pm.Name = m.Name;
                    pm.Diffuse.R = (float)(m.Color.R * m.Diffuse);
                    pm.Diffuse.G = (float)(m.Color.G * m.Diffuse);
                    pm.Diffuse.B = (float)(m.Color.B * m.Diffuse);
                    pm.Diffuse.A = (float)m.Color.A;
                    pm.Ambient.R = (float)(m.Color.R * m.Ambient);
                    pm.Ambient.G = (float)(m.Color.G * m.Ambient);
                    pm.Ambient.B = (float)(m.Color.B * m.Ambient);
                    pm.Specular.R = (float)(m.Color.R * m.Specular);
                    pm.Specular.G = (float)(m.Color.G * m.Specular);
                    pm.Specular.B = (float)(m.Color.B * m.Specular);
                    pm.Power = (float)m.Power;
                    pm.Tex = m.Tex;
                    pmx.Material.Add(pm);
                });

                // 各オブジェクトを処理
                // ただし、非表示オブジェクトはスキップ
                mc = mqo.Object.Count;
                cw = 100 / mc;
                bw.ReportProgress(0, "法線を計算中");
                Parallel.ForEach(mqo.Object, mObj =>
                {
                    if (mObj.Visible) mObj.CalcNormals();
                    bw.ReportProgress(cw, 1);
                });

                // 先に頂点をすべて登録してから面を登録する
                // 頂点登録と面登録を交互に行うととんでもなく遅くなる
                mc = mqo.Material.Count;
                WorkFaceList workfacelist = new WorkFaceList(mc);
                WorkVertexDict workvertexdict = new WorkVertexDict();

                mc = mqo.Object.Count;
                cw = 100 / mc;
                pc = 0;
                for (int objID=0; objID<mc; objID++)
                {
                    var mObj = mqo.Object[objID];
                    bw.ReportProgress(cw * pc++, String.Format("'{0}'の変換中", mObj.Name));
                    mObj.Face.ForEach(fc =>
                    {
                        if (!mObj.Visible) return; // 非表示オブジェクトは無視

                        // 材質割り当てのない面は材質0として処理
                        int matID = fc.MatID < 0 ? 0 : fc.MatID;

                        Func<int, int> get_vertex = i => workvertexdict.RegistVertex(objID, fc.VertexID[i], fc.UVID[i], fc.NormalID[i]);
                        workfacelist.AddFace(matID, get_vertex(0), get_vertex(1), get_vertex(2));
                    });
                }

                workvertexdict.RegistToPmx(pmx, bld, mqo, bw);
                workfacelist.RegistToPmx(pmx, bld, mqo, workvertexdict, bw);
            }
        }
Esempio n. 9
0
 public void RegistToPmx(IPXPmx pmx, IPXPmxBuilder bld, FileFormat.MQOFile mqo, BackgroundWorker bw)
 {
     int N = dict.Count;
     for(int i=0; i<N; i++)
     {
         bw.ReportProgress(100 * i / N, "頂点の登録中");
         var wv = dict[i];
         IPXVertex v = bld.Vertex();
         var mObj = mqo.Object[wv.ObjID];
         var mv = mObj.Vertex[wv.VertID];
         v.Position.X = (float)(mv.X);
         v.Position.Y = (float)(mv.Y);
         v.Position.Z = -(float)(mv.Z);
         FileFormat.MQOUV muv = mObj.UV[wv.UvID];
         v.UV.U = (float)muv.U;
         v.UV.V = (float)muv.V;
         v.Normal.X = (float)mObj.Normal[wv.NormID].X;
         v.Normal.Y = (float)mObj.Normal[wv.NormID].Y;
         v.Normal.Z = -(float)mObj.Normal[wv.NormID].Z;
         wv.vertex = v;
         pmx.Vertex.Add(v);
     }
 }
Esempio n. 10
0
 public void RegistToPmx(IPXPmx pmx, IPXPmxBuilder bld, FileFormat.MQOFile mqo, WorkVertexDict dict, BackgroundWorker bw)
 {
     int N = list.Length;
     for (int i = 0; i < N; i++)
     {
         bw.ReportProgress(100 * i / N, "面の登録中");
         list[i].ForEach(f =>
         {
             var xf = bld.Face();
             xf.Vertex1 = dict.GetVertex(f.V0);
             xf.Vertex2 = dict.GetVertex(f.V1);
             xf.Vertex3 = dict.GetVertex(f.V2);
             pmx.Material[i].Faces.Add(xf);
         });
     }
 }
Esempio n. 11
0
 public RunnerArgs(XmlDocument document, IPXPmx pmx, IPXPmxBuilder builder)
 {
     Document = document;
     Pmx      = pmx;
     Builder  = builder;
 }
Esempio n. 12
0
        /// <summary>
        /// Parses the Material Template Library at the provided path and returns a list of materials.
        /// </summary>
        private static Dictionary <string, IPXMaterial> ImportMaterials(string path, IPXPmxBuilder builder, ImportSettings settings, IOProgress progress)
        {
            // Cancel the process if needed
            if (progress.CancellationToken.IsCancellationRequested)
            {
                progress.CancellationToken.ThrowIfCancellationRequested();
            }

            StreamReader reader = null;

            System.Globalization.NumberFormatInfo fi = System.Globalization.NumberFormatInfo.InvariantInfo;
            System.Globalization.NumberStyles     ns = System.Globalization.NumberStyles.Float;

            Dictionary <string, IPXMaterial> materials = new Dictionary <string, IPXMaterial>();
            IPXMaterial current    = null;
            int         lineNumber = 0;

            char[] separator = { ' ' };

            try
            {
                reader = new StreamReader(path);
                while (!reader.EndOfStream)
                {
                    // Cancel the process if needed
                    if (progress.CancellationToken.IsCancellationRequested)
                    {
                        progress.CancellationToken.ThrowIfCancellationRequested();
                    }

                    string line = reader.ReadLine().Trim();
                    ++lineNumber;
                    if (string.IsNullOrWhiteSpace(line) || line[0] == '#')
                    {
                        continue;
                    }
                    string[] split = line.Split(separator, StringSplitOptions.RemoveEmptyEntries);
                    switch (split[0])
                    {
                    // Diffuse color and opacity
                    case "Kd":
                        if (current != null)
                        {
                            float r = 0, g = 0, b = 0, a = 1;
                            float.TryParse(split[1], ns, fi, out r);
                            float.TryParse(split[2], ns, fi, out g);
                            float.TryParse(split[3], ns, fi, out b);
                            if (split.Length > 4)
                            {
                                float.TryParse(split[4], ns, fi, out a);
                            }

                            current.Diffuse = new V4(r, g, b, a);
                        }
                        break;

                    // Ambient - used as emissive
                    case "Ka":
                        if (current != null)
                        {
                            float r = 0, g = 0, b = 0;
                            float.TryParse(split[1], ns, fi, out r);
                            float.TryParse(split[2], ns, fi, out g);
                            float.TryParse(split[3], ns, fi, out b);
                            current.Ambient = new V3(r, g, b);
                        }
                        break;

                    // Specular color
                    case "Ks":
                        if (current != null)
                        {
                            float r = 0, g = 0, b = 0;
                            float.TryParse(split[1], ns, fi, out r);
                            float.TryParse(split[2], ns, fi, out g);
                            float.TryParse(split[3], ns, fi, out b);
                            current.Specular = new V3(r, g, b);
                        }
                        break;

                    // Emissive
                    case "Ke":
                        if (current != null)
                        {
                            float r = 0, g = 0, b = 0;
                            float.TryParse(split[1], ns, fi, out r);
                            float.TryParse(split[2], ns, fi, out g);
                            float.TryParse(split[3], ns, fi, out b);
                            current.Ambient = new V3(r, g, b);
                        }
                        break;

                    // Opacity (1 is fully opaque)
                    case "d":
                        if (current != null)
                        {
                            if (float.TryParse(split[1], ns, fi, out float a))
                            {
                                current.Diffuse.A = a;
                            }
                        }
                        break;

                    // Transparency (1 is fully transparent)
                    case "Tr":
                        if (current != null)
                        {
                            if (float.TryParse(split[1], ns, fi, out float a))
                            {
                                current.Diffuse.A = 1.0f - a;
                            }
                        }
                        break;

                    // Specular exponent
                    case "Ns":
                        if (current != null)
                        {
                            if (float.TryParse(split[1], ns, fi, out float a))
                            {
                                current.Power = a;
                            }
                        }
                        break;

                    // Illumination mode (unused)
                    case "illum":
                        break;

                    // Diffuse map
                    case "map_Kd":
                        if (current != null)
                        {
                            current.Tex = line.Substring(7);
                            if (settings.WhiteMaterialIfTextured)
                            {
                                current.Diffuse = new V4(1, 1, 1, current.Diffuse.A);
                                current.Ambient = new V3(0.5f, 0.5f, 0.5f);
                            }
                        }
                        break;

                    // Specular map
                    case "map_Ks":
                        break;

                    // Ambient map
                    case "map_Ka":
                        break;

                    // Begin a new material
                    case "newmtl":
                        current               = builder.Material();
                        current.Name          = current.NameE = line.Substring(7);
                        current.Diffuse       = new V4(1, 1, 1, 1);
                        current.Ambient       = new V3(0.5f, 0.5f, 0.5f);
                        current.Specular      = new V3(0, 0, 0);
                        current.Power         = 20;
                        current.SelfShadow    = true;
                        current.SelfShadowMap = true;
                        current.Shadow        = true;
                        current.BothDraw      = false;

                        if (materials.ContainsKey(current.Name))
                        {
                            progress.ReportWarning(string.Format("[MTL {1}] Duplicate material found: \"{0}\".", current.Name, lineNumber));
                        }
                        else
                        {
                            materials.Add(current.Name, current);
                        }

                        break;

                    default:
                        break;
                    }
                }
            }
            catch (OperationCanceledException) { throw; }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                    reader = null;
                }
            }

            return(materials);
        }
Esempio n. 13
0
        // Create a physics chain that fits onto the bone chain
        public static void GeneratePhysics(IPXPmxBuilder builder, IPXBone[] bones, PhysicsSettings settings, out IPXBody[] rigidbodies, out IPXJoint[] joints)
        {
            rigidbodies = new IPXBody[bones.Length - 1];
            joints      = new IPXJoint[bones.Length - 2];

            for (int i = 0; i < rigidbodies.Length; ++i)
            {
                // Basic setup
                IPXBody b = rigidbodies[i] = builder.Body();
                b.Position = Vector3.Average(bones[i].Position, bones[i + 1].Position);
                b.Bone     = bones[i];
                b.Name     = b.Bone.Name;
                b.NameE    = b.Bone.NameE;
                b.Mode     = settings.BodyMode;

                // Size
                b.BoxKind = settings.Shape;
                float w = settings.Width;
                float h = settings.Height;
                float length;
                switch (settings.LengthCalculation)
                {
                case PhysicsSettings.LengthCalculationMode.Relative:
                    length = Vector3.Distance(bones[i].Position, bones[i + 1].Position) * settings.Length;
                    break;

                case PhysicsSettings.LengthCalculationMode.DistanceFromEnds:
                    length = Math.Max(Vector3.Distance(bones[i].Position, bones[i + 1].Position) - settings.Length * 2, 0);
                    break;

                default:
                    length = settings.Length;
                    break;
                }
                if (settings.Shape == PEPlugin.Pmd.BodyBoxKind.Sphere)
                {
                    b.BoxSize = new V3(length / 2.0f, 1, 1);
                }
                else
                {
                    b.BoxSize = new Vector3(w, length / 2.0f, h);
                }

                // Angle
                V3 dir = bones[i + 1].Position - bones[i].Position;
                dir.Normalize();
                float heading = Mathf.Atan2(dir.X, dir.Z);
                float theta   = -heading;
                V3    elev    = new V3(Mathf.Cos(theta) * dir.X + Mathf.Sin(theta) * dir.Z, dir.Y, -Mathf.Sin(theta) * dir.X + Mathf.Cos(theta) * dir.Z);
                b.Rotation = new V3(Mathf.Atan2(elev.Z, elev.Y), heading, 0);
            }

            for (int i = 0; i < joints.Length; ++i)
            {
                IPXJoint j = joints[i] = builder.Joint();
                j.Position = bones[i + 1].Position;
                j.BodyA    = rigidbodies[i];
                j.BodyB    = rigidbodies[i + 1];
                j.Name     = j.BodyA.Name;
                j.NameE    = j.BodyA.NameE;
            }
        }
Esempio n. 14
0
        // Create evenly spaced bone chain along spline
        public static IPXBone[] GenerateSplineChainEvenSpaced(IPXPmxBuilder builder, int count, Vector3[] points, string name, string nameE)
        {
            List <IPXBone> bones = new List <IPXBone>();

            // Identify the t values that divide the spline into a count number of equal pieces
            float deltaT = 1.0f / CURVE_POINT_COUNT;                  // The density of t parameters

            Vector3[] curve         = new Vector3[CURVE_POINT_COUNT]; // Calculated curve points
            float     curveLength   = 0;                              // The total arc length of the curve
            Vector3   previousPoint = points[0];

            for (int i = 0; i < CURVE_POINT_COUNT; ++i)
            {
                Vector3 pt = Mathf.Curve.BezierPoint(deltaT * i, points);
                curveLength  += pt.Distance(previousPoint);
                previousPoint = curve[i] = pt;
            }
            float distance = curveLength / count;           // The desired arc length between links

            float[] linkT = new float[count];               // The t parameters that divide the spline into roughly equal parts; the first and last are always 0 and 1.
            linkT[0]         = 0;
            linkT[count - 1] = 1;
            int   linkNumber = 1;
            float distSoFar  = 0;

            for (int i = 1; i < CURVE_POINT_COUNT; ++i)
            {
                distSoFar += curve[i].Distance(curve[i - 1]);
                if (distSoFar >= distance)
                {
                    linkT[linkNumber] = deltaT * i;
                    distSoFar         = 0;
                    ++linkNumber;
                }
                if (linkNumber >= count)
                {
                    break;
                }
            }

            if (DEBUG)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder("t\tpoint\n\n");
                foreach (float t in linkT)
                {
                    sb.AppendFormat("{0:f4}\t{1}\n", t, Mathf.Curve.BezierPoint(t, points));
                }
                System.Windows.Forms.MessageBox.Show(sb.Append("All t values should be between 0 and 1, in incremental order.").ToString());
            }

            // Place the links at the desired t parameters
            for (int i = 0; i < count; ++i)
            {
                IPXBone bone = builder.Bone();
                bone.Name     = name.Replace("#", i.ToString()).Replace("&", (i + 1).ToString());
                bone.NameE    = nameE.Replace("#", i.ToString()).Replace("&", (i + 1).ToString());
                bone.Position = Mathf.Curve.BezierPoint(linkT[i], points);
                if (i > 0)
                {
                    bone.Parent        = bones[i - 1];
                    bone.Parent.ToBone = bone;
                }
                bones.Add(bone);
            }

            return(bones.ToArray());
        }
Esempio n. 15
0
        //DoWorkイベントハンドラ
        private void ProgressDialog_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bw = (BackgroundWorker)sender;

            bw.ReportProgress(0, "ファイル読み込み中(バーは動きません (^-^;)");
            using (FileFormat.MQOFile mqo = FileFormat.MQOFile.load(mqopath, true)) // 三角面化して読み込む
            {
                if (mqo == null)
                {
                    throw new Exception("読み込み失敗。おそらくmqoファイルの構文エラー。");
                }

                if (mqo.Object.Count == 0)
                {
                    throw new Exception("オブジェクトが空です。");
                }

                // pmx作成
                bld = PEStaticBuilder.Pmx;
                pmx = bld.Pmx();
                pmx.Clear();

                // モデル名は最初のオブジェクト名を利用する
                pmx.ModelInfo.ModelName = mqo.Object[0].Name;

                // 材質
                int mc = mqo.Material.Count;
                if (mc == 0)
                {
                    throw new Exception("材質がありません。少なくとも1つ材質が必要です。");
                }

                int cw = 100 / mc;
                int pc = 0;
                mqo.Material.ForEach(m =>
                {
                    bw.ReportProgress(cw * pc++, "材質の変換中");
                    IPXMaterial pm = bld.Material();
                    pm.Name        = m.Name;
                    pm.Diffuse.R   = (float)(m.Color.R * m.Diffuse);
                    pm.Diffuse.G   = (float)(m.Color.G * m.Diffuse);
                    pm.Diffuse.B   = (float)(m.Color.B * m.Diffuse);
                    pm.Diffuse.A   = (float)m.Color.A;
                    pm.Ambient.R   = (float)(m.Color.R * m.Ambient);
                    pm.Ambient.G   = (float)(m.Color.G * m.Ambient);
                    pm.Ambient.B   = (float)(m.Color.B * m.Ambient);
                    pm.Specular.R  = (float)(m.Color.R * m.Specular);
                    pm.Specular.G  = (float)(m.Color.G * m.Specular);
                    pm.Specular.B  = (float)(m.Color.B * m.Specular);
                    pm.Power       = (float)m.Power;
                    pm.Tex         = m.Tex;
                    pmx.Material.Add(pm);
                });

                // 各オブジェクトを処理
                // ただし、非表示オブジェクトはスキップ
                mc = mqo.Object.Count;
                cw = 100 / mc;
                bw.ReportProgress(0, "法線を計算中");
                Parallel.ForEach(mqo.Object, mObj =>
                {
                    if (mObj.Visible)
                    {
                        mObj.CalcNormals();
                    }
                    bw.ReportProgress(cw, 1);
                });

                // 先に頂点をすべて登録してから面を登録する
                // 頂点登録と面登録を交互に行うととんでもなく遅くなる
                mc = mqo.Material.Count;
                WorkFaceList   workfacelist   = new WorkFaceList(mc);
                WorkVertexDict workvertexdict = new WorkVertexDict();

                mc = mqo.Object.Count;
                cw = 100 / mc;
                pc = 0;
                for (int objID = 0; objID < mc; objID++)
                {
                    var mObj = mqo.Object[objID];
                    bw.ReportProgress(cw * pc++, String.Format("'{0}'の変換中", mObj.Name));
                    mObj.Face.ForEach(fc =>
                    {
                        if (!mObj.Visible)
                        {
                            return;                // 非表示オブジェクトは無視
                        }
                        // 材質割り当てのない面は材質0として処理
                        int matID = fc.MatID < 0 ? 0 : fc.MatID;

                        Func <int, int> get_vertex = i => workvertexdict.RegistVertex(objID, fc.VertexID[i], fc.UVID[i], fc.NormalID[i]);
                        workfacelist.AddFace(matID, get_vertex(0), get_vertex(1), get_vertex(2));
                    });
                }

                workvertexdict.RegistToPmx(pmx, bld, mqo, bw);
                workfacelist.RegistToPmx(pmx, bld, mqo, workvertexdict, bw);
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Parses the Wavefront Object file at the provided path and returns the operation's result.
        /// </summary>
        public static ImportResult Import(string path, IPXPmxBuilder builder, ImportSettings settings, IOProgress progress)
        {
            // Cancel the process if needed
            if (progress.CancellationToken.IsCancellationRequested)
            {
                progress.CancellationToken.ThrowIfCancellationRequested();
            }

            IPXPmx pmx = builder.Pmx();

            pmx.Clear();
            pmx.ModelInfo.ModelName = pmx.ModelInfo.ModelNameE = Path.GetFileNameWithoutExtension(path);
            pmx.ModelInfo.Comment   = pmx.ModelInfo.CommentE = "(Imported from OBJ by WPlugins.ObjIO)";
            StreamReader reader = null;

            System.Globalization.NumberFormatInfo fi = System.Globalization.NumberFormatInfo.InvariantInfo;
            System.Globalization.NumberStyles     ns = System.Globalization.NumberStyles.Float;

            // Model elements
            List <V3> vList  = new List <V3>();
            List <V2> vtList = new List <V2>();
            List <V3> vnList = new List <V3>();
            Dictionary <Tuple <int, int, int>, int> vertexDictionary = new Dictionary <Tuple <int, int, int>, int>();
            Dictionary <string, IPXMaterial>        materials        = new Dictionary <string, IPXMaterial>();
            IPXMaterial currentMaterial = null;

            // Values derived from settings
            V3 positionScale = new V3(settings.ScaleX, settings.ScaleY, settings.ScaleZ) * (settings.UseMetricUnits ? 0.254f : 0.1f);

            // Statistics
            int lineNumber = 0;

            try
            {
                reader = new StreamReader(path);
                char[] separator = { ' ' };
                while (!reader.EndOfStream)
                {
                    System.Threading.Thread.Sleep(2);

                    // Cancel the process if needed
                    if (progress.CancellationToken.IsCancellationRequested)
                    {
                        progress.CancellationToken.ThrowIfCancellationRequested();
                    }

                    string line = reader.ReadLine().Trim();
                    ++lineNumber;
                    ++progress.LineNumber;
                    progress.Report(IOProgress.Percent(reader.BaseStream.Position, reader.BaseStream.Length));

                    // Skip empty lines and comments
                    if (string.IsNullOrWhiteSpace(line) || line[0] == '#')
                    {
                        continue;
                    }

                    string[] split = line.Split(separator, StringSplitOptions.RemoveEmptyEntries);
                    switch (split[0])
                    {
                    // Vertex position
                    case "v":
                        try
                        {
                            float x = float.Parse(split[1], ns, fi);
                            float y = float.Parse(split[2], ns, fi);
                            float z = float.Parse(split[3], ns, fi);
                            vList.Add(new V3(x, y, -z));
                        }
                        catch (FormatException ex)
                        {
                            if (progress.ReportError(string.Format("A format exception has occured: {0}", line)))
                            {
                                return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                            }
                            vList.Add(new V3());
                        }
                        break;

                    // Vertex texture coordinates
                    case "vt":
                        try
                        {
                            // Technically this can be a V3 or any vector, but PMX only uses the first two elements for the main UV channel.
                            float x = float.Parse(split[1], ns, fi);
                            float y = float.Parse(split[2], ns, fi);
                            vtList.Add(new V2(x, -y));
                        }
                        catch (FormatException ex)
                        {
                            if (progress.ReportError(string.Format("A format exception has occured: {0}", line)))
                            {
                                return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                            }
                            vtList.Add(new V2());
                        }
                        break;

                    // Vertex normal
                    case "vn":
                        try
                        {
                            float x = float.Parse(split[1], ns, fi);
                            float y = float.Parse(split[2], ns, fi);
                            float z = float.Parse(split[3], ns, fi);
                            vnList.Add(new V3(x, y, -z));
                        }
                        catch (FormatException ex)
                        {
                            if (progress.ReportError(string.Format("A format exception has occured: {0}", line)))
                            {
                                return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                            }
                            vnList.Add(new V3());
                        }
                        break;

                    // Face definition
                    case "f":
                        if (currentMaterial == null)
                        {
                            progress.ReportWarning(string.Format("Encountered a face record when no active group was set.", lineNumber));
                            currentMaterial = builder.Material();
                        }

                        // Triangle
                        if (split.Length == 4)
                        {
                            int  v  = 0;
                            int  vt = 0;
                            int  vn = 0;
                            bool newVertex;

                            try
                            {
                                // Split each vertex assignment triple into its respective v/vt/vn indices.
                                GetVertexElements(split[1], out v, out vt, out vn);
                                // Based on the indices, determine if the vertex assignment is unique or already exists. A vertex is considered unique if one or more index is different, regardless of the vectors they represent.
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index1);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);       // The new vertex is added to the end of the list, making its index equal to the list's count before the addition.
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex1 = pmx.Vertex[index1];

                                // Repeat the same process for the rest of the vertex triples.
                                GetVertexElements(split[2], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index2);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex2 = pmx.Vertex[index2];

                                GetVertexElements(split[3], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index3);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex3 = pmx.Vertex[index3];

                                // Build the triangle and assign the vertices; use reverse order and negative normal vectors if the triangles are reversed.
                                IPXFace face = builder.Face();
                                if (settings.FlipFaces)
                                {
                                    vertex1.Normal *= -1;
                                    vertex2.Normal *= -1;
                                    vertex3.Normal *= -1;
                                    face.Vertex1    = vertex1;
                                    face.Vertex2    = vertex2;
                                    face.Vertex3    = vertex3;
                                }
                                else
                                {
                                    face.Vertex1 = vertex3;
                                    face.Vertex2 = vertex2;
                                    face.Vertex3 = vertex1;
                                }
                                currentMaterial.Faces.Add(face);
                            }
                            catch (Exception ex)
                            {
                                if (progress.ReportError(ex.ToString()))
                                {
                                    return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                                }
                            }
                        }
                        // Quad
                        else if (split.Length == 5)
                        {
                            int  v  = 0;
                            int  vt = 0;
                            int  vn = 0;
                            bool newVertex;
                            try
                            {
                                GetVertexElements(split[1], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index1);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex1 = pmx.Vertex[index1];

                                GetVertexElements(split[2], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index2);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex2 = pmx.Vertex[index2];

                                GetVertexElements(split[3], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index3);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex3 = pmx.Vertex[index3];

                                GetVertexElements(split[4], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index4);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex4 = pmx.Vertex[index4];

                                int     faceIndex1 = 0, faceIndex2 = 0;
                                IPXFace face = builder.Face();
                                if (settings.FlipFaces)
                                {
                                    face.Vertex3 = settings.TurnQuads ? vertex3 : vertex4;
                                    face.Vertex2 = vertex2;
                                    face.Vertex1 = vertex1;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex1 = currentMaterial.Faces.Count - 1;

                                    face         = builder.Face();
                                    face.Vertex1 = settings.TurnQuads ? vertex1 : vertex2;
                                    face.Vertex2 = vertex3;
                                    face.Vertex3 = vertex4;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex2 = currentMaterial.Faces.Count - 1;
                                }
                                else
                                {
                                    face.Vertex1 = settings.TurnQuads ? vertex3 : vertex4;
                                    face.Vertex2 = vertex2;
                                    face.Vertex3 = vertex1;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex1 = currentMaterial.Faces.Count - 1;

                                    face         = builder.Face();
                                    face.Vertex3 = settings.TurnQuads ? vertex1 : vertex2;
                                    face.Vertex2 = vertex3;
                                    face.Vertex1 = vertex4;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex2 = currentMaterial.Faces.Count - 1;
                                }

                                if (settings.SaveTrianglePairs)
                                {
                                    currentMaterial.Memo += string.Format("({0},{1})", faceIndex1, faceIndex2);
                                }
                            }
                            catch (Exception ex)
                            {
                                if (progress.ReportError(ex.ToString()))
                                {
                                    return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                                }
                            }
                        }
                        else
                        {
                            if (progress.ReportError(string.Format("The OBJ file contains a polygon with an invalid number of vertices. Currently only triangles and quads are supported. Line content: {0}", line)))
                            {
                                return(ImportResult.Fail(new InvalidOperationException("Invalid polygon"), progress.WarningCount, progress.ErrorCount));
                            }
                        }
                        break;

                    // Group assignment defines which PMX object (IPXMaterial instance) the subsequent faces belong to.
                    case "g":
                        currentMaterial      = builder.Material();
                        currentMaterial.Name = currentMaterial.NameE = line.Trim().Substring(2);
                        progress.Report("New object: " + currentMaterial.Name);
                        pmx.Material.Add(currentMaterial);
                        // Set default properties
                        currentMaterial.Diffuse = new V4(1, 1, 1, 1);
                        currentMaterial.Ambient = new V3(0.5f, 0.5f, 0.5f);
                        break;

                    // Material assignment defines which material template should be applied to the currently active PMX object. Any number of PMX objects can refer to a single material template.
                    case "usemtl":
                        if (currentMaterial == null)
                        {
                            progress.ReportWarning(string.Format("Encountered a material template reference when no active group was set.", lineNumber));
                            currentMaterial = builder.Material();
                        }
                        {
                            string      name = line.Trim().Substring(7);
                            IPXMaterial m    = currentMaterial;     // Active material
                            IPXMaterial t    = materials[name];     // Template material
                            m.Diffuse       = t.Diffuse;
                            m.Specular      = t.Specular;
                            m.Power         = t.Power;
                            m.Ambient       = t.Ambient;
                            m.Diffuse       = t.Diffuse;
                            m.SelfShadow    = t.SelfShadow;
                            m.SelfShadowMap = t.SelfShadowMap;
                            m.Shadow        = t.Shadow;
                            m.Tex           = t.Tex;
                            m.EdgeSize      = t.EdgeSize;
                            m.EdgeColor     = t.EdgeColor;
                            m.Edge          = t.Edge;
                        }
                        break;

                    // Material library, may occur multiple times in a model.
                    case "mtllib":
                        string materialLibraryName = line.Substring(7);
                        progress.Report("Importing materials from " + materialLibraryName);
                        // Try relative path
                        string materialLibraryPath = Path.Combine(Path.GetDirectoryName(path), materialLibraryName);
                        if (!File.Exists(materialLibraryPath))
                        {
                            // Try absolute path
                            materialLibraryPath = materialLibraryName;
                            if (!File.Exists(materialLibraryPath))
                            {
                                progress.ReportError(string.Format("Material library not found ({0}).", materialLibraryName));
                                break;
                            }
                        }
                        Dictionary <string, IPXMaterial> tempDict = ImportMaterials(materialLibraryPath, builder, settings, progress);
                        foreach (KeyValuePair <string, IPXMaterial> kvp in tempDict)
                        {
                            if (materials.ContainsKey(kvp.Key))
                            {
                                progress.ReportWarning(string.Format("Duplicate material {0} imported from {1} has been discarded.", kvp.Key, materialLibraryName));
                            }
                            else
                            {
                                materials.Add(kvp.Key, kvp.Value);
                            }
                        }
                        progress.Report(string.Format("Imported {0} materials from {1}.", tempDict.Count, materialLibraryName));
                        break;

                    // Smoothing group assignment (unused)
                    case "s":
                        break;

                    default:
                        break;
                    }
                }

                // Second pass for bone weights and transformations because I'm lazy
                IPXBone bone = null;
                if (settings.CreateBone != ImportSettings.CreateBoneMode.None)
                {
                    bone      = builder.Bone();
                    bone.Name = bone.NameE = pmx.ModelInfo.ModelName.Replace(' ', '_');
                }
                foreach (IPXVertex vertex in pmx.Vertex)
                {
                    // Bone
                    if (settings.CreateBone == ImportSettings.CreateBoneMode.Average)
                    {
                        bone.Position += vertex.Position;
                    }
                    vertex.Bone1   = settings.CreateBone != ImportSettings.CreateBoneMode.None ? bone : null;
                    vertex.Weight1 = 1.0f;
                    vertex.Bone2   = vertex.Bone3 = vertex.Bone4 = null;
                    vertex.Weight2 = vertex.Weight3 = vertex.Weight4 = 0;

                    // Axis swap
                    if (settings.SwapYZ)
                    {
                        float temp = vertex.Position.Y;
                        vertex.Position.Y = vertex.Position.Z;
                        vertex.Position.Z = temp;
                        temp            = vertex.Normal.Y;
                        vertex.Normal.Y = vertex.Normal.Z;
                        vertex.Normal.Z = temp;
                    }
                }
                if (settings.CreateBone == ImportSettings.CreateBoneMode.Average)
                {
                    bone.Position /= pmx.Vertex.Count;
                }
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if (progress.ReportError(ex.ToString()))
                {
                    return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                }
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                    reader = null;
                }
            }

            return(ImportResult.Success(pmx, progress.WarningCount, progress.ErrorCount));
        }
Esempio n. 17
0
        /// <summary>
        /// Executes the provided XmlDocument on the PMX object.
        /// </summary>
        public static RunnerResult Execute(XmlDocument doc, IPXPmx pmx, IPXPmxBuilder builder, RunnerProgress progress)
        {
            XmlElement root = doc.DocumentElement;

            progress.Report(0, "> Execution started.");

            // Begin processing
            // Only the first level of elements are interpreted as commands.
            XmlElement[] commands = root.ChildNodes.OfType <XmlElement>().ToArray();
            for (int i = 0; i < commands.Length; ++i)
            {
                try
                {
                    XmlElement node = commands[i];

                    // The meaningful content of each case constitutes a separate block to avoid mixing variables. Might be unnecessary, but right now I'm not feeling too hot and my output WILL be sloppy.
                    // Should review this code later.
                    switch (node.Name.ToLowerInvariant())
                    {
                    // Creates a new bone with the provided properties.
                    case "bone":
                    {
                        string  name = Math.Abs(Guid.NewGuid().GetHashCode()).ToString();
                        IPXBone bone = null;

                        // Get name and check for collision
                        if (node["name"] != null)
                        {
                            name = node["name"].InnerText;

                            IPXBone existing = pmx.Bone.Where(b => b.Name == name).FirstOrDefault();
                            if (existing != null)
                            {
                                // If there is a collision, refer to the collision attribute
                                switch (node["name"].GetAttribute("collision"))
                                {
                                // If the attribute is "update" or "replace", refer to the existing bone for the rest of the command.
                                case "replace":
                                case "update":
                                    bone = existing;
                                    break;

                                // If the attribute is "skip", don't do anything with the bone and skip the command.
                                case "skip":
                                    continue;

                                // If the attribute is not valid, create a new bone and ignore the old one.
                                default:
                                    bone      = builder.Bone();
                                    bone.Name = bone.NameE = name;
                                    break;
                                }
                            }
                            else
                            {
                                bone      = builder.Bone();
                                bone.Name = bone.NameE = name;
                            }
                        }
                        else
                        {
                            bone      = builder.Bone();
                            bone.Name = bone.NameE = name;
                        }

                        if (node["position"] != null)
                        {
                            bone.Position = node["position"].GetV3();
                        }
                        if (node["translation"] != null)
                        {
                            bone.IsTranslation = bool.TryParse(node["translation"].InnerText, out bool translation) ? translation : false;
                        }
                        if (node["parent"] != null)
                        {
                            bone.Parent = Selector.Bone.Selector(node["parent"], pmx).FirstOrDefault();
                        }
                        if (node["axis"] != null)
                        {
                            V3 v = node["axis"].GetV3();
                            v.Normalize();
                            bone.IsFixAxis = true;
                            bone.FixAxis   = v;
                        }
                        if (node["weight"] != null)
                        {
                            //IEnumerable<IPXVertex> vertices = Selector.Vertex.SelectorList(node["weight"].ChildNodes, pmx);
                            IEnumerable <IPXVertex> vertices = Selector.Vertex.SelectorNode(node["weight"], pmx);
                            foreach (IPXVertex v in vertices)
                            {
                                v.Bone1   = bone;
                                v.Weight1 = 1;
                                v.Bone2   = v.Bone3 = v.Bone4 = null;
                                v.Weight2 = v.Weight3 = v.Weight4 = 0;
                            }
                        }
                        pmx.Bone.Add(bone);
                        progress.Report(Percent(i + 1, commands.Length), string.Format("[bone] Added new bone {0}.", bone.Name));
                    }
                    break;

                    // Assigns the selected vertices to the selected bone using BDEF1.
                    case "weight":
                    {
                        IPXBone bone = null;
                        if (node["target"] != null)
                        {
                            bone = Selector.Bone.Selector(node["target"], pmx).FirstOrDefault();
                            if (bone == null)
                            {
                                progress.Report(Percent(i + 1, commands.Length), string.Format("[weight] Bone was not found.", node["target"].InnerText));
                                break;
                            }
                        }
                        else
                        {
                            progress.Report(Percent(i + 1, commands.Length), "[weight] Bone selector was not specified.");
                            break;
                        }

                        // Set vertex weights
                        if (node["select"] == null)
                        {
                            progress.Report(Percent(i + 1, commands.Length), "[weight] No vertices were selected.");
                            break;
                        }
                        IEnumerable <IPXVertex> vertices = Selector.Vertex.SelectorNode(node["select"], pmx);
                        foreach (IPXVertex v in vertices)
                        {
                            v.Bone1   = bone;
                            v.Weight1 = 1;
                            v.Bone2   = v.Bone3 = v.Bone4 = null;
                            v.Weight2 = v.Weight3 = v.Weight4 = 0;
                        }

                        progress.Report(Percent(i + 1, commands.Length), string.Format("[weight] Weighted {0} vertices to {1} ({2}).", vertices.Count(), bone.Name, bone.NameE));
                    }
                    break;

                    // Creates a new UV morph.
                    case "uvmorph":
                    {
                        // The morph's properties are defined in attributes.
                        IPXMorph morph = builder.Morph();
                        morph.Kind = MorphKind.UV;

                        // Set the UV channel
                        if (int.TryParse(node.GetAttribute("channel"), out int ch))
                        {
                            switch (ch)
                            {
                            case 1:
                                morph.Kind = MorphKind.UVA1;
                                break;

                            case 2:
                                morph.Kind = MorphKind.UVA2;
                                break;

                            case 3:
                                morph.Kind = MorphKind.UVA3;
                                break;

                            case 4:
                                morph.Kind = MorphKind.UVA4;
                                break;

                            default:
                                morph.Kind = MorphKind.UV;
                                break;
                            }
                        }

                        // Set the group panel
                        if (int.TryParse(node.GetAttribute("group"), out int group) && group <= 4 && group >= 0)
                        {
                            morph.Panel = group;
                        }
                        else
                        {
                            switch (node.GetAttribute("group").ToLowerInvariant())
                            {
                            case "hidden":
                            case "hide":
                            case "none":
                            case "0":
                                morph.Panel = 0;
                                break;

                            case "eyebrow":
                            case "eyebrows":
                            case "1":
                                morph.Panel = 1;
                                break;

                            case "eye":
                            case "eyes":
                            case "2":
                                morph.Panel = 2;
                                break;

                            case "mouth":
                            case "3":
                                morph.Panel = 3;
                                break;

                            default:
                                morph.Panel = 4;
                                break;
                            }
                        }

                        // Set the name, ignore collisions
                        if (node.HasAttribute("name"))
                        {
                            morph.Name = morph.NameE = node.GetAttribute("name");
                        }
                        else
                        {
                            morph.Name = morph.NameE = morph.GetHashCode().ToString();
                        }

                        // Each morph contains one or more steps. Each step has its own selectors and transforms, which are applied independently.
                        foreach (XmlElement step in node.ChildNodes.OfType <XmlElement>().Where(el => el.Name.ToLowerInvariant() == "step"))
                        {
                            // Skip steps that have no selectors
                            if (step["select"] == null)
                            {
                                continue;
                            }
                            // Select vertices
                            IEnumerable <IPXVertex> vertices = Selector.Vertex.SelectorNode(step["select"], pmx);
                            foreach (XmlElement e in step)
                            {
                                switch (e.Name.ToLowerInvariant())
                                {
                                case "pan":
                                case "translate":
                                {
                                    V2 v = e.GetV2();
                                    foreach (IPXVertex vertex in vertices)
                                    {
                                        IPXUVMorphOffset offset = builder.UVMorphOffset();
                                        offset.Vertex = vertex;
                                        offset.Offset = new V4(v.X, v.Y, 0, 0);
                                        morph.Offsets.Add(offset);
                                    }
                                }
                                break;

                                case "rotate":              // TODO: UV morph rotation
                                case "scale":               // TODO: UV morph scaling
                                default:
                                    break;
                                }
                            }
                        }

                        pmx.Morph.Add(morph);
                        progress.Report(Percent(i + 1, commands.Length), string.Format("[uvmorph] Created UV morph {0} with {1} offsets.", morph.Name, morph.Offsets.Count));
                    }
                    break;

                    // No particular functionality, testing only.
                    case "test":
                    {
                        //foreach (IPXMorph morph in pmx.Morph.Where(m => m.Kind == MorphKind.UV))
                        //{
                        //    foreach (IPXUVMorphOffset o in morph.Offsets)
                        //    {
                        //        _report(string.Format("{0:f2}, {1:f2}, {2:f2}, {3:f2}", o.Offset.X, o.Offset.Y, o.Offset.Z, o.Offset.W), -1);
                        //    }
                        //}
                    }
                    break;

                    // Sets up the selected vertices for use with AutoLuminous.
                    case "autoluminous":
                    {
                        if (node["select"] == null)
                        {
                            progress.Report(Percent(i + 1, commands.Length), "[weight] No vertices were selected.");
                            break;
                        }
                        IEnumerable <IPXVertex> vertices = Selector.Vertex.SelectorNode(node["select"], pmx);

                        // Set required values.
                        pmx.Header.UVACount = Math.Max(pmx.Header.UVACount, 3);

                        // UV1
                        int   texture        = 0;
                        int   hsv            = 0;
                        float flashFrequency = 0;
                        // UV2
                        V4 baseColor = new V4(0, 0, 0, 0);
                        // UV3
                        float texSubtract = 0;
                        float flashBias   = 0;
                        float push        = 0;

                        // Base emissive color
                        if (node["color"] != null)
                        {
                            baseColor = node["color"].GetV4();
                        }

                        // Base emissive power
                        if (node["power"] != null)
                        {
                            baseColor.W = node["power"].GetSingle();
                        }

                        if (node["texture"] != null)
                        {
                            int.TryParse(node["texture"].InnerText, System.Globalization.NumberStyles.Integer, System.Globalization.NumberFormatInfo.InvariantInfo, out texture);
                        }

                        if (node["colormode"] != null)
                        {
                            switch (node["colormode"].InnerText.ToLowerInvariant())
                            {
                            case "hsv":
                                hsv = 10;
                                break;

                            default:
                                hsv = 0;
                                break;
                            }
                        }

                        if (node["flash"] != null)
                        {
                            float.TryParse(node["flash"].GetAttribute("bias"), System.Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo, out flashBias);
                            flashFrequency = node["flash"].GetSingle();
                        }

                        if (node["subtract"] != null)
                        {
                            texSubtract = node["subtract"].GetSingle();
                        }

                        if (node["push"] != null)
                        {
                            push = node["push"].GetSingle();
                        }

                        foreach (IPXVertex v in vertices)
                        {
                            v.UVA1.X = 0.2f;            // Required value
                            v.UVA1.Y = 0.7f;            // Required value
                            v.UVA1.Z = flashFrequency;
                            v.UVA1.W = texture + hsv;

                            v.UVA2 = baseColor;

                            v.UVA3.X = texSubtract;
                            v.UVA3.Y = flashBias;
                            v.UVA3.Z = push;
                        }
                    }
                    break;

                    // Creates a vertex morph for AutoLuminous properties.
                    case "almorph":
                    {
                        if (node["select"] == null)
                        {
                            progress.Report(Percent(i + 1, commands.Length), "[weight] No vertices were selected.");
                            break;
                        }
                        HashSet <IPXVertex> vertices = new HashSet <IPXVertex>(Selector.Vertex.SelectorNode(node["select"], pmx));

                        V4 color = new V4();

                        if (node["color"] != null)
                        {
                            color = node["color"].GetV4();
                        }

                        // TODO: Implement the rest of the AL properties in ALMorph

                        IPXMorph morph = builder.Morph();
                        morph.Kind = MorphKind.UVA2;
                        if (node.HasAttribute("name"))
                        {
                            morph.Name = morph.NameE = node.GetAttribute("name");
                        }
                        else
                        {
                            morph.Name = morph.NameE = morph.GetHashCode().ToString();
                        }

                        foreach (IPXVertex v in vertices)
                        {
                            // Set required values in case the vertex isn't already AL-enabled
                            v.UVA1.X = 0.2f;
                            v.UVA1.Y = 0.7f;
                            // Create the offset
                            morph.Offsets.Add(builder.UVMorphOffset(v, color));
                        }
                    }
                    break;

                    // Sets environment variables.
                    case "settings":
                    {
                        foreach (XmlElement child in node.ChildNodes.OfType <XmlElement>())
                        {
                            switch (child.Name.ToLowerInvariant())
                            {
                            case "exception":
                                break;

                            case "regex":
                                bool regexCI = GlobalSettings.RegexCaseInsensitive;
                                bool.TryParse(child.GetAttributeCI("caseinsensitive"), out regexCI);
                                break;

                            case "colortype":
                                GlobalSettings.ColorIsFloat = child.InnerText.ToLowerInvariant() == "float";
                                break;

                            default:
                                break;
                            }
                        }
                    }
                    break;

                    // Displays a MessageBox with the provided content. Optionally perform certain actions based on user input.
                    case "mbox":
                    case "messagebox":
                    case "prompt":
                    {
                        if (int.TryParse(node.GetAttributeCI("skip"), out int skipNumber) && skipNumber > 0)
                        {
                            StringBuilder sb = new StringBuilder(string.Format("Would you like to skip the following {0} command(s)?\n", skipNumber));
                            for (int j = 1; j <= skipNumber; ++j)
                            {
                                sb.Append(commands[i + j].Name);
                            }
                            MessageBox.Show(sb.ToString(), "Prompt: skip", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                        }
                        else
                        {
                            MessageBox.Show(node.InnerText, "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                    break;

                    // Prints a line in the console.
                    case "echo":
                    case "print":
                        progress.Report(Percent(i + 1, commands.Length), node.InnerText);
                        break;

                    default:
                        progress.Report(Percent(i + 1, commands.Length), "Skipping unknown command " + node.Name);
                        break;
                    }
                }
                catch (Exception ex)
                {
                    if (GlobalSettings.Exception == GlobalSettings.ErrorHandling.Ask)
                    {
                        if (MessageBox.Show(string.Format("The following exception has occured:\n\n{0}\n\nWould you like to continue execution?", ex.ToString()), "Exception", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Error) == System.Windows.Forms.DialogResult.No)
                        {
                            return(RunnerResult.Fail);
                        }
                    }
                    else if (GlobalSettings.Exception == GlobalSettings.ErrorHandling.Abort)
                    {
                        return(RunnerResult.Fail);
                    }
                }
            }

            // If control has reached this point, the execution is considered successful.
            return(RunnerResult.Success);
        }
Esempio n. 18
0
        public void InitVariables(IPERunArgs args)
        {
            // 常用接続変数一括登録

            // ホスト配下
            host = args.Host;
            builder = host.Builder;
            bd = builder.SC;		// 短絡系ビルダ
            bdx = builder.Pmx;		// PMXビルダ
            connect = host.Connector;
            view = connect.View.PMDView;

            // PMX関連
            pmx = connect.Pmx.GetCurrentState();     // PMX取得
            header = pmx.Header;                  // header   :ヘッダ
            info = pmx.ModelInfo;              // info     :モデル情報
            vertex = pmx.Vertex;           // vertex   :頂点   | リスト
            material = pmx.Material;     // material :材質   | リスト
            bone = pmx.Bone;                 // bone     :ボーン | リスト
            morph = pmx.Morph;				// morph    :モーフ | リスト
            node = pmx.Node;					// node     :表示枠 | リスト
            body = pmx.Body;                 // body     :剛体   | リスト
            joint = pmx.Joint;              // joint    :Joint  | リスト
        }