Пример #1
0
        public static void AddObjectToSequence(ExportEntry newObject, ExportEntry sequenceExport, bool removeLinks = false)
        {
            ArrayProperty <ObjectProperty> seqObjs = sequenceExport.GetProperty <ArrayProperty <ObjectProperty> >("SequenceObjects") ?? new ArrayProperty <ObjectProperty>("SequenceObjects");

            seqObjs.Add(new ObjectProperty(newObject));
            sequenceExport.WriteProperty(seqObjs);

            PropertyCollection newObjectProps = newObject.GetProperties();

            newObjectProps.AddOrReplaceProp(new ObjectProperty(sequenceExport, "ParentSequence"));
            newObject.WriteProperties(newObjectProps);
            if (removeLinks)
            {
                RemoveAllLinks(newObject);
            }
            newObject.Parent = sequenceExport;
        }
Пример #2
0
        public static void CreateReachSpec(ExportEntry startNode, bool createTwoWay, ExportEntry destinationNode, string reachSpecClass, ReachSpecSize size, PropertyCollection externalGUIDProperties = null)
        {
            IMEPackage  Pcc = startNode.FileRef;
            ExportEntry reachSpectoClone = Pcc.Exports.FirstOrDefault(x => x.ClassName == "ReachSpec");

            if (externalGUIDProperties != null) //EXTERNAL
            {
                //external node

                //Debug.WriteLine("Num Exports: " + pcc.Exports.Count);
                if (reachSpectoClone != null)
                {
                    ExportEntry outgoingSpec = reachSpectoClone.Clone();
                    Pcc.addExport(outgoingSpec);

                    IEntry reachSpecClassImp = GetEntryOrAddImport(Pcc, reachSpecClass); //new class type.

                    outgoingSpec.idxClass      = reachSpecClassImp.UIndex;
                    outgoingSpec.idxObjectName = reachSpecClassImp.idxObjectName;

                    var            properties            = outgoingSpec.GetProperties();
                    ObjectProperty outgoingSpecStartProp = properties.GetProp <ObjectProperty>("Start");                                                                   //START
                    StructProperty outgoingEndStructProp = properties.GetProp <StructProperty>("End");                                                                     //Embeds END
                    ObjectProperty outgoingSpecEndProp   = outgoingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(outgoingSpec)); //END
                    outgoingSpecStartProp.Value = startNode.UIndex;
                    outgoingSpecEndProp.Value   = 0;
                    var endGuid = outgoingEndStructProp.GetProp <StructProperty>("Guid");
                    endGuid.Properties = externalGUIDProperties; //set the other guid values to our guid values

                    //Add to source node prop
                    ArrayProperty <ObjectProperty> PathList = startNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList");
                    PathList.Add(new ObjectProperty(outgoingSpec.UIndex));
                    startNode.WriteProperty(PathList);
                    outgoingSpec.WriteProperties(properties);


                    //Write Spec Size
                    SharedPathfinding.SetReachSpecSize(outgoingSpec, size.SpecRadius, size.SpecHeight);

                    //Reindex reachspecs.
                    SharedPathfinding.ReindexMatchingObjects(outgoingSpec);
                }
            }
            else
            {
                //Debug.WriteLine("Source Node: " + startNode.Index);

                //Debug.WriteLine("Num Exports: " + pcc.Exports.Count);
                //int outgoingSpec = pcc.ExportCount;
                //int incomingSpec = pcc.ExportCount + 1;


                if (reachSpectoClone != null)
                {
                    ExportEntry outgoingSpec = reachSpectoClone.Clone();
                    Pcc.addExport(outgoingSpec);
                    ExportEntry incomingSpec = null;
                    if (createTwoWay)
                    {
                        incomingSpec = reachSpectoClone.Clone();
                        Pcc.addExport(incomingSpec);
                    }

                    IEntry reachSpecClassImp = GetEntryOrAddImport(Pcc, reachSpecClass); //new class type.

                    outgoingSpec.idxClass      = reachSpecClassImp.UIndex;
                    outgoingSpec.idxObjectName = reachSpecClassImp.idxObjectName;

                    var outgoingSpecProperties = outgoingSpec.GetProperties();
                    if (reachSpecClass == "Engine.SlotToSlotReachSpec")
                    {
                        outgoingSpecProperties.Add(new ByteProperty(1, "SpecDirection")); //We might need to find a way to support this edit
                    }

                    //Debug.WriteLine("Outgoing UIndex: " + outgoingSpecExp.UIndex);

                    ObjectProperty outgoingSpecStartProp = outgoingSpecProperties.GetProp <ObjectProperty>("Start");                                                       //START
                    StructProperty outgoingEndStructProp = outgoingSpecProperties.GetProp <StructProperty>("End");                                                         //Embeds END
                    ObjectProperty outgoingSpecEndProp   = outgoingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(outgoingSpec)); //END
                    outgoingSpecStartProp.Value = startNode.UIndex;
                    outgoingSpecEndProp.Value   = destinationNode.UIndex;

                    //Add to source node prop
                    var PathList = startNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList");
                    PathList.Add(new ObjectProperty(outgoingSpec.UIndex));
                    startNode.WriteProperty(PathList);

                    //Write Spec Size
                    SetReachSpecSize(outgoingSpecProperties, size.SpecRadius, size.SpecHeight);
                    outgoingSpec.WriteProperties(outgoingSpecProperties);

                    if (createTwoWay)
                    {
                        incomingSpec.idxClass      = reachSpecClassImp.UIndex;
                        incomingSpec.idxObjectName = reachSpecClassImp.idxObjectName;
                        var incomingSpecProperties = incomingSpec.GetProperties();
                        if (reachSpecClass == "Engine.SlotToSlotReachSpec")
                        {
                            incomingSpecProperties.Add(new ByteProperty(2, "SpecDirection"));
                        }

                        ObjectProperty incomingSpecStartProp = incomingSpecProperties.GetProp <ObjectProperty>("Start");                                                       //START
                        StructProperty incomingEndStructProp = incomingSpecProperties.GetProp <StructProperty>("End");                                                         //Embeds END
                        ObjectProperty incomingSpecEndProp   = incomingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(incomingSpec)); //END

                        incomingSpecStartProp.Value = destinationNode.UIndex;                                                                                                  //Uindex
                        incomingSpecEndProp.Value   = startNode.UIndex;


                        //Add reachspec to destination node's path list (returning)
                        var DestPathList = destinationNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList");
                        DestPathList.Add(new ObjectProperty(incomingSpec.UIndex));
                        destinationNode.WriteProperty(DestPathList);

                        //destNode.WriteProperty(DestPathList);
                        SetReachSpecSize(incomingSpecProperties, size.SpecRadius, size.SpecHeight);

                        incomingSpec.WriteProperties(incomingSpecProperties);
                    }

                    //Reindex reachspecs.
                    SharedPathfinding.ReindexMatchingObjects(outgoingSpec);
                }
            }
        }
