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); } }
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); }