Esempio n. 1
0
    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);
    }
Esempio n. 2
0
    UpdateSub(SsPartRes res, int frame, bool initialize = false)
    {
        // priority
        if (res.HasAttrFlags(SsKeyAttrFlags.Prio))
        {
            int nowPrio = (int)res.Prio(frame);
            if (_priority != nowPrio)
            {
                _priority         = nowPrio;
                _mgr._prioChanged = true;
            }
        }

        // visibility
        if (res.HasAttrFlags(SsKeyAttrFlags.Hide))
        {
            if (res.IsRoot)
            {
                _visible = !res.Hide(frame);
            }
            else
            if (res.Type == SsPartType.Normal)
            {
                bool nowVisible;
                if (res.IsBeforeFirstKey(frame))
                {
                    nowVisible = false;
                }
                else
                {
                    if (_parent != null &&
                        !_parent._res.IsRoot &&
                        (res.InheritRate(SsKeyAttr.Hide) > 0.5f))
                    {
                        nowVisible = _parent._visible;
                    }
                    else
                    {
                        nowVisible = !res.Hide(frame);
                    }
                }
#if _INHERITS_FORCE_VISIBLE
                if (_forceVisibleAvailable)
                {
                    nowVisible = _forceVisible;
                }
#endif
                if (nowVisible != _visible)
                {
                    Show(nowVisible);
                }
            }
        }

        // vertex color
        if (res.HasAttrFlags(SsKeyAttrFlags.PartsCol))
        {
            SsColorBlendKeyValue  cbk   = res.PartsCol(frame);
            SsColorBlendOperation cbkOp = ColorBlendType;
            if (cbk == null)
            {
                if (_colorBlendKeyValue != null)
                {
                    // set back default color
                    cbkOp = SsColorBlendOperation.Non;
                    for (int i = 0; i < 4; ++i)
                    {
                        _mgr._colors[_vIndex + i] = _vertexColor;
                    }
                    _mgr._colorChanged = true;
                }
            }
            else
            {
                cbkOp = cbk.Operation;
                if (cbk.Target == SsColorBlendTarget.Vertex)
                {
                    // vertex colors
                    for (int i = 0; i < 4; ++i)
                    {
                        _mgr._colors[_vIndex + i] = GetBlendedColor(cbk.Colors[i], cbk.Operation);
                    }
                }
                else
                {
                    // affect a color to overall, so it doesn't inidicate that this is not vertex color.
                    Color c = GetBlendedColor(cbk.Colors[0], cbk.Operation);
                    for (int i = 0; i < 4; ++i)
                    {
                        _mgr._colors[_vIndex + i] = c;
                    }
                }
                _mgr._colorChanged = true;
            }
            _colorBlendKeyValue = cbk;

            if (_mgr._colorChanged)
            {
                if (cbkOp != ColorBlendType)
                {
                    // change other shader
                    ColorBlendType = cbkOp;
                    // place stored alpha is variable with color blend type. where is simply in color.a if blend is none.
                    AlphaValue = AlphaValue;
                }
            }
        }

        // transparency
        if (_hasTransparency)
        {
            float nowAlpha = res.Trans(frame);
            if (_parent != null && res.Inherits(SsKeyAttr.Trans))
            {
                float parentAlpha;
                // if parent is root, it doesn't have material.
                if (_parent._material == null)
                {
                    parentAlpha = _parent._res.Trans(frame);
                }
                else
                {
                    parentAlpha = _parent.AlphaValue;
                }
                // just multiply simply
                nowAlpha = parentAlpha * nowAlpha;
            }
            if (_forceAlphaAvailable)
            {
                nowAlpha = _forceAlpha;
            }
            if (nowAlpha != AlphaValue)
            {
                AlphaValue = nowAlpha;
            }
        }

        // scale
        if (res.HasAttrFlags(SsKeyAttrFlags.Scale))
        {
            var scale = new Vector3(res.ScaleX(frame), res.ScaleY(frame), 1f);
            if (scale != _scale)
            {
                _scale            = scale;
                _mgr._vertChanged = true;
            }
        }

        // rotation (now supports only Z axis)
        if (res.HasAttrFlags(SsKeyAttrFlags.Angle))
        {
            var ang = res.Angle(frame);
            // SpriteStudio demands me to Z axis rotation consistently.
            if (_parent)
            {
                // reverse angle direction if parent part's scale is negative value.
                if (_parent._pivotMatrix.m00 * _parent._pivotMatrix.m11 < 0)
                {
                    ang *= -1;
                }
                if (_mgr.hFlip ^ _mgr.vFlip)
                {
                    ang *= -1;
                }
            }
            Quaternion rot = Quaternion.Euler(0, 0, ang);
            if (rot != _quaternion)
            {
                _quaternion       = rot;
                _mgr._vertChanged = true;
#if _MAKE_ROOT_TO_LOCAL_TRANSFORM
                _rotChanged = true;
#endif
            }
#if _MAKE_ROOT_TO_LOCAL_TRANSFORM
            else
            {
                _rotChanged = false;
            }
#endif
        }

        // translate
        if (res.HasAttrFlags(SsKeyAttrFlags.Pos))
        {
            var pos = new Vector3(res.PosX(frame), -res.PosY(frame));
#if false
            if (_parent != null)
            {
                if (_parent._flipH)
                {
                    pos.x *= -1;
                }
                if (_parent._flipV)
                {
                    pos.y *= -1;
                }
            }
#endif
#if _APPLY_ROOT_POS_AS_PIVOT
            // apply X,Y position as pivot if this is root.
            if (res.IsRoot)
            {
                pos += _rootPivot;
            }
#endif

#if false
            // update vertices when position is changed.
            if (_pos != pos)
#endif
            {
                _pos = pos;
                _mgr._vertChanged = true;
            }
        }

        bool orgVertChanged = false;

        // UV animation
        if (res.HasAttrFlags(SsKeyAttrFlags.ImageOffset))
        {
            int nowImgOfs = res.ImageOffsetX(frame);
            if (nowImgOfs != _imgOfsX)
            {
                _imgOfsX        = nowImgOfs;
                _mgr._uvChanged = true;
            }
            nowImgOfs = res.ImageOffsetY(frame);
            if (nowImgOfs != _imgOfsY)
            {
                _imgOfsY        = nowImgOfs;
                _mgr._uvChanged = true;
            }
            bool sizeChnaged = false;
            nowImgOfs = res.ImageOffsetW(frame);
            if (nowImgOfs != _imgOfsW)
            {
                _imgOfsW        = nowImgOfs;
                _mgr._uvChanged = true;
                sizeChnaged     = true;
            }
            nowImgOfs = res.ImageOffsetH(frame);
            if (nowImgOfs != _imgOfsH)
            {
                _imgOfsH        = nowImgOfs;
                _mgr._uvChanged = true;
                sizeChnaged     = true;
            }
            if (sizeChnaged)
            {
                // modify polygon size
                Vector2 size = res.PicArea.WH();
                size.x        += _imgOfsW;
                size.y        += _imgOfsH;
                _orgVertices   = res.GetVertices(size);
                orgVertChanged = true;
            }
            if (_mgr._uvChanged)
            {
                res.CalcUVs(_imgOfsX, _imgOfsY, _imgOfsW, _imgOfsH);
            }
        }

        // origin animation
        if (res.HasAttrFlags(SsKeyAttrFlags.OriginOffset))
        {
            int nowOrgOfsX = -res.OriginOffsetX(frame);
            if (nowOrgOfsX != _originOffset.x)
            {
                _originOffset.x = nowOrgOfsX;
                orgVertChanged  = true;
            }
            int nowOrgOfsY = res.OriginOffsetY(frame);
            if (nowOrgOfsY != _originOffset.y)
            {
                _originOffset.y = nowOrgOfsY;
                orgVertChanged  = true;
            }
        }

        if (res.HasAttrFlags(SsKeyAttrFlags.Vertex))
        {
            orgVertChanged = true;
        }

        // vertex modification
        if (orgVertChanged &&
            _vertPositions != null)
        {
            for (int i = 0; i < _vertPositions.Length; ++i)
            {
                _vertPositions[i] = _orgVertices[i];
                if (res.HasAttrFlags(SsKeyAttrFlags.Vertex))
                {
                    _vertPositions[i] += res.Vertex(frame).Vertex3(i);
                }
                if (res.HasAttrFlags(SsKeyAttrFlags.OriginOffset))
                {
                    _vertPositions[i] += _originOffset;
                }
            }
            orgVertChanged    = false;
            _mgr._vertChanged = true;
        }

        // flip image only. the setting is given from anime resource.
        bool dontFlipCoord = res.IsRoot ? false : _mgr._animation.hvFlipForImageOnly;

        // flip H
        bool nowFlipH = false;

        if (res.IsRoot)
        {
            nowFlipH = _mgr.hFlip;
        }
        else
        {
            if (dontFlipCoord)
            {
                if (_parent != null && res.Inherits(SsKeyAttr.FlipH))
                {
                    if (!_parent._res.IsRoot)
                    {
                        nowFlipH = _parent._flipH;
                    }
                }
            }
            if (res.FlipH(frame))
            {
                nowFlipH = !nowFlipH;
            }
        }

        if (!dontFlipCoord)
        {
            if ((nowFlipH && _scale.x > 0f) ||
                (!nowFlipH && _scale.x < 0f))
            {
                _scale.x         *= -1;
                _mgr._vertChanged = true;
            }
        }

        // flip V
        bool nowFlipV = false;

        if (res.IsRoot)
        {
            nowFlipV = _mgr.vFlip;
        }
        else
        {
            if (dontFlipCoord)
            {
                if (_parent != null && res.Inherits(SsKeyAttr.FlipV))
                {
                    if (!_parent._res.IsRoot)
                    {
                        nowFlipV = _parent._flipV;                              // 2012.06.27 fixed an issue that nowFlipV refers _parent._flipH
                    }
                }
            }
            if (res.FlipV(frame))
            {
                nowFlipV = !nowFlipV;
            }
        }
        if (!dontFlipCoord)
        {
            if ((nowFlipV && _scale.y > 0f) ||
                (!nowFlipV && _scale.y < 0f))
            {
                _scale.y         *= -1;
                _mgr._vertChanged = true;
            }
        }

        if (nowFlipH != _flipH ||
            nowFlipV != _flipV)
        {
            _flipH = nowFlipH;
            _flipV = nowFlipV;
            if (dontFlipCoord)
            {
                _mgr._uvChanged = true;
            }
        }

        // udpate uv indices
        if (_mgr._uvChanged &&
            res.UVs != null &&          // root part has no UVs
            res.UVs.Length == 4)
        {
            if (dontFlipCoord)
            {
                int index = -1;
                if (nowFlipV)
                {
                    index = 1;
                }
                if (nowFlipH)
                {
                    ++index;
                }
                for (int i = 0; i < 4; ++i)
                {
                    _mgr._uvs[_vIndex + i] = res.UVs[index >= 0 ? _flippedUvIndices[index, i] : i];
                }
            }
            else
            {
                for (int i = 0; i < 4; ++i)
                {
                    _mgr._uvs[_vIndex + i] = res.UVs[i];
                }
            }
        }

        // update vertex buffer
        if (_mgr._vertChanged)
        {
            // udpate matrix
            var p = _pos;
            var s = _scale;
            if (_parent)
            {
                // previously apply compensated value if this doesn't want to inherit parent's value.
                if (!res.Inherits(SsKeyAttr.ScaleX))
                {
                    s.x /= _parent._scale.x;
                    p.x /= _parent._scale.x;
                }
                if (!res.Inherits(SsKeyAttr.ScaleY))
                {
                    s.y /= _parent._scale.y;
                    p.y /= _parent._scale.y;
                }
            }
            _pivotMatrix.SetTRS(p, _quaternion, s);

            // multiply parent's
            if (_parent)
            {
                _pivotMatrix = _parent._pivotMatrix * _pivotMatrix;
            }

            if (_vertPositions != null)
            {
                // apply matrix to vertices
                for (int i = 0; i < _vertPositions.Length; ++i)
                {
                    Vector3 v = _pivotMatrix.MultiplyPoint3x4(_vertPositions[i]);
                    _mgr._vertices[_vIndex + i] = v;
                }
        #if false
                if (_drawPartsRect)
                {
                    // get rectangle from bounding box.
                    Vector3 lt = _vertTransforms[0].position;
                    Vector3 rb = _vertTransforms[2].position;
                    Vector3 rt = lt;
                    rt.x = rb.x;
                    Vector3 lb = lt;
                    lb.y = rb.y;
                    // draw rectangle
                    Debug.DrawLine(lt, rt, Color.red);
                    Debug.DrawLine(rt, rb, Color.red);
                    Debug.DrawLine(rb, lb, Color.red);
                    Debug.DrawLine(lb, lt, Color.red);
                }
        #endif
            }
        }

        if (_transform)
        {
#if _MAKE_ROOT_TO_LOCAL_TRANSFORM
            // update quaternion in root space and my transform
            if (_parent != null && _parent._rotChanged)
            {
                // apply parent's rotation on ahead
                _rootSpaceQuaternion = _quaternion * _parent._quaternion;
                UpdateRootTransform();
            }
            else
#endif
            if (_mgr._vertChanged)
            {
                // update transform in this part's local space.
                _transform.localPosition = _pos;
                _transform.localRotation = _quaternion;
                _transform.localScale    = _scale;
            }
        }

        // ignore when called from initializing.
        if (initialize)
        {
            return;
        }

        // do callback at userdata key
        if (ExistsOnUserDataKey &&
            _res.HasAttrFlags(SsKeyAttrFlags.User))
        {
            _OnEvent(SsKeyAttr.User);
        }

        // do callback at sound key
        if (ExistsOnSoundKey &&
            _res.HasAttrFlags(SsKeyAttrFlags.Sound))
        {
            _OnEvent(SsKeyAttr.Sound);
        }
    }