Ejemplo n.º 1
0
        public void GetGMTOffset_PST()
        {
            var offset = DataTypeUtil.GetGMTOffset(TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"),
                                                   new DateTime(2014, 12, 1));

            Assert.Equal(-800, offset);
        }
Ejemplo n.º 2
0
        /// <summary> This method takes in integer values for the year and month and day
        /// and performs validations, it then sets the value in the object
        /// formatted as an HL7 date value with year and month and day precision (YYYYMMDD).
        /// </summary>
        public virtual void setYearMonthDayPrecision(int yr, int mnth, int dy)
        {
            try
            {
                //ensure that the year field is four digits long
                if (Convert.ToString(yr).Length != 4)
                {
                    String            msg = "The input year value must be four digits long";
                    DataTypeException e   = new DataTypeException(msg);
                    throw e;
                }

                GregorianCalendar cal = new GregorianCalendar();

                //validate the input month/day combination
                new DateTime(yr, mnth, dy, cal);
                year          = yr;
                month         = mnth;
                day           = dy;
                value_Renamed = Convert.ToString(yr) + DataTypeUtil.preAppendZeroes(mnth, 2) + DataTypeUtil.preAppendZeroes(dy, 2);
            }
            catch (DataTypeException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new DataTypeException("An unexpected exception ocurred", e);
            }
        }
Ejemplo n.º 3
0
        /// <summary> This method takes in integer values for the year and month and performs validations,
        /// it then sets the value field formatted as an HL7 date
        /// value with year and month precision (YYYYMM).
        /// Note: The first month = 1 = January.
        /// </summary>
        public virtual void SetYearMonthPrecision(int yr, int mnth)
        {
            try
            {
                // ensure that the year field is four digits long
                if (Convert.ToString(yr).Length != 4)
                {
                    var msg = "The input year value must be four digits long";
                    var e   = new DataTypeException(msg);
                    throw e;
                }

                var cal = new GregorianCalendar();

                // validate the input month
                new DateTime(yr, mnth, 1, cal);
                Year         = yr;
                Month        = mnth;
                Day          = 0;
                valueRenamed = Convert.ToString(yr) + DataTypeUtil.PreAppendZeroes(mnth, 2);
            }
            catch (DataTypeException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new DataTypeException("An unexpected exception occurred", e);
            }
        }
Ejemplo n.º 4
0
        public virtual string GetXmlColumnValue(IColumn col, DataRow row)
        {
            Throw.If(col, "col").IsNull();
            Throw.If(row, "row").IsNull();

            if (col.IsNullable && row[col.Name] == DBNull.Value)
            {
                return(null);
            }
            else if (DataTypeUtil.IsNumeric(col))
            {
                return(row[col.Name].ToString());
            }
            else if (DataTypeUtil.IsDateTime(col))
            {
                DateTime dt = (DateTime)row[col.Name];
                return(dt.ToString("o"));    // ISO 8601
            }
            else if (DataTypeUtil.IsBoolean(col))
            {
                if ((bool)row[col.Name])
                {
                    return("1");
                }
                else
                {
                    return("0");
                }
            }
            else
            {
                // wrap in CDATA section?
                return(string.Format("{0}", row[col.Name]));
            }
        }
