public void GetGMTOffset_PST() { var offset = DataTypeUtil.GetGMTOffset(TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"), new DateTime(2014, 12, 1)); Assert.Equal(-800, offset); }
/// <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); } }
/// <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); } }
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])); } }
} //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 }
/// <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("'", "''"))); } }
/// <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); } }
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); }
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); }
/// <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); } }
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); }
/// <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); }
/// <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 }
/// <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()); } } }
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); } }
/// <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); }
// 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); }
/// <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))); }
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)); }