Пример #3
0
        public void Write2DAToExport()
        {
            using (var stream = new MemoryStream())
            {
                //Cell count
                if (IsIndexed)
                {
                    //Indexed ones seem to have 0 at start
                    stream.WriteBytes(BitConverter.GetBytes(0));
                }
                stream.WriteBytes(BitConverter.GetBytes(PopulatedCellCount));

                //Write cell data
                for (int rowindex = 0; rowindex < RowCount; rowindex++)
                {
                    for (int colindex = 0; colindex < ColumnCount; colindex++)
                    {
                        Bio2DACell cell = Cells[rowindex, colindex];
                        if (cell != null)
                        {
                            if (IsIndexed)
                            {
                                //write index
                                int index = (rowindex * ColumnCount) + colindex; //+1 because they are not zero based indexes since they are numerals
                                stream.WriteBytes(BitConverter.GetBytes(index));
                            }
                            stream.WriteByte((byte)cell.Type);
                            stream.WriteBytes(cell.Data);
                        }
                        else
                        {
                            if (IsIndexed)
                            {
                                //this is a blank cell. It is not present in the table.
                                continue;
                            }
                            else
                            {
                                Debug.WriteLine("THIS SHOULDN'T OCCUR!");
                                Debugger.Break();
                                throw new Exception("A non-indexed Bio2DA cannot have null cells.");
                            }
                        }
                    }
                }

                //Write Columns
                if (!IsIndexed)
                {
                    stream.WriteBytes(BitConverter.GetBytes(0)); //seems to be a 0 before column definitions
                }
                //Console.WriteLine("Columns defs start at " + stream.Position.ToString("X6"));
                stream.WriteBytes(BitConverter.GetBytes(ColumnCount));
                for (int colindex = 0; colindex < ColumnCount; colindex++)
                {
                    //Console.WriteLine("Writing column definition " + columnNames[colindex]);
                    int nameIndexForCol = export.FileRef.FindNameOrAdd(ColumnNames[colindex]);
                    stream.WriteBytes(BitConverter.GetBytes(nameIndexForCol));
                    stream.WriteBytes(BitConverter.GetBytes(0)); //second half of name reference in 2da is always zero since they're always indexed at 0
                    stream.WriteBytes(BitConverter.GetBytes(colindex));
                }

                int    propsEnd   = export.propsEnd();
                byte[] binarydata = stream.ToArray();

                //Todo: Rewrite properties here
                PropertyCollection props = new PropertyCollection();
                if (export.ClassName == "Bio2DA")
                {
                    var indicies = new ArrayProperty <NameProperty>(ArrayType.Name, "m_sRowLabel");
                    foreach (var rowname in RowNames)
                    {
                        indicies.Add(new NameProperty {
                            Value = rowname
                        });
                    }
                    props.Add(indicies);
                }
                else
                {
                    var indices = new ArrayProperty <IntProperty>(ArrayType.Int, "m_lstRowNumbers");
                    foreach (var rowname in RowNames)
                    {
                        indices.Add(new IntProperty(int.Parse(rowname)));
                    }
                    props.Add(indices);
                }

                MemoryStream propsStream = new MemoryStream();
                props.WriteTo(propsStream, export.FileRef);
                MemoryStream currentDataStream   = new MemoryStream(export.Data);
                byte[]       propertydata        = propsStream.ToArray();
                int          propertyStartOffset = export.GetPropertyStart();
                var          newExportData       = new byte[propertyStartOffset + propertydata.Length + binarydata.Length];
                Buffer.BlockCopy(export.Data, 0, newExportData, 0, propertyStartOffset);
                propertydata.CopyTo(newExportData, propertyStartOffset);
                binarydata.CopyTo(newExportData, propertyStartOffset + propertydata.Length);
                //Console.WriteLine("Old data size: " + export.Data.Length);
                //Console.WriteLine("NEw data size: " + newExportData.Length);

                //This assumes the input and output data sizes are the same. We should not assume this with new functionality
                //if (export.Data.Length != newExportData.Length)
                //{
                //    Debug.WriteLine("FILES ARE WRONG SIZE");
                //    Debugger.Break();
                //}
                export.Data = newExportData;
            }
        }
