static SsImageFile() { invalidInstance = new SsImageFile(); invalidInstance.path = "INVALID"; invalidInstance.width = 8; invalidInstance.height = 8; invalidInstance.bpp = 8; }
AddMaterials(SsPartRes part, SsColorBlendOperation colorBlendType) { SsImageFile img = part.imageFile; SsShaderType shaderType = SsShaderManager.EnumToType(colorBlendType, part.AlphaBlendType, SsMaterialColorBlendOperation.Non); Material material = img.GetMaterial(shaderType); if (material) { return; // already added } // create material #if _BUILD_UNIFIED_SHADERS img.useUnifiedShader = _anmRes.UseCgProgram; Shader shader = SsShaderManager.Get(shaderType, _anmRes.UseCgProgram); #else Shader shader = SsShaderManager.Get(shaderType, false); #endif // get material asset path string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(img.texture)) + "/assets/"; string shaderName = shader.name; shaderName = shaderName.Replace("Ss/", ""); string assetName = assetPath + img.texture.name + "_Mat_" + shaderName + ".asset"; // try to load the exiting Material existedMat = (Material)AssetDatabase.LoadAssetAtPath(assetName, typeof(Material)); Material mat = (existedMat ?? new Material(shader)); mat.SetTexture("_MainTex", img.texture); if (existedMat == null) { // if none, create material as asset file newly // Debug.Log("create material: " + img.path + " shader: " + shaderType); if (!Directory.Exists(assetPath)) { string parentFolder = Path.GetDirectoryName(assetPath.TrimEnd('\\', '/')); AssetDatabase.CreateFolder(parentFolder, "assets"); } AssetDatabase.CreateAsset(mat, assetName); } else { // update the existing content mat.shader = shader; EditorUtility.SetDirty(mat); AssetDatabase.SaveAssets(); //same as EditorApplication.SaveAssets(); } // add to material list img.materials[SsShaderManager.ToSerial(shaderType)] = mat; }
GetImage(string path) { //Debug.Log("Textures " + Resources.FindObjectsOfTypeAll(typeof(Texture)).Length); SsImageFile img; try { // try get the existing img = _imageFileList[path]; } catch (KeyNotFoundException) { // not found, so create img = new SsImageFile(); img.path = path; img.materials = new Material[(int)SsShaderType.Num]; #if false // reimport texture with settings for SpriteStudio SsAssetPostProcessor.HookTextureImport = true; AssetDatabase.ImportAsset(path, ImportAssetOptions.Default); #endif #if false // omit extension to load Texture Asset successfully //string pathExtOmitted = Path.ChangeExtension(path, null); // load image newly //Object obj = Resources.Load(pathExtOmitted, typeof(Texture2D)); #else Object obj = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)); #endif img.texture = obj as Texture2D; //Debug.Log(img.texture); if (img.texture == null) { Debug.LogError("can't load image: " + path); return(null); } // change default texture wrap and filtering medthod to avoid unexpected edge colors img.texture.wrapMode = TextureWrapMode.Clamp; // img.texture.filterMode = FilterMode.Point; // unwanted... 2012.04.04 // add to list _imageFileList[path] = img; } return(img); }
Init() { // if don't do this, Transforms(GameObjects) are created every time as come into ExecuteInEditMode. DeleteTransformChildren(); //Debug.Log("Init() " + gameObject.name); if (!_animation) { // clear variables //Debug.LogWarning("No anime resource attached-> " + gameObject.name); // works _partResList = null; _imageList = null; _partsNum = 0; _parts = null; _boundPartList = null; _materials = null; _vertices = null; _uvs = null; _colors = null; _extras = null; _mesh = null; _meshFilter.mesh = null; #if _USE_SHARED_MATERIAL _meshRenderer.sharedMaterials = new Material[1]; #else _meshRenderer.materials = new Material[1]; #endif // statuses _isPlaying = _isFinished = false; PlayCount = 0; Speed = 1f; _prevPlayDirection = _playDirection = SsAnimePlayDirection.Forward; ResetAnimationStatus(); _startAnimeFrame = _endAnimeFrame = _playFrameLength = 0; return; } EnsureMeshComponent(); // initialize values ResetAnimationStatus(); Pause(); _isFinished = false; // get parts and images. _partResList = _animation.PartList; _imageList = _animation.ImageList; _partsNum = _partResList.Length; // create material array. actually root doesn't need material so can cut down. _materials = new Material[_partsNum - 1]; // create vertices... int vertNum = (_partsNum - 1) * 4; _vertices = new Vector3[vertNum]; _uvs = new Vector2[vertNum]; _colors = new Color[vertNum]; _extras = new Vector2[vertNum]; // now create mesh _mesh = new Mesh(); _mesh.vertices = _vertices; // to avoid "out of bounds" error when we set triangle indices. _mesh.subMeshCount = _partsNum - 1; _mesh.uv2 = _extras; // attach to MeshFilter _meshFilter.mesh = _mesh; // create sprite parts and pass to resource used _parts = new SsPart[_partsNum]; for (int i = 0; i < _parts.Length; ++i) { SsPartRes partRes = _partResList[i]; SsImageFile image = partRes.IsRoot ? null : _imageList[partRes.SrcObjId]; _parts[i] = new SsPart(this, i, partRes, image); // set root sprite if (i == 0) { _rootPart = _parts[i]; } else { // set individual material to buffer _materials[i - 1] = _parts[i]._material; } // register bound parts separately for fast access if (partRes.Type == SsPartType.Bound) { if (_boundPartList == null) { _boundPartList = new List <SsPart>(); } _boundPartList.Add(_parts[i]); } } // set materials to affect #if _USE_SHARED_MATERIAL _meshRenderer.sharedMaterials = _materials; #else _meshRenderer.materials = _materials; #endif // attach values to the Mesh _mesh.vertices = _vertices; _mesh.uv = _uvs; // at first time must invoke vertex update to display initial posed animation. _vertChanged = true; // reflect blend settings to shader _extraChanged = true; #if false // use user data numeric value as PlayCount if (PartResList[0].UserKeys.Count > 0) { SsUserDataKeyFrame userKey = (SsUserDataKeyFrame)PartResList[0].GetKey(SsKeyAttr.User, 0); PlayCount = userKey.Value.Num; } #endif // to fix the problem that h/vFlipped animation from initial time doesn't affects mesh UpdateAlways(); }
Parse(bool isAnime) // = true) { if (_text == null) { return(false); } XmlDocument doc = new XmlDocument(); // doc is the new xml document. doc.LoadXml(_text); // load the file. string rootTagStr, rootNSStr; if (isAnime) { // this is .ssax rootTagStr = "SpriteStudioMotion"; rootNSStr = "http://www.webtech.co.jp/SpriteStudio/XML/Motion"; } else { // this is .sssx rootTagStr = "SpriteStudioScene"; rootNSStr = "http://www.webtech.co.jp/SpriteStudio/XML/Scene"; } // check the root tag name validity // root is ?xml, so skip to the next XmlNode rootNode = doc.FirstChild; rootNode = rootNode.NextSibling; if (rootNode.Name != rootTagStr) { Debug.LogError("Invalid root tag name: " + rootNode.Name); return(false); } // check the root tag namespace validity XmlAttributeCollection rootNodeAttrs = rootNode.Attributes; XmlNode nodeXMLNS = rootNodeAttrs["xmlns"]; if (nodeXMLNS.Value != rootNSStr) { Debug.LogError("\"xmlns\" doesn't match: " + rootNode.Name); return(false); } // check file format version validity XmlNode versionNode = rootNodeAttrs["version"]; int readVersion = SsVersion.ToInt(versionNode.Value); if (readVersion < RequiredVersion) { Debug.LogError("Version under " + SsVersion.ToString(RequiredVersion) + " is not supported -> " + SsVersion.ToString(readVersion)); return(false); } if (readVersion > CurrentVersion) { Debug.LogError("This version " + SsVersion.ToString(readVersion) + " is not supported yet. supports up to " + SsVersion.ToString(CurrentVersion)); return(false); } #if false // made sure the rootNode has Header, ImageList, Parts XmlNodeList children = rootNode.ChildNodes; foreach (XmlNode n in children) { Debug.Log(n.Name); } #endif // Create an XmlNamespaceManager to resolve namespaces. NameTable nt = new NameTable(); _nsMgr = new XmlNamespaceManager(nt); _nsMgr.AddNamespace("cur", nodeXMLNS.Value); // read header XmlNode headerNode = _SelectSingleNode(rootNode, "cur:Header"); if (headerNode == null) { Debug.LogError("Header node is not found"); return(false); } XmlNode endFrameNode = _SelectSingleNode(headerNode, "cur:EndFrame"); if (endFrameNode == null) { Debug.LogError("EndFrame node is not found"); return(false); } _anmRes.EndFrame = _ToInt(endFrameNode.InnerText); #if NEED_EDIT_MODE _editMode = _ToInt(_SelectSingleNode(headerNode, "cur:EditMode").InnerText); #endif _anmRes.FPS = _ToInt(_SelectSingleNode(headerNode, "cur:BaseTickTime").InnerText); // read option settings XmlNode optionNode = _SelectSingleNode(headerNode, "cur:OptionState"); if (optionNode != null) { XmlNode n = _SelectSingleNode(optionNode, "cur:hvFlipForImageOnly"); if (n == null) { _anmRes.hvFlipForImageOnly = true; } else { _anmRes.hvFlipForImageOnly = _ToBool(n.InnerText); } } // create image manager singleton //var imgMgr = SsImageManager.Singleton; // enumerate image paths // it is possible to be nothing in .ssax XmlNodeList imageNodeList = _SelectNodes(rootNode, "./cur:ImageList/cur:Image"); if (imageNodeList == null) { Debug.LogError("ImageList node is not found"); return(false); } if (imageNodeList.Count <= 0) { Debug.LogError("ImageList has no contents"); return(false); } _anmRes.ImageList = new SsImageFile[imageNodeList.Count]; //Debug.Log("imageNodeList.Count: " + imageNodeList.Count); foreach (XmlNode e in imageNodeList) { string idStr = e.Attributes["Id"].Value; int index = _ToInt(idStr) - 1; // because it starts from 1. string path = e.Attributes["Path"].Value; // remove the useless string "./cur:" on head //Debug.Log("Id=" + idStr + " Path=" + path); if (path.StartsWith(@".\")) { path = path.Remove(0, 2); } path = path.Replace(@"\", "/"); // for Mac //path = _relPath + "/" + path; // doesn't care about ../ string baseFullPath = Path.GetFullPath("./"); path = Path.GetFullPath(Path.Combine(_relPath, path)); // combine path considering ../ path = path.Substring(baseFullPath.Length); path = path.Replace(@"\", "/"); // just in case //Debug.Log("Id=" + index + " Path=" + path); // get image file info which contains a Texture Asset. SsImageFile imgFile = GetImage(path); if (imgFile == null) { return(false); } XmlNode widthNode = e.Attributes["Width"]; if (widthNode != null) { imgFile.width = _ToInt(widthNode.Value); if (!_IsPowerOfTwo(imgFile.width)) { Debug.LogWarning("Image width is not power of 2, it will be scaled."); } } else { imgFile.width = imgFile.texture.width; } XmlNode heightNode = e.Attributes["Height"]; if (heightNode != null) { imgFile.height = _ToInt(heightNode.Value); if (!_IsPowerOfTwo(imgFile.height)) { Debug.LogWarning("Image height is not power of 2, it will be scaled."); } } else { imgFile.height = imgFile.texture.height; } // For now, bpp is not used anywhere. XmlNode bppNode = e.Attributes["Bpp"]; if (bppNode != null) { imgFile.bpp = _ToInt(bppNode.Value); if (imgFile.bpp <= 8) { Debug.LogWarning(path + " seems index color image, so it has to be converted to direct color or compressed type"); } } else { switch (imgFile.texture.format) { default: imgFile.bpp = 0; // Zero means something compressed type break; case TextureFormat.ARGB4444: case TextureFormat.RGB565: imgFile.bpp = 16; break; case TextureFormat.RGB24: imgFile.bpp = 24; break; case TextureFormat.ARGB32: case TextureFormat.RGBA32: imgFile.bpp = 32; break; } } // register image info into the list _anmRes.ImageList[index] = imgFile; } // enumerate parts XmlNodeList partList = _SelectNodes(rootNode, "./cur:Parts/cur:Part"); if (partList == null) { Debug.LogError("Parts node is not found"); return(false); } //Debug.Log("Parts Num: " + partList.Count); if (partList.Count <= 0) { Debug.LogError("No existence of Parts"); return(false); } _anmRes.PartList = new SsPartRes[partList.Count]; foreach (XmlNode part in partList) { // create a part var partBase = new SsPartRes(); partBase.AnimeRes = _anmRes; XmlAttribute rootAttr = part.Attributes["Root"]; partBase.InheritState.Initialize(4, _anmRes.hvFlipForImageOnly); string partName = _GetNodeValue(part, "./cur:Name"); partBase.Name = System.String.Copy(partName); if (rootAttr != null) { // this is root parts partBase.Type = SsPartType.Root; partBase.MyId = 0; partBase.ParentId = -1; } else { // general parts partBase.Type = (SsPartType)_ToInt(_GetNodeValue(part, "./cur:Type")); partBase.PicArea.Top = _ToInt(_GetNodeValue(part, "./cur:PictArea/cur:Top")); partBase.PicArea.Left = _ToInt(_GetNodeValue(part, "./cur:PictArea/cur:Left")); partBase.PicArea.Bottom = _ToInt(_GetNodeValue(part, "./cur:PictArea/cur:Bottom")); partBase.PicArea.Right = _ToInt(_GetNodeValue(part, "./cur:PictArea/cur:Right")); partBase.OriginX = _ToInt(_GetNodeValue(part, "./cur:OriginX")); partBase.OriginY = _ToInt(_GetNodeValue(part, "./cur:OriginY")); partBase.MyId = 1 + _ToInt(_GetNodeValue(part, "./cur:ID")); partBase.ParentId = 1 + _ToInt(_GetNodeValue(part, "./cur:ParentID")); partBase.SrcObjId = _ToInt(_GetNodeValue(part, "./cur:PicID")); partBase.AlphaBlendType = (SsAlphaBlendOperation)(1 + _ToInt(_GetNodeValue(part, "./cur:TransBlendType"))); partBase.InheritState.Type = (SsInheritanceType)_ToInt(_GetNodeValue(part, "./cur:InheritType")); if (partBase.SrcObjId >= _anmRes.ImageList.Length) { /* * // supply lack of image * int count = 1 + partBase.SrcObjId - _anmRes.ImageList.Length; * _anmRes.ImageList. * for (int i = 0; i < count; ++i) * { * _anmRes.ImageList[partBase.SrcObjId + i] = SsImageFile.invalidInstance; * } */ // clamp id Debug.LogWarning("Picture ID is out of image list. Part: " + partName + " PicId: " + partBase.SrcObjId); partBase.SrcObjId = 0; } partBase.imageFile = _anmRes.ImageList[partBase.SrcObjId]; if (partBase.imageFile != SsImageFile.invalidInstance) { // precalc UV coordinates partBase.CalcUVs(0, 0, 0, 0); // add basic material with basic shader AddMaterials(partBase, SsColorBlendOperation.Non); } if (partBase.InheritState.Type == SsInheritanceType.Parent) { // copy parent's value and rate statically. dynamic reference is certain implement but it costs much more. for (int i = 0; i < (int)SsKeyAttr.Num; ++i) { SsKeyAttr attr = (SsKeyAttr)i; var param = _anmRes.PartList[partBase.ParentId].InheritParam(attr); partBase.InheritState.Values[i] = param; //Debug.Log(partBase.Name +" inherits parent's attr: " + attr + " use: " + param.Use + " rate:" + param.Rate); } } } // make original 4 vertices will be not modified. it consists of OriginX/Y and PicArea.WH. partBase.OrgVertices = partBase.GetVertices(partBase.PicArea.WH()); #if false // parent part SsPartRes parentPart = null; if (partBase.ParentId >= 0) { parentPart = _anmRes.PartList[partBase.ParentId]; } #endif if (!isAnime) { // scene only has this element partBase.SrcObjType = (SsSourceObjectType)_ToInt(_GetNodeValue(part, "./cur:ObjectType")); } // parse attributes XmlNodeList attrList = _SelectNodes(part, "./cur:Attributes/cur:Attribute"); string attrName; foreach (XmlNode attrNode in attrList) { // recognize the tag attrName = attrNode.Attributes["Tag"].Value; if (attrName.Length != 4) { Debug.LogWarning("invalid attribute tag!!: " + attrName); continue; } SsKeyAttrDesc attrDesc = SsKeyAttrDescManager.Get(attrName); if (attrDesc == null) { Debug.LogWarning("Unknown or Unsupported attribute: " + attrName); continue; } switch (attrDesc.Attr) { case SsKeyAttr.PartsPal: if (attrNode.HasChildNodes) { Debug.LogWarning("Unsupported attribute: " + attrName); } continue; } // set inheritance parameter to part instance. if (partBase.Type != SsPartType.Root) { if (partBase.InheritState.Type == SsInheritanceType.Self) { // has its own value. var InheritParam = new SsInheritanceParam(); XmlNode InheritNode = attrNode.Attributes.GetNamedItem("Inherit"); if (InheritNode != null) { // mix my value and parent's value, but actually user 100% parent's... InheritParam.Use = true; InheritParam.Rate = (100 * _ToInt(InheritNode.Value)) / SSIO_SUCCEED_DENOMINATOR; } else { // absolutely not refer the parent's value. InheritParam.Use = false; InheritParam.Rate = 0; } // apply to part partBase.InheritState.Values[(int)attrDesc.Attr] = InheritParam; //Debug.LogError(partBase.Name +" has own value! attr:" + attrDesc.Attr + " use:" + InheritParam.Use); } } // enumerate keys XmlNodeList keyList = _SelectNodes(attrNode, "./cur:Key"); if (keyList == null || keyList.Count < 1) { //Debug.Log(attrName + " has no keys"); } else { foreach (XmlNode key in keyList) { //dynamic keyBase; cannot use dynamic at this time SsKeyFrameInterface keyBase; bool bNeedCurve = true; switch (attrDesc.ValueType) { case SsKeyValueType.Data: { // if value type is Data, string format of node "Value" depends on attribute type. string strValue = _GetNodeValue(key, "./cur:Value"); switch (attrDesc.CastType) { default: case SsKeyCastType.Bool: // not supported currently case SsKeyCastType.Other: // not supported currently case SsKeyCastType.Int: case SsKeyCastType.Hex: // these types are used as integer. var intKey = new SsIntKeyFrame(); // to make intellisence working, really?? if (attrDesc.CastType == SsKeyCastType.Hex) { intKey.Value = _HexToInt(strValue); } else { intKey.Value = _ToInt(strValue); } switch (attrDesc.Attr) { case SsKeyAttr.PosX: case SsKeyAttr.PosY: // apply scale factor intKey.Value = (int)((float)intKey.Value * _anmRes.ScaleFactor); break; #if _FORCE_BOUND_PART_TO_MOST_TOP // force bound part to most top to draw surely if wanted case SsKeyAttr.Prio: if (partBase.Type == SsPartType.Bound) { intKey.Value = short.MaxValue; // int.MaxValue is failed to unbox } break; #endif } #if _DEBUG Debug.LogWarning("Is it OK? -> " + strValue + " = " + intKey.Value); #endif keyBase = intKey; break; case SsKeyCastType.Float: case SsKeyCastType.Degree: var floatKey = new SsFloatKeyFrame(); // to make intellisence working, really?? #if _FORCE_BOUND_PART_TO_BE_TRANSPARENT // force bound part to transparent to draw if wanted if (attrDesc.Attr == SsKeyAttr.Trans && partBase.Type == SsPartType.Bound) { floatKey.Value = 0.5f; } else #endif floatKey.Value = (float)_ToDouble(strValue); // unnecessary to convert to radian. because Unity requires degree unit. //if (attrDesc.CastType == SsKeyCastType.Degree) //floatKey.Value = (float)_DegToRad( _ToDouble(strValue) ); keyBase = floatKey; break; } } break; case SsKeyValueType.Param: { var boolKey = new SsBoolKeyFrame(); keyBase = boolKey; boolKey.Value = _ToUInt(_GetNodeValue(key, "./cur:Value")) != 0 ? true : false; bNeedCurve = false; } break; case SsKeyValueType.Palette: { var paletteKey = new SsPaletteKeyFrame(); keyBase = paletteKey; var v = new SsPaletteKeyValue(); v.Use = _ToUInt(_GetNodeValue(key, "./cur:Use")) != 0 ? true : false; v.Page = _ToInt(_GetNodeValue(key, "./cur:Page")); v.Block = (byte)_ToInt(_GetNodeValue(key, "./cur:Block")); paletteKey.Value = v; } break; case SsKeyValueType.Color: { var colorBlendKey = new SsColorBlendKeyFrame(); keyBase = colorBlendKey; var v = new SsColorBlendKeyValue(4); v.Target = (SsColorBlendTarget)_ToUInt(_GetNodeValue(key, "./cur:Type")); v.Operation = (SsColorBlendOperation)(1 + _ToUInt(_GetNodeValue(key, "./cur:Blend"))); AddMaterials(partBase, v.Operation); switch (v.Target) { case SsColorBlendTarget.None: // no color, but do care about interpolation to/from 4 vertex colors for (int i = 0; i < 4; ++i) { v.Colors[i].R = v.Colors[i].G = v.Colors[i].B = 255; // 0 alpha value means no effect. v.Colors[i].A = 0; } break; case SsColorBlendTarget.Overall: // one color, but do care about interpolation to/from 4 vertex colors _GetColorRef(v.Colors[0], key, "./cur:Value"); for (int i = 1; i < 4; ++i) { v.Colors[i] = v.Colors[0]; } break; case SsColorBlendTarget.Vertex: // 4 vertex colors. the order is clockwise. _GetColorRef(v.Colors[0], key, "./cur:TopLeft"); _GetColorRef(v.Colors[1], key, "./cur:TopRight"); _GetColorRef(v.Colors[2], key, "./cur:BottomRight"); _GetColorRef(v.Colors[3], key, "./cur:BottomLeft"); break; } colorBlendKey.Value = v; } break; case SsKeyValueType.Vertex: { var vertexKey = new SsVertexKeyFrame(); keyBase = vertexKey; var v = new SsVertexKeyValue(4); _GetPoint(v.Vertices[0], key, "./cur:TopLeft"); _GetPoint(v.Vertices[1], key, "./cur:TopRight"); if (readVersion <= (uint)SsAnimeFormatVersion.V320) { // for obsolete version _GetPoint(v.Vertices[2], key, "./cur:BottomLeft"); _GetPoint(v.Vertices[3], key, "./cur:BottomRight"); } else { _GetPoint(v.Vertices[3], key, "./cur:BottomLeft"); _GetPoint(v.Vertices[2], key, "./cur:BottomRight"); } // apply scale factor for (int i = 0; i < v.Vertices.Length; ++i) { v.Vertices[i].Scale(_anmRes.ScaleFactor); } vertexKey.Value = v; } break; case SsKeyValueType.User: { var userKey = new SsUserDataKeyFrame(); keyBase = userKey; var v = new SsUserDataKeyValue(); XmlNode numberNode = _SelectSingleNode(key, "./cur:Number"); if (numberNode != null) { v.IsNum = true; v.Num = _ToInt(numberNode.InnerText); } XmlNode rectNode = _SelectSingleNode(key, "./cur:Rect"); if (rectNode != null) { v.IsRect = true; v.Rect = new SsRect(); _GetRect(v.Rect, rectNode); } XmlNode pointNode = _SelectSingleNode(key, "./cur:Point"); if (pointNode != null) { v.IsPoint = true; v.Point = new SsPoint(); _GetPoint(v.Point, pointNode); } XmlNode stringNode = _SelectSingleNode(key, "./cur:String"); if (stringNode != null) { v.IsString = true; v.String = System.String.Copy(stringNode.InnerText); } // writeback userKey.Value = v; bNeedCurve = false; } // case KEYTYPE_USERDATA break; case SsKeyValueType.Sound: { var soundKey = new SsSoundKeyFrame(); keyBase = soundKey; var v = new SsSoundKeyValue(); v.Flags = (SsSoundKeyFlags)_ToUInt(_SelectSingleNode(key, "./cur:Use").InnerText); v.NoteOn = _ToByte(_SelectSingleNode(key, "./cur:Note").InnerText); v.SoundId = _ToByte(_SelectSingleNode(key, "./cur:ID").InnerText); v.LoopNum = _ToByte(_SelectSingleNode(key, "./cur:Loop").InnerText); v.Volume = _ToByte(_SelectSingleNode(key, "./cur:Volume").InnerText); v.UserData = _ToUInt(_SelectSingleNode(key, "./cur:Data").InnerText); // writeback soundKey.Value = v; bNeedCurve = false; } break; default: Debug.LogError("Fatal error!! not implemented cast type: " + _ToInt(attrNode.Value)); continue; } // switch //keyBase = InitKeyFrameData(); keyBase.ValueType = attrDesc.ValueType; keyBase.Time = _ToInt(key.Attributes["Time"].Value); if (bNeedCurve) { // make values to interpolate var v = new SsCurveParams(); XmlNode curveTypeNode = key.Attributes["CurveType"]; if (curveTypeNode == null) { v.Type = SsInterpolationType.None; } else { v.Type = (SsInterpolationType)_ToUInt(curveTypeNode.Value); if (v.Type == SsInterpolationType.Hermite || v.Type == SsInterpolationType.Bezier) { // must exist if (key.Attributes["CurveStartT"] == null) { Debug.LogError("CurveStartT param not found!!"); return(false); } v.StartT = _ToFloat(key.Attributes["CurveStartT"].Value); v.StartV = _ToFloat(key.Attributes["CurveStartV"].Value); v.EndT = _ToFloat(key.Attributes["CurveEndT"].Value); v.EndV = _ToFloat(key.Attributes["CurveEndV"].Value); switch (attrDesc.Attr) { case SsKeyAttr.PosX: case SsKeyAttr.PosY: case SsKeyAttr.Vertex: // apply scale factor v.StartV *= _anmRes.ScaleFactor; v.EndV *= _anmRes.ScaleFactor; break; case SsKeyAttr.Angle: if (_database.AngleCurveParamAsRadian) { // degree to radian v.StartV = (float)(v.StartV * 180 / System.Math.PI); v.EndV = (float)(v.EndV * 180 / System.Math.PI); } break; } } } keyBase.Curve = v; } #if false//_DEBUG // dump debug info SsDebugLog.Print("Attr: " + attrDesc.Attr + " " + keyBase.ToString()); #endif // add keyFrame info to part instance. partBase.AddKeyFrame(attrDesc.Attr, keyBase); } } } #if _DEBUG // dump debug info SsDebugLog.Print(partBase.ToString()); #endif if (_precalcAttrValues) { // precalculate attribute values each frame partBase.CreateAttrValues(_anmRes.EndFrame + 1); } // add to list // if the container is Dictionary, allow non-sequential ID order of the stored parts, but it occurs to search by ID. _anmRes.PartList[partBase.MyId] = partBase; //_anmRes.PartList.Add(partBase); } // Debug.Log("_anmRes.PartList.Count: " + _anmRes.PartList.Count); #if false // precalculate values to inherit parent's one. if (PrecalcAttrValues) { //foreach (var e in _anmRes.PartList.Values) // for Dictionary version foreach (var e in _anmRes.PartList) { if (!e.IsRoot && e.HasParent) { e.CalcInheritedValues(_anmRes.PartList[e.ParentId]); } } } #endif return(true); }
SsPart( SsSprite manager, int index, ///< index of parts SsPartRes partRes, ///< part resource SsImageFile imageFile) ///< source image path, texture and material. { _mgr = manager; _index = index; _vIndex = (index - 1) * 4; _subMeshIndex = index - 1; _res = partRes; _mesh = _mgr._mesh; if (_res.HasParent) { _parent = _mgr.Sprite(_res.ParentId); if (_parent == null) { Debug.LogError("##### parent sprite must be created already!!"); //throw ArgumentNullException; Debug.Break(); return; } } // attach parent's transform to inherit its SRT. _pivotMatrix = Matrix4x4.identity; switch (_res.Type) { case SsPartType.Root: // root has only position, no vertices #if _APPLY_ROOT_POS_AS_PIVOT _rootPivot = new Vector3(-_res.PosX(0), +_res.PosY(0), 0f); #endif break; case SsPartType.Normal: case SsPartType.Bound: // each vertices are attached to pivot _vertPositions = new Vector3[4]; _orgVertices = new Vector3[4]; for (int i = 0; i < _vertPositions.Length; ++i) { _orgVertices[i] = _vertPositions[i] = _res.OrgVertices[i]; #if _MOVE_BOUND_PART_TO_THE_FRONT if (_res.Type == SsPartType.Bound) { _vertPositions[i].z = -0.1f; _orgVertices[i].z = -0.1f; } #endif } break; default: // other types don't require vertices. break; } // set startup value _visible = !_res.Hide(0); _flipH = false; _flipV = false; _pos = Vector3.zero; _quaternion = Quaternion.identity; _scale = Vector3.one; #if _MAKE_ROOT_TO_LOCAL_TRANSFORM _rotChanged = false; #endif // not any normal types don't require a material, colors, and vertices. if (_res.Type != SsPartType.Normal && _res.Type != SsPartType.Bound) { return; } // shortcut #if _USE_UNIFIED_SHADER _useUnifiedShader = _res.imageFile.useUnifiedShader; #endif _useCgShader = (SystemInfo.graphicsShaderLevel >= 20); if (_res.Type == SsPartType.Bound) { #if !_BOUND_PART_DRAW_AS_INVALID // set vertex color to transparent red. // this alpha value will be overwritten in AlphaValue property later. _vertexColor = new Color(1, 0, 0, 1); for (int i = 0; i < 4; ++i) { // set UVs to a point at left-top. _mgr._uvs[_vIndex + i] = Vector2.zero; // set vertex colors _mgr._colors[_vIndex + i] = _vertexColor; } // invisible is default. _visible = false; #else _visible = _mgr.DrawBoundingParts; #endif } else { // default vertex color _vertexColor = new Color(1, 1, 1, 1); for (int i = 0; i < 4; ++i) { // set UVs. use precalculated UVs, it is stored clockwise _mgr._uvs[_vIndex + i] = _res.UVs[i]; // set vertex colors _mgr._colors[_vIndex + i] = _vertexColor; } // set blend type and _shaderType ColorBlendType = SsColorBlendOperation.Non; } // set boolean about having transparency if (_res.Type == SsPartType.Bound) { #if _BOUND_PART_DRAW_AS_INVALID // become purple that mean invalid. _material = null; #else // needs any appropriate material _hasTransparency = true; AlphaValue = 0.5f; #endif } else { _hasTransparency = _res.HasTrancparency || (_parent != null && _res.Inherits(SsKeyAttr.Trans)); // always inherits parent's alpha whether the immediate parent has transparency or not. 2012.12.19 bug fixed // set alpha value AlphaValue = _res.Trans(0); // set appropriate material. _shaderType was set inside ColorBlendType property. _material = imageFile.GetMaterial(_shaderType); } //--------- calculates various info... Update(true); // set triangle indices. never changed so far. #if _USE_TRIANGLE_STRIP _triIndices = new int[] { _vIndex + 0, _vIndex + 1, _vIndex + 3, _vIndex + 2 }; // order is LT->RT->LB->RB. #else _triIndices = new int[] { _vIndex + 0, _vIndex + 1, _vIndex + 2, _vIndex + 2, _vIndex + 3, _vIndex + 0 }; // order is LT->RT->RB->RB->LB->LT #endif SetToSubmeshArray(_index - 1); }