using System;
using CommonUI.Display;
using CommonLang;
namespace CommonUI.Cell.Game
{
public class CSpriteMeta
{
public const byte CD_TYPE_MAP = 0;
public const byte CD_TYPE_ATK = 1;
public const byte CD_TYPE_DEF = 2;
public const byte CD_TYPE_EXT = 3;
private SpriteSet data;
private CAnimates animates;
private CCollides collides;
private int animCount;
private int[] frameCounts;
//frameAnimate[animate id][frame id] = canimate frame index.
private string[] AnimateNames;
//
private int[][] FrameAnimate;
// frameAnimate[animate id][frame id] = ccollide frame index.
private int[][] FrameCDMap;
// frameAnimate[animate id][frame id] = ccollide frame index.
private int[][] FrameCDAtk;
// frameAnimate[animate id][frame id] = ccollide frame index.
private int[][] FrameCDDef;
// frameAnimate[animate id][frame id] = ccollide frame index.
private int[][] FrameCDExt;
private float[][] FrameAlpha;
public CAnimates Animates { get { return animates; } }
public CCollides Collides { get { return collides; } }
public SpriteSet Data { get { return data; } }
public CPJAtlas Atlas { get { return animates.tiles; } }
public CSpriteMeta(SpriteSet tsprite, CPJAtlas tiles)
{
this.data = tsprite;
{
//scene parts
int scenePartCount = tsprite.PartTileID.Length; // --> u16
CAnimates animates = new CAnimates(scenePartCount, tiles);
for (int i = 0; i < scenePartCount; i++)
{
animates.setPart(i,
tsprite.PartX[i],
tsprite.PartY[i],
tsprite.PartTileID[i],
tsprite.PartTileTrans[i],
tsprite.PartAlpha[i],
tsprite.PartRotate[i],
tsprite.PartScaleX[i],
tsprite.PartScaleY[i]);
}
//scene frames
animates.setFrames(tsprite.Parts);
//cd parts
int cdCount = tsprite.BlocksMask.Length; // --> u16
CCollides collides = new CCollides(cdCount);
for (int i = 0; i < cdCount; i++)
{
collides.setCDRect(i,
tsprite.BlocksMask[i],
tsprite.BlocksX1[i],
tsprite.BlocksY1[i],
tsprite.BlocksW[i],
tsprite.BlocksH[i]);
}
//cd frames
collides.setFrames(tsprite.Blocks);
this.animates = animates;
this.collides = collides;
}
{
animCount = tsprite.AnimateCount;
frameCounts = new int[animCount];
AnimateNames = tsprite.AnimateNames;
FrameAnimate = new int[animCount][];
FrameCDMap = new int[animCount][];
FrameCDAtk = new int[animCount][];
FrameCDDef = new int[animCount][];
FrameCDExt = new int[animCount][];
FrameAlpha = new float[animCount][];
for (int a = 0; a < animCount; a++)
{
int fc = tsprite.FrameAnimate[a].Length;
frameCounts[a] = fc;
FrameAnimate[a] = new int[fc];
FrameCDMap[a] = new int[fc];
FrameCDAtk[a] = new int[fc];
FrameCDDef[a] = new int[fc];
FrameCDExt[a] = new int[fc];
FrameAlpha[a] = new float[fc];
for (int f = 0; f < fc; f++)
{
FrameAnimate[a][f] = tsprite.FrameAnimate[a][f];
FrameCDMap[a][f] = tsprite.FrameCDMap[a][f];
FrameCDAtk[a][f] = tsprite.FrameCDAtk[a][f];
FrameCDDef[a][f] = tsprite.FrameCDDef[a][f];
FrameCDExt[a][f] = tsprite.FrameCDExt[a][f];
FrameAlpha[a][f] = tsprite.FrameAlpha[a][f];
}
}
}
}
// ------------------------------------------------------------------------------------------
public int getFrameImageCount(int anim, int frame = 0)
{
return animates.getComboFrameCount(FrameAnimate[anim][frame]);
}
public int getFrameTileID(int anim, int frame = 0, int sub = 0)
{
return animates.getFrameTileID(FrameAnimate[anim][frame], sub);
}
public float getFrameImageX(int anim, int frame = 0, int sub = 0)
{
return animates.getFrameX(FrameAnimate[anim][frame], sub);
}
public float getFrameImageY(int anim, int frame = 0, int sub = 0)
{
return animates.getFrameY(FrameAnimate[anim][frame], sub);
}
public float getFrameImageWidth(int anim, int frame = 0, int sub = 0)
{
return animates.getFrameW(FrameAnimate[anim][frame], sub);
}
public float getFrameImageHeight(int anim, int frame = 0, int sub = 0)
{
return animates.getFrameH(FrameAnimate[anim][frame], sub);
}
public Trans getFrameImageTransform(int anim, int frame = 0, int sub = 0)
{
return animates.getFrameTransform(FrameAnimate[anim][frame], sub);
}
public int getAvaliableTileID()
{
for (int anim = 0; anim < getAnimateCount(); anim++)
{
for (int frame = 0; frame < getFrameCount(anim); frame++)
{
for (int sub = 0; sub < getFrameImageCount(anim, frame); sub++)
{
int tid = getFrameTileID(anim, frame, sub);
if (!Atlas.IsNullTile(tid))
{
return tid;
}
}
}
}
return 0;
}
// ------------------------------------------------------------------------------------------
public int[][] getCDAnimates(byte type)
{
switch (type)
{
case CD_TYPE_MAP:
return FrameCDMap;
case CD_TYPE_ATK:
return FrameCDAtk;
case CD_TYPE_DEF:
return FrameCDDef;
case CD_TYPE_EXT:
return FrameCDExt;
}
return null;
}
public int getFrameCDCount(int anim, int frame, byte type)
{
int[][] out_animates = getCDAnimates(type);
if (out_animates != null)
{
return collides.getComboFrameCount(out_animates[anim][frame]);
}
return -1;
}
public CCD getFrameCD(int anim, int frame, byte type, int sub)
{
int[][] out_animates = getCDAnimates(type);
if (out_animates != null)
{
return collides.getFrameCD(out_animates[anim][frame], sub);
}
return null;
}
// ------------------------------------------------------------------------------------------
public CCD getVisibleBounds()
{
return animates.getAllBounds();
}
public CCD getVisibleBounds(int anim, int frame)
{
if (anim < animCount)
{
if (frame < frameCounts[anim])
{
CCD out_bounds = new CCD();
out_bounds.X1 = float.MaxValue;
out_bounds.X2 = float.MinValue;
out_bounds.Y1 = float.MaxValue;
out_bounds.Y2 = float.MinValue;
int frameid = FrameAnimate[anim][frame];
int count = animates.getComboFrameCount(frameid);
for (int i = 0; i < count; i++)
{
out_bounds.X1 = Math.Min(out_bounds.X1, animates.getFrameX(frameid, i));
out_bounds.Y1 = Math.Min(out_bounds.Y1, animates.getFrameY(frameid, i));
out_bounds.X2 = Math.Max(out_bounds.X2, animates.getFrameX(frameid, i) + animates.getFrameW(frameid, i));
out_bounds.Y2 = Math.Max(out_bounds.Y2, animates.getFrameY(frameid, i) + animates.getFrameH(frameid, i));
}
return out_bounds;
}
}
return null;
}
public CCD getVisibleBounds(int anim)
{
if (anim < animCount)
{
CCD out_bounds = new CCD();
out_bounds.X1 = float.MaxValue;
out_bounds.X2 = float.MinValue;
out_bounds.Y1 = float.MaxValue;
out_bounds.Y2 = float.MinValue;
for (int f = getFrameCount(anim) - 1; f >= 0; --f)
{
int frameid = FrameAnimate[anim][f];
int count = animates.getComboFrameCount(frameid);
for (int i = 0; i < count; i++)
{
out_bounds.X1 = Math.Min(out_bounds.X1, animates.getFrameX(frameid, i));
out_bounds.Y1 = Math.Min(out_bounds.Y1, animates.getFrameY(frameid, i));
out_bounds.X2 = Math.Max(out_bounds.X2, animates.getFrameX(frameid, i) + animates.getFrameW(frameid, i));
out_bounds.Y2 = Math.Max(out_bounds.Y2, animates.getFrameY(frameid, i) + animates.getFrameH(frameid, i));
}
}
return out_bounds;
}
return null;
}
public CCD getCDBounds()
{
return collides.getAllBounds();
}
public int getAnimateIndex(string animate_name)
{
for (int i = animCount - 1; i >= 0; --i)
{
if (string.Equals(AnimateNames[i], animate_name))
{
return i;
}
}
return -1;
}
public string getAnimateName(int anim)
{
return AnimateNames[anim];
}
public int getAnimateCount()
{
return animCount;
}
public int getFrameCount(int anim)
{
return frameCounts[anim];
}
public void render(Graphics g, int anim, int frame, float dx = 0, float dy = 0)
{
if ((anim < animCount) && (frame < frameCounts[anim]))
{
float olda = g.getAlpha();
g.addAlpha(FrameAlpha[anim][frame]);
animates.render(g, FrameAnimate[anim][frame], dx, dy);
g.setAlpha(olda);
}
}
public void addVertex(VertexBuffer v, int anim, int frame, float dx, float dy)
{
if ((anim < animCount) && (frame < frameCounts[anim]))
{
animates.addVertex(v, FrameAnimate[anim][frame], dx, dy);
}
}
public void beginImage(Graphics g)
{
animates.beginImage(g);
}
}
public struct TSpriteMetaAnimateFrame
{
public CSpriteMeta sprite;
public int anim, frame;
}
///
/// CPJSprite 控制类
///
public class CSpriteController : ICellSpriteController
{
private readonly CSpriteMeta mMeta;
private int mCurAnimate = 0;
private int mCurFrame = 0;
private int mPlayTimes = -1;
private int mCurrentPlayTimes = 0;
public bool IsAutoPlay = true;
public CSpriteController(CSpriteMeta src)
{
mMeta = src;
}
public bool Update()
{
if (IsAutoPlay)
{
NextCycFrame();
PlayTimesTick();
return true;
}
return false;
}
public void Dispose()
{
IsAutoPlay = false;
m_FinishCallback = null;
}
public CSpriteMeta Meta
{
get { return mMeta; }
}
public int CurrentFrame
{
get { return mCurFrame; }
}
public int CurrentAnimate
{
get { return mCurAnimate; }
}
public bool IsEndFrame
{
get
{
if (mCurFrame + 1 >= mMeta.getFrameCount(mCurAnimate))
{
return true;
}
else
{
return false;
}
}
}
public void SetCurrentAnimate(string anim_name)
{
int anim = mMeta.getAnimateIndex(anim_name);
if (anim >= 0)
{
SetCurrentAnimate(anim);
}
}
public void SetCurrentAnimate(int anim)
{
mCurAnimate = anim;
mCurAnimate = CMath.cycNum(mCurAnimate, 0, mMeta.getAnimateCount());
mCurFrame = CMath.cycNum(mCurFrame, 0, mMeta.getFrameCount(mCurAnimate));
}
public void SetCurrentFrame(int anim, int index)
{
mCurAnimate = CMath.cycNum(anim, 0, mMeta.getAnimateCount());
mCurFrame = CMath.cycNum(index, 0, mMeta.getFrameCount(mCurAnimate));
}
public bool NextFrame()
{
mCurFrame++;
int acount = mMeta.getFrameCount(mCurAnimate);
if (mCurFrame >= acount)
{
mCurFrame = acount - 1;
return true;
}
else
{
return false;
}
}
public void NextCycFrame()
{
mCurFrame++;
int acount = mMeta.getFrameCount(mCurAnimate);
if (acount > 0)
{
mCurFrame %= acount;
}
}
public void NextCycFrame(int restart)
{
mCurFrame++;
int acount = mMeta.getFrameCount(mCurAnimate);
if (mCurFrame < acount)
{
}
else
{
if (acount > 0)
{
mCurFrame = (restart % acount);
}
}
}
public bool PrewFrame()
{
mCurFrame--;
if (mCurFrame < 0)
{
mCurFrame = 0;
return true;
}
else
{
return false;
}
}
public void PrewCycFrame()
{
mCurFrame--;
if (mCurFrame < 0)
{
mCurFrame = mMeta.getFrameCount(mCurAnimate) - 1;
}
}
public void PrewCycFrame(int restart)
{
mCurFrame--;
if (mCurFrame < 0)
{
mCurFrame = (restart % mMeta.getFrameCount(mCurAnimate));
}
}
///
/// 播放动画:anim动画名、times次数(-1=无限).
///
///
///
///
public void PlayAnimate(int anim, int times, CSpriteEventHandler callBack)
{
mPlayTimes = times;
m_FinishCallback = callBack;
SetCurrentAnimate(anim);
mCurFrame = 0;
IsAutoPlay = true;
}
///
/// 播放动画:anim_name动画名、times次数(-1=无限).
///
///
///
///
public void PlayAnimate(string anim_name, int times, CSpriteEventHandler callBack)
{
int anim = mMeta.getAnimateIndex(anim_name);
if (anim >= 0)
{
PlayAnimate(anim, times, callBack);
}
}
public void StopAnimate(bool needCallBack)
{
IsAutoPlay = false;
if (m_FinishCallback != null && needCallBack)
{
m_FinishCallback(this);
}
m_FinishCallback = null;
}
private void PlayTimesTick()
{
if (mPlayTimes < 0) { return; }
if (!IsEndFrame) { return; }
mCurrentPlayTimes++;
if (mCurrentPlayTimes >= mPlayTimes)
{
IsAutoPlay = false;
if (m_FinishCallback != null)
{
CSpriteEventHandler temp = m_FinishCallback;
m_FinishCallback = null;
temp(this);
temp = null;
}
}
}
//---------------------------------------------------------------------------------------------------
private CSpriteEventHandler m_FinishCallback;
public event CSpriteEventHandler Finish { add { m_FinishCallback += value; } remove { m_FinishCallback -= value; } }
//---------------------------------------------------------------------------------------------------
}
///
/// 动画编辑器控制类
///
public interface ICellSpriteController
{
int CurrentFrame { get; }
int CurrentAnimate { get; }
bool IsEndFrame { get; }
void SetCurrentAnimate(string anim);
void SetCurrentAnimate(int anim);
void SetCurrentFrame(int anim, int index);
bool NextFrame();
void NextCycFrame();
void NextCycFrame(int restart);
bool PrewFrame();
void PrewCycFrame();
void PrewCycFrame(int restart);
}
public delegate void CSpriteEventHandler(ICellSpriteController sender);
}