Пример #4
0
        public static StructProperty CreateAggGeom(ICollection <Vector3> vertexBuffer, ICollection <uint> indexBuffer, uint depth = 4, double conservationThreshold = 24, int maxVerts = 12)
        {
            double[] vertices    = vertexBuffer.SelectMany(vert => vert.ToArray().Select(v => (double)v)).ToArray();
            uint[]   indices     = indexBuffer.ToArray();
            var      convexElems = new ArrayProperty <StructProperty>("ConvexElems")
            {
                Reference = "KConvexElem"
            };

            #region Callback

            void DecompCallback(uint vertsLength, double[] verts, uint trisLength, int[] tris)
            {
                PropertyCollection props = new PropertyCollection();
                var convexElem           = new StructProperty("KConvexElem", props);

                convexElems.Add(convexElem);

                Box box = new Box();

                //VertexData
                var vertexData = new ArrayProperty <StructProperty>("VertexData")
                {
                    Reference = "Vector"
                };
                var vertexes = new Vector3[vertsLength / 3];

                for (int i = 0; i < vertsLength; i += 3)
                {
                    var vert = new Vector3((float)verts[i], (float)verts[i + 1], (float)verts[i + 2]);
                    vertexes[i / 3] = vert;
                    vertexData.Add(new StructProperty("Vector", true, new FloatProperty(vert.X, "X"), new FloatProperty(vert.Y, "Y"), new FloatProperty(vert.Z, "Z")));
                    box.Add(vert);
                }

                //PermutedVertexData
                int leftover           = vertexes.Length % 4;
                int numPlanes          = vertexes.Length / 4;
                var permutedVertexData = new ArrayProperty <StructProperty>("PermutedVertexData")
                {
                    Reference = "Plane"
                };

                for (int i = 0; i < numPlanes; i++)
                {
                    permutedVertexData.Add(new StructProperty("Plane", true, new FloatProperty(vertexes[i * 4 + 3].X, "W"), new FloatProperty(vertexes[i * 4 + 0].X, "X"), new FloatProperty(vertexes[i * 4 + 1].X, "Y"), new FloatProperty(vertexes[i * 4 + 2].X, "Z")));
                    permutedVertexData.Add(new StructProperty("Plane", true, new FloatProperty(vertexes[i * 4 + 3].Y, "W"), new FloatProperty(vertexes[i * 4 + 0].Y, "X"), new FloatProperty(vertexes[i * 4 + 1].Y, "Y"), new FloatProperty(vertexes[i * 4 + 2].Y, "Z")));
                    permutedVertexData.Add(new StructProperty("Plane", true, new FloatProperty(vertexes[i * 4 + 3].Z, "W"), new FloatProperty(vertexes[i * 4 + 0].Z, "X"), new FloatProperty(vertexes[i * 4 + 1].Z, "Y"), new FloatProperty(vertexes[i * 4 + 2].Z, "Z")));
                }

                if (leftover > 0)
                {
                    Vector3 vec1 = vertexes[numPlanes * 4], vec2 = vec1, vec3 = vec1, vec4 = vec1;
                    switch (leftover)
                    {
                    case 3:
                        vec3 = vertexes[numPlanes * 4 + 2];
                        goto case 2;     //fallthrough!

                    case 2:
                        vec2 = vertexes[numPlanes * 4 + 1];
                        break;
                    }

                    permutedVertexData.Add(new StructProperty("Plane", true, new FloatProperty(vec1.X, "W"), new FloatProperty(vec2.X, "X"), new FloatProperty(vec3.X, "Y"), new FloatProperty(vec4.X, "Z")));
                    permutedVertexData.Add(new StructProperty("Plane", true, new FloatProperty(vec1.Y, "W"), new FloatProperty(vec2.Y, "X"), new FloatProperty(vec3.Y, "Y"), new FloatProperty(vec4.Y, "Z")));
                    permutedVertexData.Add(new StructProperty("Plane", true, new FloatProperty(vec1.Z, "W"), new FloatProperty(vec2.Z, "X"), new FloatProperty(vec3.Z, "Y"), new FloatProperty(vec4.Z, "Z")));
                }

                //FaceTriData
                var faceTriData = new ArrayProperty <IntProperty>("FaceTriData");

                faceTriData.AddRange(tris.Select(idx => new IntProperty(idx)));


                var allEdges      = new List <(int edge0, int edge1)>();
                var edgeDirs      = new List <Vector3>();
                var allNormals    = new List <Vector3>();
                var uniqueNormals = new List <Vector3>();
                var planes        = new List <Plane>();

                for (int i = 0; i < trisLength; i += 3)
                {
                    int idx0 = tris[i], idx1 = tris[i + 1], idx2 = tris[i + 2];

                    if (!allEdges.Contains((idx0, idx1)))
                    {
                        allEdges.Add((idx0, idx1));
                    }
                    if (!allEdges.Contains((idx1, idx2)))
                    {
                        allEdges.Add((idx1, idx2));
                    }
                    if (!allEdges.Contains((idx2, idx0)))
                    {
                        allEdges.Add((idx2, idx0));
                    }

                    Vector3 vert0 = vertexes[idx0];
                    Vector3 vert1 = vertexes[idx1];
                    Vector3 vert2 = vertexes[idx2];

                    Vector3 normal = Vector3.Normalize(Vector3.Cross(vert2 - vert0, vert1 - vert0));
                    allNormals.Add(normal);
                    AddVec(normal, uniqueNormals);
                    AddPlane(new Plane(vert0, normal));
                }

                //FacePlaneData
                var facePlaneData = new ArrayProperty <StructProperty>("FacePlaneData")
                {
                    Reference = "Plane"
                };

                foreach (Plane plane in planes)
                {
                    facePlaneData.Add(new StructProperty("Plane", true, new FloatProperty(plane.D, "W"), new FloatProperty(plane.Normal.X, "X"), new FloatProperty(plane.Normal.Y, "Y"), new FloatProperty(plane.Normal.Z, "Z")));
                }

                //FaceNormalDirections
                var faceNormalDirections = new ArrayProperty <StructProperty>("FaceNormalDirections")
                {
                    Reference = "Vector"
                };

                foreach (Vector3 normal in uniqueNormals)
                {
                    faceNormalDirections.Add(new StructProperty("Vector", true, new FloatProperty(normal.X, "X"), new FloatProperty(normal.Y, "Y"), new FloatProperty(normal.Z, "Z")));
                }


                //EdgeDirections
                var edgeDirections = new ArrayProperty <StructProperty>("EdgeDirections")
                {
                    Reference = "Vector"
                };

                foreach ((int edge0, int edge1) in allEdges)
                {
                    int triIdx0 = -1, triIdx1 = -1;
                    for (int i = 0; i < trisLength; i += 3)
                    {
                        int idx0 = tris[i], idx1 = tris[i + 1], idx2 = tris[i + 2];
                        if (idx0 == edge0 && idx1 == edge1 || idx0 == edge0 && idx2 == edge1 || idx1 == edge0 && idx0 == edge1 || idx1 == edge0 && idx2 == edge1 || idx2 == edge0 && idx0 == edge1 || idx2 == edge0 && idx1 == edge1)
                        {
                            if (triIdx0 == -1)
                            {
                                triIdx0 = i / 3;
                            }
                            else if (triIdx1 == -1)
                            {
                                triIdx1 = i / 3;
                            }
                        }
                    }

                    if (triIdx0 != -1 && triIdx1 != -1 && Vector3.Dot(allNormals[triIdx0], allNormals[triIdx1]) < 1f - 0.0003)
                    {
                        AddVec(Vector3.Normalize(vertexes[edge0] - vertexes[edge1]), edgeDirs);
                    }
                }

                foreach (Vector3 edgeDir in edgeDirs)
                {
                    edgeDirections.Add(new StructProperty("Vector", true, new FloatProperty(edgeDir.X, "X"), new FloatProperty(edgeDir.Y, "Y"), new FloatProperty(edgeDir.Z, "Z")));
                }

                //ElemBox
                var elemBox = new StructProperty("Box", true,
                                                 new StructProperty("Vector", true,
                                                                    new FloatProperty(box.Min.X, "X"),
                                                                    new FloatProperty(box.Min.Y, "Y"),
                                                                    new FloatProperty(box.Min.Z, "Z"))
                {
                    Name = "Min"
                },
                                                 new StructProperty("Vector", true,
                                                                    new FloatProperty(box.Max.X, "X"),
                                                                    new FloatProperty(box.Max.Y, "Y"),
                                                                    new FloatProperty(box.Max.Z, "Z"))
                {
                    Name = "Max"
                },
                                                 new ByteProperty(box.IsValid, "IsValid")
                                                 )
                {
                    Name = "ElemBox"
                };


                props.Add(vertexData);
                props.Add(permutedVertexData);
                props.Add(faceTriData);
                props.Add(edgeDirections);
                props.Add(faceNormalDirections);
                props.Add(facePlaneData);
                props.Add(elemBox);
                props.Add(new NoneProperty());

                void AddVec(Vector3 vec, List <Vector3> vecs)
                {
                    foreach (Vector3 uniqueVec in vecs)
                    {
                        float dot = Math.Abs(Vector3.Dot(uniqueVec, vec));
                        if (Math.Abs(dot - 1) < 0.0003)
                        {
                            return;
                        }
                    }

                    vecs.Add(vec);
                }

                void AddPlane(Plane plane)
                {
                    foreach (Plane uniquePlane in planes)
                    {
                        float dot = Vector3.Dot(uniquePlane.Normal, plane.Normal);
                        if (Math.Abs(dot - 1) < 0.0003 && Math.Abs(uniquePlane.D - plane.D) < 0.1)
                        {
                            return;
                        }
                    }

                    planes.Add(plane);
                }
            }

            #endregion

            CreateConvexHull(vertexBuffer.Count, vertices, indices.Length / 3, indices, depth, conservationThreshold, maxVerts, DecompCallback);

            return(new StructProperty("KAggregateGeom", new PropertyCollection
            {
                convexElems,
                new NoneProperty()
            }, "AggGeom"));
        }