Ejemplo n.º 5
0
        } //end constructor

        /// <summary> This method takes in integer values for the hour and minute and performs validations,
        /// it then sets the value field formatted as an HL7 time value
        /// with hour and minute precision (HHMM).
        /// </summary>
        public virtual void setHourMinutePrecision(int hr, int min)
        {
            try
            {
                this.HourPrecision = hr;
                //validate input minute value
                if ((min < 0) || (min > 59))
                {
                    System.String     msg = "The minute value of the TM datatype must be >=0 and <=59";
                    DataTypeException e   = new DataTypeException(msg);
                    throw e;
                } //end if
                minute        = min;
                second        = 0;
                fractionOfSec = 0;
                offSet        = 0;
                //Here the offset is not defined, we should omit showing it in the
                //return value from the getValue() method
                omitOffsetFg  = 'y';
                value_Renamed = value_Renamed + DataTypeUtil.preAppendZeroes(min, 2);
            }
            //end try
            catch (DataTypeException e)
            {
                throw e;
            }
            //end catch
            catch (System.Exception e)
            {
                throw new DataTypeException(e.Message);
            } //end catch
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Gets the SQL value ready for insert for this row and column.
        /// </summary>
        /// <param name="col">The column to retrieve the value.</param>
        /// <param name="row">The current row.</param>
        /// <returns>The escaped value.</returns>
        public virtual string GetSqlColumnValue(IColumn col, DataRow row)
        {
            Throw.If(col, "col").IsNull();
            Throw.If(row, "row").IsNull();

            if (col.IsNullable && row[col.Name] == DBNull.Value)
            {
                return("NULL");
            }
            else if (DataTypeUtil.IsNumeric(col))
            {
                return(row[col.Name].ToString());
            }
            else if (DataTypeUtil.IsBoolean(col))
            {
                if ((bool)row[col.Name])
                {
                    return("1");
                }
                else
                {
                    return("0");
                }
            }
            else
            {
                return(string.Format("'{0}'", row[col.Name].ToString().Replace("'", "''")));
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// This method takes in integer values for the hour and minute and performs validations,
        /// it then sets the value field formatted as an HL7 time value
        /// with hour and minute precision (HHMM).
        /// </summary>
        public virtual void SetHourMinutePrecision(int hr, int min)
        {
            try
            {
                HourPrecision = hr;

                // validate input minute value
                if ((min < 0) || (min > 59))
                {
                    var msg = "The minute value of the TM datatype must be >=0 and <=59";
                    var e   = new DataTypeException(msg);
                    throw e;
                }

                Minute      = min;
                Second      = 0;
                FractSecond = 0;
                GMTOffset   = 0;

                // Here the offset is not defined, we should omit showing it in the
                // return value from the getValue() method
                omitOffsetFg = 'y';
                valueRenamed = valueRenamed + DataTypeUtil.PreAppendZeroes(min, 2);
            }
            catch (DataTypeException e)
            {
                // TODO: this will remove the stack trace - is that correct?
                throw e;
            }
            catch (Exception e)
            {
                throw new DataTypeException(e.Message);
            }
        }
Ejemplo n.º 8
0
        public void GetGMTOffset_For_TimeZone_With_Non_Zero_Minutes()
        {
            var offset = DataTypeUtil.GetGMTOffset(TimeZoneInfo.FindSystemTimeZoneById("Myanmar Standard Time"),
                                                   new DateTime(2014, 11, 1));

            Assert.Equal(630, offset);
        }
Ejemplo n.º 9
0
        public void GetGMTOffset_For_TimeZone_With_Offset_Greater_Than_12()
        {
            var offset = DataTypeUtil.GetGMTOffset(TimeZoneInfo.FindSystemTimeZoneById("Line Islands Standard Time"),
                                                   new DateTime(2014, 11, 1));

            Assert.Equal(1400, offset);
        }
Ejemplo n.º 10
0
 /// <summary> This method takes in integer values for the year and month and day
 /// and performs validations, it then sets the value in the object
 /// formatted as an HL7 date value with year and month and day precision (YYYYMMDD).
 /// </summary>
 public virtual void setYearMonthDayPrecision(int yr, int mnth, int dy)
 {
     try
     {
         System.Globalization.GregorianCalendar cal = new System.Globalization.GregorianCalendar();
         SupportClass.CalendarManager.manager.Clear(cal);
         //ensure that the year field is four digits long
         if (System.Convert.ToString(yr).Length != 4)
         {
             System.String     msg = "The input year value must be four digits long";
             DataTypeException e   = new DataTypeException(msg);
             throw e;
         }
         //validate the input month/day combination
         SupportClass.CalendarManager.manager.Set(cal, yr, (mnth - 1), dy);
         SupportClass.CalendarManager.manager.GetDateTime(cal); //for error detection
         year          = yr;
         month         = mnth;
         day           = dy;
         value_Renamed = System.Convert.ToString(yr) + DataTypeUtil.preAppendZeroes(mnth, 2) + DataTypeUtil.preAppendZeroes(dy, 2);
     }
     catch (DataTypeException e)
     {
         throw e;
     }
     catch (System.Exception e)
     {
         throw new DataTypeException("An unexpected exception ocurred", e);
     }
 }
Ejemplo n.º 11
0
        public void GetGMTOffset_PDT()
        {
            var timeZone = GetAppropriateTimeZoneId("Pacific Standard Time");

            var offset = DataTypeUtil.GetGMTOffset(
                TimeZoneInfo.FindSystemTimeZoneById(timeZone),
                new DateTime(2014, 10, 1));

            Assert.AreEqual(-700, offset);
        }
        public void VirtualDataTypeNameCallsAttributeGetDataTypeName()
        {
            // Arrange
            DataTypeAttribute derivedAttr      = new DerivedDataTypeAttribute(DataType.Html);
            string            expectedTypeName = derivedAttr.GetDataTypeName();

            // Act
            string actualTypeName = DataTypeUtil.ToDataTypeName(derivedAttr);

            // Assert
            Assert.Equal(expectedTypeName, actualTypeName);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// This method takes in integer values for the hour, minute, seconds, and fractional seconds
        /// (going to the ten thousandths precision).
        /// The method performs validations and then sets the value field formatted as an
        /// HL7 time value with a precision that starts from the hour and goes down to the ten thousandths
        /// of a second (HHMMSS.SSSS).
        /// Note: all of the precisions from tenths down to ten thousandths of a
        /// second are optional. If the precision goes below ten thousandths of a second then the second
        /// value will be rounded to the nearest ten thousandths of a second.
        /// </summary>
        public virtual void SetHourMinSecondPrecision(int hr, int min, float sec)
        {
            try
            {
                SetHourMinutePrecision(hr, min);

                // multiply the seconds input value by 10000 and round the result
                // then divide the number by ten thousand and store it back.
                // This will round the fractional seconds to the nearest ten thousandths
                var secMultRound = (int)Math.Round((double)(10000F * sec));
                sec = secMultRound / 10000F;

                // Now store the second and fractional component
                Second = (int)Math.Floor(sec);

                // validate input seconds value
                if ((Second < 0) || (Second >= 60))
                {
                    var msg = "The (rounded) second value of the TM datatype must be >=0 and <60";
                    var e   = new DataTypeException(msg);
                    throw e;
                }

                var fractionOfSecInt = (int)(secMultRound - (Second * 10000));
                FractSecond = fractionOfSecInt / 10000F;
                var fractString = string.Empty;

                // Now convert the fractionOfSec field to a string without the leading zero
                if (FractSecond != 0.0F)
                {
                    fractString = FractSecond.ToString().Substring(1);
                }

                // Now update the value field
                GMTOffset = 0;

                // Here the offset is not defined, we should omit showing it in the
                // return value from the getValue() method
                omitOffsetFg = 'y';
                valueRenamed = valueRenamed + DataTypeUtil.PreAppendZeroes(Second, 2) + fractString;
            }
            catch (DataTypeException e)
            {
                // TODO: this will remove the stack trace - is that correct?
                throw e;
            }
            catch (Exception e)
            {
                throw new DataTypeException("An unexpected exception occurred", e);
            }
        }
        public void CustomDataTypeNameCallsAttributeGetDataTypeName()
        {
            // Arrange
            Func <DataTypeAttribute, Boolean> isDataTypeAttribute = t => (t as DataTypeAttribute) != null;

            Mock <DataTypeAttribute> customDataType = new Mock <DataTypeAttribute>(DataType.Custom);

            customDataType.Setup(c => c.GetDataTypeName()).Returns("CustomTypeName").Verifiable();

            // Act
            string actualTypeName = DataTypeUtil.ToDataTypeName(customDataType.Object);

            // Assert
            customDataType.Verify(c => c.GetDataTypeName(), Times.Once());
            Assert.Equal("CustomTypeName", actualTypeName);
        }
Ejemplo n.º 15
0
 /// <summary> This method takes in integer values for the hour, minute, seconds, and fractional seconds
 /// (going to the tenthousandths precision).
 /// The method performs validations and then sets the value field formatted as an
 /// HL7 time value with a precision that starts from the hour and goes down to the tenthousandths
 /// of a second (HHMMSS.SSSS).
 /// Note: all of the precisions from tenths down to tenthousandths of a
 /// second are optional. If the precision goes below tenthousandths of a second then the second
 /// value will be rounded to the nearest tenthousandths of a second.
 /// </summary>
 public virtual void setHourMinSecondPrecision(int hr, int min, float sec)
 {
     try
     {
         this.setHourMinutePrecision(hr, min);
         //multiply the seconds input value by 10000 and round the result
         //then divide the number by tenthousand and store it back.
         //This will round the fractional seconds to the nearest tenthousandths
         int secMultRound = (int)System.Math.Round((double)(10000F * sec));
         sec = secMultRound / 10000F;
         //Now store the second and fractional component
         second = (int)System.Math.Floor(sec);
         //validate input seconds value
         if ((second < 0) || (second >= 60))
         {
             System.String     msg = "The (rounded) second value of the TM datatype must be >=0 and <60";
             DataTypeException e   = new DataTypeException(msg);
             throw e;
         } //end if
         int fractionOfSecInt = (int)(secMultRound - (second * 10000));
         fractionOfSec = fractionOfSecInt / 10000F;
         System.String fractString = "";
         //Now convert the fractionOfSec field to a string without the leading zero
         if (fractionOfSec != 0.0F)
         {
             fractString = (fractionOfSec.ToString()).Substring(1);
         } //end if
         //Now update the value field
         offSet = 0;
         //Here the offset is not defined, we should omit showing it in the
         //return value from the getValue() method
         omitOffsetFg  = 'y';
         value_Renamed = value_Renamed + DataTypeUtil.preAppendZeroes(second, 2) + fractString;
     }
     //end try
     catch (DataTypeException e)
     {
         throw e;
     }
     //end catch
     catch (System.Exception e)
     {
         throw new DataTypeException("An unexpected exception ocurred", e);
     } //end catch
 }
Ejemplo n.º 16
0
        /// <summary>
        /// Generates a SQL Server XML schema for the given table and XML data.
        /// </summary>
        /// <remarks>
        /// Its assumed that the XML elements (columns) have the same name as
        /// the table columns.
        /// </remarks>
        /// <param name="table">The table associated with the XML.</param>
        /// <returns>The XSD contents as a string.</returns>
        public virtual XmlSchema GenerateXsd(ITable table)
        {
            XmlSchema xsd = new XmlSchema();

            xsd.Namespaces.Add("sql", MappingSchemaNS);

            XmlSchemaElement tableElement = new XmlSchemaElement();

            tableElement.Name = table.Name;
            xsd.Items.Add(tableElement);

            XmlSchemaComplexType complexType = new XmlSchemaComplexType();

            tableElement.SchemaType = complexType;

            XmlSchemaSequence seq = new XmlSchemaSequence();

            complexType.Particle = seq;

            foreach (IColumn col in table.Columns)
            {
                string xmlDataType = DataTypeUtil.ToXmlDataType(col);

                XmlSchemaElement colElem = new XmlSchemaElement();
                colElem.Name           = col.Name;
                colElem.MaxOccurs      = 1;
                colElem.MinOccurs      = 1;
                colElem.SchemaTypeName = new XmlQualifiedName(xmlDataType, XmlDataTypeNS);

                XmlDocument  xml          = new XmlDocument();
                XmlAttribute sqlFieldAttr = xml.CreateAttribute("sql", "field", MappingSchemaNS);
                sqlFieldAttr.Value = col.Name;

                XmlAttribute sqlDataTypeAttr = xml.CreateAttribute("sql", "datatype", MappingSchemaNS);
                sqlDataTypeAttr.Value = col.DataTypeNameComplete;

                XmlAttribute[] sqlAttrs = { sqlFieldAttr, sqlDataTypeAttr };
                colElem.UnhandledAttributes = sqlAttrs;

                seq.Items.Add(colElem);
            }

            return(xsd);
        }
        public void DataTypeAttributeDoesNotCallAttributeGetDataTypeName()
        {
            // Arrange
            Func <DataTypeAttribute, Boolean> isDataTypeAttribute = t => (t as DataTypeAttribute) != null;

            foreach (DataType dataTypeValue in Enum.GetValues(typeof(DataType)))
            {
                if (dataTypeValue != DataType.Custom)
                {
                    Mock <DataTypeAttribute> dataType = new Mock <DataTypeAttribute>(dataTypeValue);

                    // Act
                    string actualTypeName = DataTypeUtil.ToDataTypeName(dataType.Object, dta => dta as DataTypeAttribute != null);

                    // Assert
                    Assert.Equal(dataTypeValue.ToString(), actualTypeName);
                    dataType.Verify(dt => dt.GetDataTypeName(), Times.Never());
                }
            }
        }
Ejemplo n.º 18
0
 public virtual bool Matches(Table table, string columnName, object value1, object
                             value2)
 {
     if (!DataTypeUtil.IsTextual(table.GetColumn(columnName).GetDataType()))
     {
         // use simple equality
         return(SimpleColumnMatcher.INSTANCE.Matches(table, columnName, value1, value2));
     }
     // convert both values to Strings and compare case-insensitively
     try
     {
         CharSequence cs1 = Column.ToCharSequence(value1);
         CharSequence cs2 = Column.ToCharSequence(value2);
         return((cs1 == cs2) || ((cs1 != null) && (cs2 != null) && Sharpen.Runtime.EqualsIgnoreCase
                                     (cs1.ToString(), cs2.ToString())));
     }
     catch (IOException e)
     {
         throw new InvalidOperationException("Could not read column " + columnName + " value"
                                             , e);
     }
 }
Ejemplo n.º 19
0
            /// <returns>
            /// the PropertyMap created from the values parsed from the given
            /// data chunk combined with the given property names
            /// </returns>
            /// <exception cref="System.IO.IOException"></exception>
            private PropertyMap ReadPropertyValues(ByteBuffer bbBlock, IList <string> propNames
                                                   , short blockType)
            {
                string mapName = DEFAULT_NAME;

                if (bbBlock.HasRemaining())
                {
                    // read the map name, if any
                    int nameBlockLen = bbBlock.GetInt();
                    int endPos       = bbBlock.Position() + nameBlockLen - 4;
                    if (nameBlockLen > 6)
                    {
                        mapName = ReadPropName(bbBlock);
                    }
                    bbBlock.Position(endPos);
                }
                PropertyMap map = new PropertyMap(mapName, blockType);

                // read the values
                while (bbBlock.HasRemaining())
                {
                    int      valLen   = bbBlock.GetShort();
                    int      endPos   = bbBlock.Position() + valLen - 2;
                    byte     flag     = bbBlock.Get();
                    DataType dataType = DataTypeUtil.FromByte(bbBlock.Get());
                    int      nameIdx  = bbBlock.GetShort();
                    int      dataSize = bbBlock.GetShort();
                    string   propName = propNames[nameIdx];
                    PropertyMaps.Handler.PropColumn col = GetColumn(dataType, propName, dataSize);
                    byte[] data = new byte[dataSize];
                    bbBlock.Get(data);
                    object value = col.Read(data);
                    map.Put(propName, dataType, flag, value);
                    bbBlock.Position(endPos);
                }
                return(map);
            }
Ejemplo n.º 20
0
        // TODO: Split these out into separate classes
        // TODO: Reading from the file here is gross
        public IModel LoadModel(CmbModelFileBundle modelFileBundle)
        {
            var cmbFile   = modelFileBundle.CmbFile;
            var csabFiles = modelFileBundle.CsabFiles;
            var ctxbFiles = modelFileBundle.CtxbFiles;
            var shpaFiles = modelFileBundle.ShpaFiles;

            var fps = 30;

            using var r =
                      new EndianBinaryReader(cmbFile.Impl.OpenRead(),
                                             Endianness.LittleEndian);

            var cmb = new Cmb(r);

            r.Position = 0;

            var filesAndCsabs =
                csabFiles?.Select(csabFile => {
                var csab =
                    csabFile.Impl.ReadNew <Csab>(Endianness.LittleEndian);
                return(csabFile, csab);
            })
                .ToList() ??
                new List <(IFileHierarchyFile shpaFile, Csab csab)>();

            var filesAndCtxbs =
                ctxbFiles?.Select(ctxbFile => {
                var ctxb =
                    ctxbFile.Impl.ReadNew <Ctxb>(Endianness.LittleEndian);
                return(ctxbFile, ctxb);
            })
                .ToList() ??
                new List <(IFileHierarchyFile shpaFile, Ctxb ctxb)>();

            var filesAndShpas =
                shpaFiles?.Select(shpaFile => {
                var shpa =
                    shpaFile.Impl.ReadNew <Shpa>(Endianness.LittleEndian);
                return(shpaFile, shpa);
            })
                .ToList() ??
                new List <(IFileHierarchyFile shpaFile, Shpa shpa)>();

            var finModel = new ModelImpl();
            var finSkin  = finModel.Skin;

            // Adds bones
            var finBones  = new IBone[cmb.skl.bones.Length];
            var boneQueue = new Queue <(Bone, IBone?)>();

            boneQueue.Enqueue((cmb.skl.bones[0], null));
            while (boneQueue.Count > 0)
            {
                var(cmbBone, finBoneParent) = boneQueue.Dequeue();

                var translation = cmbBone.translation;
                var radians     = cmbBone.rotation;
                var scale       = cmbBone.scale;

                var finBone =
                    (finBoneParent ?? finModel.Skeleton.Root)
                    .AddChild(translation.X, translation.Y, translation.Z)
                    .SetLocalRotationRadians(radians.X, radians.Y, radians.Z)
                    .SetLocalScale(scale.X, scale.Y, scale.Z);
                finBones[cmbBone.id] = finBone;

                foreach (var child in cmbBone.children)
                {
                    boneQueue.Enqueue((child, finBone));
                }
            }

            // Adds animations
            foreach (var(csabFile, csab) in filesAndCsabs)
            {
                var finAnimation = finModel.AnimationManager.AddAnimation();
                finAnimation.Name = csabFile.NameWithoutExtension;

                finAnimation.FrameCount = (int)csab.Duration;
                finAnimation.FrameRate  = fps;

                foreach (var(boneIndex, anod) in csab.BoneIndexToAnimationNode)
                {
                    var boneTracks = finAnimation.AddBoneTracks(finBones[boneIndex]);

                    // TODO: Add support for in/out tangents
                    foreach (var translationX in anod.TranslationX.Keyframes)
                    {
                        boneTracks.Positions.Set((int)translationX.Time,
                                                 0,
                                                 translationX.Value,
                                                 translationX.IncomingTangent,
                                                 translationX.OutgoingTangent);
                    }
                    foreach (var translationY in anod.TranslationY.Keyframes)
                    {
                        boneTracks.Positions.Set((int)translationY.Time,
                                                 1,
                                                 translationY.Value,
                                                 translationY.IncomingTangent,
                                                 translationY.OutgoingTangent);
                    }
                    foreach (var translationZ in anod.TranslationZ.Keyframes)
                    {
                        boneTracks.Positions.Set((int)translationZ.Time,
                                                 2,
                                                 translationZ.Value,
                                                 translationZ.IncomingTangent,
                                                 translationZ.OutgoingTangent);
                    }

                    foreach (var scaleX in anod.ScaleX.Keyframes)
                    {
                        boneTracks.Scales.Set((int)scaleX.Time,
                                              0,
                                              scaleX.Value,
                                              scaleX.IncomingTangent,
                                              scaleX.OutgoingTangent);
                    }
                    foreach (var scaleY in anod.ScaleY.Keyframes)
                    {
                        boneTracks.Scales.Set((int)scaleY.Time,
                                              1,
                                              scaleY.Value,
                                              scaleY.IncomingTangent,
                                              scaleY.OutgoingTangent);
                    }
                    foreach (var scaleZ in anod.ScaleZ.Keyframes)
                    {
                        boneTracks.Scales.Set((int)scaleZ.Time,
                                              2,
                                              scaleZ.Value,
                                              scaleZ.IncomingTangent,
                                              scaleZ.OutgoingTangent);
                    }

                    foreach (var rotationX in anod.RotationX.Keyframes)
                    {
                        boneTracks.Rotations.Set((int)rotationX.Time,
                                                 0,
                                                 rotationX.Value,
                                                 rotationX.IncomingTangent,
                                                 rotationX.OutgoingTangent);
                    }
                    foreach (var rotationY in anod.RotationY.Keyframes)
                    {
                        boneTracks.Rotations.Set((int)rotationY.Time,
                                                 1,
                                                 rotationY.Value,
                                                 rotationY.IncomingTangent,
                                                 rotationY.OutgoingTangent);
                    }
                    foreach (var rotationZ in anod.RotationZ.Keyframes)
                    {
                        boneTracks.Rotations.Set((int)rotationZ.Time,
                                                 2,
                                                 rotationZ.Value,
                                                 rotationZ.IncomingTangent,
                                                 rotationZ.OutgoingTangent);
                    }
                }
            }

            // TODO: Move these reads into the model reading logic
            var ctrTexture    = new CtrTexture();
            var textureImages =
                cmb.tex.textures.Select(cmbTexture => {
                var position = cmb.startOffset +
                               cmb.header.textureDataOffset +
                               cmbTexture.dataOffset;
                IImage image;
                if (position != 0)
                {
                    r.Position = position;
                    var data   =
                        r.ReadBytes((int)cmbTexture.dataLength);
                    image =
                        ctrTexture.DecodeImage(data, cmbTexture);
                }
                else
                {
                    var ctxb =
                        filesAndCtxbs
                        .Select(
                            fileAndCtxb => fileAndCtxb.Item2)
                        .Single(ctxb => ctxb.Chunk.Entry.name == cmbTexture.name);
                    image =
                        ctrTexture.DecodeImage(ctxb.Data,
                                               cmbTexture);
                }
                return(image);
            })
                .ToArray();

            // Creates meshes & textures
            // TODO: Emulate fixed-function materials
            var finMaterials = new List <IMaterial>();

            for (var i = 0; i < cmb.mat.materials.Length; ++i)
            {
                var cmbMaterial = cmb.mat.materials[i];

                // Get associated texture
                var texMapper = cmbMaterial.texMappers[0];
                var textureId = texMapper.textureId;

                ITexture?finTexture = null;
                if (textureId != -1)
                {
                    var cmbTexture   = cmb.tex.textures[textureId];
                    var textureImage = textureImages[textureId];

                    finTexture           = finModel.MaterialManager.CreateTexture(textureImage);
                    finTexture.Name      = cmbTexture.name;
                    finTexture.WrapModeU = this.CmbToFinWrapMode(texMapper.wrapS);
                    finTexture.WrapModeV = this.CmbToFinWrapMode(texMapper.wrapT);
                }

                // Create material
                IMaterial finMaterial = finTexture != null
                                    ? finModel.MaterialManager
                                        .AddTextureMaterial(
                    finTexture)
                                    : finModel.MaterialManager
                                        .AddLayerMaterial();

                finMaterial.Name        = $"material{i}";
                finMaterial.CullingMode = cmbMaterial.faceCulling switch {
                    CullMode.FrontAndBack => CullingMode.SHOW_BOTH,
                    CullMode.Front => CullingMode.SHOW_FRONT_ONLY,
                    CullMode.BackFace => CullingMode.SHOW_BACK_ONLY,
                    CullMode.Never => CullingMode.SHOW_NEITHER,
                    _ => throw new NotImplementedException(),
                };

                finMaterials.Add(finMaterial);
            }

            /*{
             * var nameToTextures = new Dictionary<string, ITexture>();
             * foreach (var finMaterial in finMaterials) {
             *  foreach (var finTexture in finMaterial.Textures) {
             *    nameToTextures[finTexture.Name] = finTexture;
             *  }
             * }
             *
             * foreach (var (_, finTexture) in nameToTextures) {
             *  finTexture.ImageData.Save(
             *      Path.Join(outputDirectory.FullName, finTexture.Name + ".png"));
             * }
             * }*/

            var verticesByIndex = new ListDictionary <int, IVertex>();

            // Adds meshes
            foreach (var cmbMesh in cmb.sklm.meshes.meshes)
            {
                var shape = cmb.sklm.shapes.shapes[cmbMesh.shapeIndex];

                uint vertexCount = 0;
                var  meshIndices = new List <uint>();
                foreach (var pset in shape.primitiveSets)
                {
                    foreach (var index in pset.primitive.indices)
                    {
                        meshIndices.Add(index);
                        vertexCount = Math.Max(vertexCount, index);
                    }
                }
                ++vertexCount;

                var preproject    = new bool?[vertexCount];
                var skinningModes = new SkinningMode?[vertexCount];
                foreach (var pset in shape.primitiveSets)
                {
                    foreach (var index in pset.primitive.indices)
                    {
                        skinningModes[index] = pset.skinningMode;
                        preproject[index]    = pset.skinningMode != SkinningMode.Smooth;
                    }
                }

                // Gets flags
                var inc    = 1;
                var hasNrm = BitLogic.GetFlag(shape.vertFlags, inc++);
                if (cmb.header.version > CmbVersion.OCARINA_OF_TIME_3D)
                {
                    // Skip "HasTangents" for now
                    inc++;
                }
                var hasClr = BitLogic.GetFlag(shape.vertFlags, inc++);
                var hasUv0 = BitLogic.GetFlag(shape.vertFlags, inc++);
                var hasUv1 = BitLogic.GetFlag(shape.vertFlags, inc++);
                var hasUv2 = BitLogic.GetFlag(shape.vertFlags, inc++);
                var hasBi  = BitLogic.GetFlag(shape.vertFlags, inc++);
                var hasBw  = BitLogic.GetFlag(shape.vertFlags, inc++);

                // Gets bone indices
                var boneCount = shape.boneDimensions;
                var bIndices  = new short[vertexCount * boneCount];
                foreach (var pset in shape.primitiveSets)
                {
                    foreach (var i in pset.primitive.indices)
                    {
                        if (hasBi && pset.skinningMode != SkinningMode.Single)
                        {
                            r.Position = cmb.startOffset +
                                         cmb.header.vatrOffset +
                                         cmb.vatr.bIndices.StartOffset +
                                         shape.bIndices.Start +
                                         i *
                                         DataTypeUtil.GetSize(shape.bIndices.DataType) *
                                         shape.boneDimensions;
                            for (var bi = 0; bi < shape.boneDimensions; ++bi)
                            {
                                var boneTableIndex = shape.bIndices.Scale *
                                                     DataTypeUtil.Read(
                                    r,
                                    shape.bIndices.DataType);
                                bIndices[i * boneCount + bi] =
                                    pset.boneTable[(int)boneTableIndex];
                            }
                        }
                        else
                        {
                            bIndices[i] = shape.primitiveSets[0].boneTable[0];
                        }
                    }
                }

                var finMesh = finSkin.AddMesh();

                // TODO: Encapsulate these reads somewhere else
                // Get vertices
                var finVertices = new IVertex[vertexCount];
                for (var i = 0; i < vertexCount; ++i)
                {
                    // Position
                    r.Position = cmb.startOffset +
                                 cmb.header.vatrOffset +
                                 cmb.vatr.position.StartOffset +
                                 shape.position.Start +
                                 3 * DataTypeUtil.GetSize(shape.position.DataType) * i;
                    var positionValues =
                        DataTypeUtil.Read(r, 3, shape.position.DataType)
                        .Select(value => value * shape.position.Scale)
                        .ToArray();

                    var finVertex = finSkin.AddVertex(positionValues[0],
                                                      positionValues[1],
                                                      positionValues[2]);
                    finVertices[i] = finVertex;

                    var index = (ushort)(shape.position.Start / 3 + i);
                    verticesByIndex.Add(index, finVertex);

                    if (hasNrm)
                    {
                        r.Position = cmb.startOffset +
                                     cmb.header.vatrOffset +
                                     cmb.vatr.normal.StartOffset +
                                     shape.normal.Start +
                                     3 * DataTypeUtil.GetSize(shape.normal.DataType) * i;
                        var normalValues =
                            DataTypeUtil.Read(r, 3, shape.normal.DataType)
                            .Select(value => value * shape.normal.Scale)
                            .ToArray();
                        finVertex.SetLocalNormal(normalValues[0],
                                                 normalValues[1],
                                                 normalValues[2]);
                    }

                    if (hasClr)
                    {
                        r.Position = cmb.startOffset +
                                     cmb.header.vatrOffset +
                                     cmb.vatr.color.StartOffset +
                                     shape.color.Start +
                                     4 * DataTypeUtil.GetSize(shape.color.DataType) * i;
                        var colorValues =
                            DataTypeUtil.Read(r, 4, shape.color.DataType)
                            .Select(value => value * shape.color.Scale)
                            .ToArray();

                        finVertex.SetColorBytes((byte)(colorValues[0] * 255),
                                                (byte)(colorValues[1] * 255),
                                                (byte)(colorValues[2] * 255),
                                                (byte)(colorValues[3] * 255));
                    }

                    if (hasUv0)
                    {
                        r.Position = cmb.startOffset +
                                     cmb.header.vatrOffset +
                                     cmb.vatr.uv0.StartOffset +
                                     shape.uv0.Start +
                                     2 * DataTypeUtil.GetSize(shape.uv0.DataType) * i;
                        var uv0Values =
                            DataTypeUtil.Read(r, 2, shape.uv0.DataType)
                            .Select(value => value * shape.uv0.Scale)
                            .ToArray();

                        finVertex.SetUv(0, uv0Values[0], 1 - uv0Values[1]);
                    }
                    if (hasUv1)
                    {
                        r.Position = cmb.startOffset +
                                     cmb.header.vatrOffset +
                                     cmb.vatr.uv1.StartOffset +
                                     shape.uv1.Start +
                                     2 * DataTypeUtil.GetSize(shape.uv1.DataType) * i;
                        var uv1Values =
                            DataTypeUtil.Read(r, 2, shape.uv1.DataType)
                            .Select(value => value * shape.uv1.Scale)
                            .ToArray();

                        finVertex.SetUv(1, uv1Values[0], 1 - uv1Values[1]);
                    }
                    if (hasUv2)
                    {
                        r.Position = cmb.startOffset +
                                     cmb.header.vatrOffset +
                                     cmb.vatr.uv2.StartOffset +
                                     shape.uv2.Start +
                                     2 * DataTypeUtil.GetSize(shape.uv2.DataType) * i;
                        var uv2Values =
                            DataTypeUtil.Read(r, 2, shape.uv2.DataType)
                            .Select(value => value * shape.uv2.Scale)
                            .ToArray();

                        finVertex.SetUv(2, uv2Values[0], 1 - uv2Values[1]);
                    }

                    var preprojectMode = preproject[i].Value
                                   ? PreprojectMode.BONE
                                   : PreprojectMode.NONE;

                    if (hasBw)
                    {
                        r.Position = cmb.startOffset +
                                     cmb.header.vatrOffset +
                                     cmb.vatr.bWeights.StartOffset +
                                     shape.bWeights.Start +
                                     i *
                                     DataTypeUtil.GetSize(shape.bWeights.DataType) *
                                     boneCount;

                        var totalWeight = 0f;
                        var boneWeights = new List <BoneWeight>();
                        for (var j = 0; j < boneCount; ++j)
                        {
                            // TODO: Looks like this is rounded to the nearest 2 in the original??
                            var weight = DataTypeUtil.Read(r, shape.bWeights.DataType) *
                                         shape.bWeights.Scale;
                            totalWeight += weight;

                            if (weight > 0)
                            {
                                var bone =
                                    finBones[bIndices[i * boneCount + j]];
                                var boneWeight = new BoneWeight(bone, null, weight);

                                boneWeights.Add(boneWeight);
                            }
                        }

                        Asserts.True(boneWeights.Count > 0);
                        Asserts.True(Math.Abs(1 - totalWeight) < .0001);
                        finVertex.SetBoneWeights(
                            finSkin.GetOrCreateBoneWeights(preprojectMode,
                                                           boneWeights.ToArray()));
                    }
                    else
                    {
                        var boneIndex = bIndices[i];
                        finVertex.SetBoneWeights(
                            finSkin.GetOrCreateBoneWeights(preprojectMode,
                                                           finBones[boneIndex]));
                    }

                    finVertex.SetColor(ColorImpl.FromSystemColor(Color.White));
                }

                // Adds faces. Thankfully, it's all just triangles!
                var triangleVertices = meshIndices
                                       .Select(meshIndex => finVertices[meshIndex])
                                       .ToArray();
                finMesh.AddTriangles(triangleVertices)
                .SetMaterial(finMaterials[cmbMesh.materialIndex])
                .SetVertexOrder(VertexOrder.NORMAL);
            }

            // Adds morph targets
            foreach (var(shpaFile, shpa) in filesAndShpas)
            {
                var shpaIndexToPosi =
                    shpa?.Posi.Values.Select((posi, i) => (shpa.Idxs.Indices[i], posi))
                    .ToDictionary(indexAndPosi => indexAndPosi.Item1,
                                  indexAndPosi => indexAndPosi.posi);

                var morphTarget = finModel.AnimationManager.AddMorphTarget();
                morphTarget.Name = shpaFile.NameWithoutExtension;

                foreach (var(index, position) in shpaIndexToPosi)
                {
                    if (!verticesByIndex.TryGetList(index, out var finVertices))
                    {
                        continue;
                    }

                    foreach (var finVertex in finVertices)
                    {
                        morphTarget.MoveTo(finVertex, position);
                    }
                }
            }

            return(finModel);
        }
Ejemplo n.º 21
0
 /// <summary>
 /// Sets the type for the new column based on the given SQL type and target
 /// data length (in type specific units).
 /// </summary>
 /// <remarks>
 /// Sets the type for the new column based on the given SQL type and target
 /// data length (in type specific units).
 /// </remarks>
 /// <exception cref="Sharpen.SQLException"></exception>
 public virtual HealthMarketScience.Jackcess.ColumnBuilder SetSQLType(int type, int
                                                                      lengthInUnits)
 {
     return(SetType(DataTypeUtil.FromSQLType(type, lengthInUnits)));
 }
Ejemplo n.º 22
0
 private bool IsPseudoGuidColumn(DataType dataType, string propName, int dataSize)
 {
     // guids seem to be marked as "binary" fields
     return((dataType == DataType.BINARY) && (dataSize == DataTypeUtil.GetFixedSize(DataType
                                                                                    .GUID)) && Sharpen.Runtime.EqualsIgnoreCase(PropertyMap.GUID_PROP, propName));
 }