using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.IO;
using System.Threading;
using Mars_Mission;
namespace Sprite
{
public enum enuMirror { none, vertical, horizontal, VerticalAndHorizontal }
public struct udtSprite_StorageRetrieval
{
public string myName;
public udtLimb_StorageRetrieval[] limbs;
public int intImagesPerRotation;
}
public struct udtLimb_StorageRetrieval
{
public string myName;
public Bitmap[] bmp;
public bool IRotate;
public bool AlwaysVertical;
public classMath.classRadialCoor radMaster;
public int MasterIndex;
public classMath.classRadialCoor radSlave;
public string hingeName;
public int intNumImagesPerQuarterRotation;
}
class formGenerateFirstQuarterImages : Form
{
classSpriteLimb limb;
Bitmap[] bmpSpriteLimb;
Bitmap bmpOriginal;
ProgressBar proBar = new ProgressBar();
System.Windows.Forms.Timer tmrGenerateFirstQuarterImagesFromOriginal = new System.Windows.Forms.Timer();
int intImageCounter = 1;
Label lbl = new Label();
public formGenerateFirstQuarterImages(ref classSpriteLimb Limb, Bitmap BmpOriginal)
{
limb = Limb;
ShowInTaskbar = false;
FormBorderStyle = FormBorderStyle.None;
bmpOriginal = BmpOriginal;
Controls.Add(proBar);
Controls.Add(lbl);
BackColor
= lbl.BackColor
= proBar.BackColor
= Color.Teal;
ForeColor
= lbl.ForeColor
= proBar.ForeColor
= Color.Black;
if (limb.IRotate)
{
if (bmpSpriteLimb == null)
bmpSpriteLimb = new Bitmap[(int)limb.mainSprite.ImagesPerRotation];
bmpSpriteLimb[0] = bmpOriginal;
limb.bmpSpriteLimb = bmpSpriteLimb;
limb.myCurrentImage = bmpSpriteLimb[0];
}
else
{
bmpSpriteLimb = new Bitmap[(int)limb.mainSprite.ImagesPerRotation];
}
tmrGenerateFirstQuarterImagesFromOriginal.Interval = 5;
tmrGenerateFirstQuarterImagesFromOriginal.Tick += new EventHandler(tmrGenerateFirstQuarterImagesFromOriginal_Tick);
VisibleChanged += new EventHandler(formGenerateFirstQuarterImages_VisibleChanged);
}
void tmrGenerateFirstQuarterImagesFromOriginal_Tick(object sender, EventArgs e)
{
tmrGenerateFirstQuarterImagesFromOriginal.Enabled = false;
Color clrTransparent = bmpSpriteLimb[0].GetPixel(0, 0);
double dblRotationAngle = 0;
dblRotationAngle = Math.PI + (Math.PI * (double)intImageCounter / (limb.mainSprite.ImagesPerRotation / 2));
bmpSpriteLimb[intImageCounter] = rotate(bmpSpriteLimb[0], dblRotationAngle);
intImageCounter++;
proBar.Value = intImageCounter;
if (intImageCounter < (int)(limb.mainSprite.ImagesPerRotation / 4))
tmrGenerateFirstQuarterImagesFromOriginal.Enabled = true;
else
Dispose();
}
void formGenerateFirstQuarterImages_VisibleChanged(object sender, EventArgs e)
{
if (Visible)
{
Width = (int)(Screen.PrimaryScreen.WorkingArea.Width * .6);
Height = proBar.Height + lbl.Height;
lbl.Top = 0;
lbl.Left = 0;
lbl.Width
= proBar.Width
= Width;
proBar.Top = lbl.Top + lbl.Height;
proBar.Maximum = (int)(limb.mainSprite.ImagesPerRotation / 4);
proBar.Value = intImageCounter;
Left = (Screen.PrimaryScreen.WorkingArea.Width - Width) / 2;
Top = (Screen.PrimaryScreen.WorkingArea.Height - Height) / 2;
lbl.Text = "Rotating images for limb \"" + limb.Name + "\".";
if (limb.IRotate)
tmrGenerateFirstQuarterImagesFromOriginal.Enabled = true;
else
Dispose();
}
}
Bitmap rotate(Bitmap bmpInput, double dblAngleRotation)
{
int intMinSquare = bmpInput.Width > bmpInput.Height
? 3 * bmpInput.Width
: 3 * bmpInput.Height;
Color clrHole = Color.YellowGreen; // some color assumed NOT in the input bmp
Bitmap bmpCopy = new Bitmap(intMinSquare, intMinSquare);
Point ptTL;
Point ptBR;
Point ptCopyCenter = new Point(bmpCopy.Width / 2, bmpCopy.Height / 2);
Point ptOriginalCenter = new Point(bmpInput.Width / 2, bmpInput.Height / 2);
using (Graphics g = Graphics.FromImage(bmpCopy))
{
g.FillRectangle(new SolidBrush(clrHole), new Rectangle(new Point(0, 0), bmpCopy.Size));
ptTL = new Point(ptCopyCenter.X, ptCopyCenter.Y);
ptBR = new Point(ptCopyCenter.X, ptCopyCenter.Y);
for (int intX = 0; intX < bmpInput.Width; intX++)
{
for (int intY = 0; intY < bmpInput.Height; intY++)
{
int intDX = ptOriginalCenter.X - intX;
int intDY = ptOriginalCenter.Y - intY;
classMath.classRadialCoor udrOriginalRad = new classMath.classRadialCoor(classMath.arcTan(intDX, intDY), Math.Sqrt(intDX * intDX + intDY * intDY));
classMath.classRadialCoor udrCopyRad = new classMath.classRadialCoor(udrOriginalRad.angle + dblAngleRotation, udrOriginalRad.radius);
Point ptCopy = new Point((int)(ptCopyCenter.X + udrCopyRad.radius * Math.Cos(udrCopyRad.angle)),
(int)(ptCopyCenter.Y + udrCopyRad.radius * Math.Sin(udrCopyRad.angle)));
try { bmpCopy.SetPixel(ptCopy.X, ptCopy.Y, bmpInput.GetPixel(intX, intY)); }
catch (Exception) { }
// keep track of limits of output image
if (ptCopy.X < ptTL.X)
ptTL.X = ptCopy.X;
if (ptCopy.Y < ptTL.Y)
ptTL.Y = ptCopy.Y;
if (ptCopy.X > ptBR.X)
ptBR.X = ptCopy.X;
if (ptCopy.Y > ptBR.Y)
ptBR.Y = ptCopy.Y;
}
}
}
// write image to output array
Size szOfImage = new Size(ptBR.X - ptTL.X, ptBR.Y - ptTL.Y);
Rectangle recSrc = new Rectangle(ptTL, szOfImage);
Rectangle recDest = new Rectangle(new Point(0, 0), szOfImage);
// fill the blanks missed when rotating image
// scanning x from 0 to width created a problem in the fill-blank
for (int intX = ptTL.X; intX < ptBR.X; intX++)
for (int intY = ptTL.Y; intY < ptBR.Y; intY++)
{
Color clrTest = bmpCopy.GetPixel(intX, intY);
if (clrTest.A == clrHole.A
&& clrTest.R == clrHole.R
&& clrTest.G == clrHole.G
&& clrTest.B == clrHole.B)
{
classPixilateColorFind[] udrColorFind = new classPixilateColorFind[0];
if (intX > 0 && intX < bmpCopy.Width - 2 && intY > 0 && intY < bmpCopy.Height - 2)
{
Point ptUp = new Point(intX, intY - 1);
Point ptDown = new Point(intX, intY + 1);
Point ptLeft = new Point(intX - 1, intY);
Point ptRight = new Point(intX + 1, intY);
Point ptUL = new Point(intX - 1, intY - 1);
Point ptUR = new Point(intX + 1, intY - 1);
Point ptDR = new Point(intX + 1, intY + 1);
Point ptDL = new Point(intX - 1, intY + 1);
addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptUp.X, ptUp.Y));
addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptDown.X, ptDown.Y));
addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptLeft.X, ptLeft.Y));
addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptRight.X, ptRight.Y));
addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptDL.X, ptDL.Y));
addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptDR.X, ptDR.Y));
addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptUL.X, ptUL.Y));
addPixilateColorFound(ref udrColorFind, bmpCopy.GetPixel(ptUR.X, ptUR.Y));
reorderPixilateColorFound(ref udrColorFind);
if (udrColorFind[0].numFound >= 2)
try { bmpCopy.SetPixel(intX, intY, udrColorFind[0].clr); }
catch (Exception) { }
else
{
int intDX = ptCopyCenter.X - intX;
int intDY = ptCopyCenter.Y - intY;
classMath.classRadialCoor udrOriginalRad = new classMath.classRadialCoor(classMath.arcTan(intDX, intDY), Math.Sqrt(intDX * intDX + intDY * intDY));
classMath.classRadialCoor udrCopyRad = new classMath.classRadialCoor(udrOriginalRad.angle - dblAngleRotation, udrOriginalRad.radius);
Point ptCopy = new Point((int)(ptOriginalCenter.X + udrCopyRad.radius * Math.Cos(udrCopyRad.angle)),
(int)(ptOriginalCenter.Y + udrCopyRad.radius * Math.Sin(udrCopyRad.angle)));
if (ptCopy.X >= 0 && ptCopy.X < bmpCopy.Width && ptCopy.Y >= 0 && ptCopy.Y < bmpCopy.Height)
try { bmpCopy.SetPixel(intX, intY, bmpInput.GetPixel(ptCopy.X, ptCopy.Y)); }
catch (Exception) { }
}
classPixilateColorFind.clear();
}
}
}
if (recDest.Width < 1)
recDest.Width = 1;
if (recDest.Height < 1)
recDest.Height = 1;
Bitmap bmpTemp = new Bitmap(recDest.Width, recDest.Height);
using (Graphics g = Graphics.FromImage(bmpTemp))
{
g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, bmpTemp.Width, bmpTemp.Height));
bmpCopy.MakeTransparent(bmpCopy.GetPixel(0, 0));
g.DrawImage(bmpCopy, recDest, recSrc, GraphicsUnit.Pixel);
}
return bmpTemp;
}
private void addPixilateColorFound(ref classPixilateColorFind[] udrPixilateColorFind, Color clrFound)
{
if (udrPixilateColorFind == null)
{
udrPixilateColorFind = new classPixilateColorFind[1];
udrPixilateColorFind[0] = classPixilateColorFind.getPixilateColorFind();
udrPixilateColorFind[0].clr = clrFound;
udrPixilateColorFind[0].numFound = 1;
}
else
{
for (int intClrCounter = 0; intClrCounter < udrPixilateColorFind.Length; intClrCounter++)
if (udrPixilateColorFind[intClrCounter].clr == clrFound)
{
udrPixilateColorFind[intClrCounter].numFound++;
return;
}
Array.Resize<classPixilateColorFind>(ref udrPixilateColorFind, udrPixilateColorFind.Length + 1);
udrPixilateColorFind[udrPixilateColorFind.Length - 1] = classPixilateColorFind.getPixilateColorFind();
udrPixilateColorFind[udrPixilateColorFind.Length - 1].clr = clrFound;
udrPixilateColorFind[udrPixilateColorFind.Length - 1].numFound = 1;
}
}
void reorderPixilateColorFound(ref classPixilateColorFind[] udrPixilateColorFind)
{
int intBestFind;
for (int intOuterLoop = 0; intOuterLoop < udrPixilateColorFind.Length - 1; intOuterLoop++)
{
intBestFind = intOuterLoop;
for (int intInnerLoop = intOuterLoop + 1; intInnerLoop < udrPixilateColorFind.Length; intInnerLoop++)
{
if (udrPixilateColorFind[intInnerLoop].numFound > udrPixilateColorFind[intBestFind].numFound)
intBestFind = intInnerLoop;
}
if (intBestFind != intOuterLoop)
{
classPixilateColorFind udrTemp = udrPixilateColorFind[intOuterLoop];
udrPixilateColorFind[intOuterLoop] = udrPixilateColorFind[intBestFind];
udrPixilateColorFind[intBestFind] = udrTemp;
}
}
}
}
/// <summary>
/// a hinge connects to limbs together
/// radial coordinates are relative to the center of each image
/// the slave's master coordinate is place at the same location as its master's slave coordinate onto the screen
/// </summary>
public class classSpriteHinge
{
public classSprite mainSprite;
string myName;
public bool bolFlag = true;
public int intMyHingeIndex;
public string name { get { return myName; } }
double myAngle;
/// <summary>
/// angle of slave limb relative to angle of master limb
/// </summary>
public double Angle
{
get { return myAngle; }
set
{
double dblTestAngle = value - (Math.PI / mainSprite.ImagesPerRotation);
if (dblTestAngle < 0)
dblTestAngle += (Math.PI * 2.0);
int intDir = (int)(Math.Ceiling(dblTestAngle / (Math.PI / (mainSprite.ImagesPerRotation / 2))));
myAngle = intDir * Math.PI / (mainSprite.ImagesPerRotation / 2);
}
}
public classSpriteHinge(string name) { myName = name; }
/// <summary>
/// a hinge connects to limbs together
/// radial coordinates are relative to the center of each image
/// the slave's master coordinate is place at the same location as its master's slave coordinate onto the screen
/// </summary>
/// <param name="name">name of this hinge, e.g. "elbow"</param>
/// <param name="RadCoor_Master">radial coordinate (radians, pixels) of location of joint on master image relative to center</param>
/// <param name="RadCoor_Slave">radial coordinate (radians, pixels) of location of joint on slave image relative to center</param>
/// <param name="LimbMaster">pointer to Master-Limb</param>
/// <param name="LimbSlave">pointer to Slave-Limb</param>
public classSpriteHinge(string name, classMath.classRadialCoor RadCoor_Master, classMath.classRadialCoor RadCoor_Slave, classSpriteLimb LimbMaster, classSpriteLimb LimbSlave)
{
cRadCoor_Master = RadCoor_Master;
cRadCoor_Slave = RadCoor_Slave;
classLimb_Master = LimbMaster;
classLimb_Slave = LimbSlave;
myName = name;
}
classMath.classRadialCoor cRadCoor_Master;
/// <summary>
/// radial coordinate location relative to center of image
/// </summary>
public classMath.classRadialCoor RadCoor_Master
{
get { return cRadCoor_Master; }
set { cRadCoor_Master = value; }
}
classMath.classRadialCoor cRadCoor_Slave;
/// <summary>
/// radial coordinate location relative to center of image
/// </summary>
public classMath.classRadialCoor RadCoor_Slave
{
get { return cRadCoor_Slave; }
set { cRadCoor_Slave = value; }
}
classSpriteLimb classLimb_Master;
/// <summary>
/// pointer to limb connected to this hinge
/// </summary>
public classSpriteLimb Limb_Master
{
get { return classLimb_Master; }
set { classLimb_Master = value; }
}
classSpriteLimb classLimb_Slave;
/// <summary>
/// pointer to limb connected to this hinge
/// </summary>
public classSpriteLimb Limb_Slave
{
get { return classLimb_Slave; }
set { classLimb_Slave = value; }
}
Point pt;
public Point Loc
{
get { return pt; }
set { pt = value; }
}
}
public class classSpriteLimb
{
public Sprite.classSprite mainSprite;
public bool bolFlag = true;
public Rectangle recDest;
public Bitmap myCurrentImage;
public classSpriteLimb[] mySlaveLimbs;
int intMySlaveID;
/// <summary>
/// my index in my master's slave limb array
/// </summary>
public int MySlaveID
{
get { return intMySlaveID; }
set { intMySlaveID = value; }
}
public int intMyLimbID;
bool bolAlwaysVertical = false;
/// <summary>
/// determines whether generated images are flipped to remain vertical or rotated 360 degrees
/// </summary>
public bool AlwaysVertical { get { return bolAlwaysVertical; } }
string myName;
public string Name { get { return myName; } }
Point ptLoc;
/// <summary>
/// location of top-left corner of image's rectangle
/// </summary>
public Point Loc
{
get { return ptLoc; }
set { ptLoc = value; }
}
int dir;
/// <summary>
/// 0-15 where 0 is east, 4 north, etc.
/// also corresponds to the bmpSpriteLimb's index of currently displayed image
/// </summary>
public int Dir
{
get { return dir; }
set { dir = value; }
}
double angle;
/// <summary>
/// at which this limb currently has on the screen
/// </summary>
public double Angle
{
get
{
return angle;
}
set { angle = value; }
}
/// <summary>
/// this limb's images
/// </summary>
public Bitmap[] bmpSpriteLimb;
bool bolIRotate = true;
/// <summary>
/// boolean variable which determines whether this limb rotates or animates
/// when true, SpriteLimbImages is expected to consist of N(num images per rotation) images
/// when false, SpriteLimbImages is either one or many images which are used to animate this limb
/// </summary>
public bool IRotate
{
get { return bolIRotate; }
set { bolIRotate = value; }
}
//bool bolIHaveNoMaster = false;
//public bool IHaveNoMaster { get { return bolIHaveNoMaster; } }
public classSpriteHinge MasterHinge;
/// <summary>
/// a limb consists of an array of images with their corresponding hinge locations
/// </summary>
/// <param name="IRotate">
/// when this is set the indices of udrSpriteLimbImage are direction of rotation, e.g. action-arm, these are created if not provided
/// when this is not set these are animation images, e.g. walking legs</param>
/// </param>
/// <param name="AlwaysVertical">
/// determines whether generated images are flipped to remain vertical or rotated 360 degrees
/// </param>
/// <param name="_myName">
/// used for ease of debugging e.g. "Torso", "left arm", "right hand"
/// </param>
/// <param name="bmpOriginal">
/// first elements of array of images
/// </param>
public classSpriteLimb(ref classSprite sprite, bool IRotate, bool AlwaysVertical, string _myName)
{
mainSprite = sprite;
myName = _myName;
bolIRotate = IRotate;
bolAlwaysVertical = AlwaysVertical;
if (IRotate)
{
bmpSpriteLimb = new Bitmap[(int)mainSprite.ImagesPerRotation];
}
else
{ // debug here (not done)
bmpSpriteLimb = new Bitmap[(int)mainSprite.ImagesPerRotation];
}
}
#region "initialize images"
public void initImages(Bitmap bmpOriginal)
{
classSpriteLimb cMyReference = this;
if (bmpSpriteLimb == null || bmpSpriteLimb.Length != mainSprite.ImagesPerRotation)
{
bmpSpriteLimb = new Bitmap[(int)mainSprite.ImagesPerRotation];
}
if (bmpOriginal.Width > 3 && bmpOriginal.Height > 3)
{
formGenerateFirstQuarterImages frmGenerateFirstQuarterImages = new formGenerateFirstQuarterImages(ref cMyReference, bmpOriginal);
frmGenerateFirstQuarterImages.ShowDialog();
}
}
/// <summary>
/// returns image appropriate for this limb at current angle
/// selected from array of N images
/// </summary>
public Bitmap getLimbImage() { return getLimbImage(ref bmpSpriteLimb, angle); }
/// <summary>
/// returns image appropriate for this limb at input angle
/// selected from array of N images
/// </summary>
/// <param name="dblAngle">
/// angled image to be returned
/// </param>
/// <returns></returns>
public Bitmap getLimbImage(double dblAngle) { return getLimbImage(ref bmpSpriteLimb, dblAngle); }
/// <summary>
/// returns image appropriate for this limb at input angle
/// selected from array of N images
/// </summary>
/// <param name="udrSpriteImage">array of N/4 images pointing in N angles where east is 0th, North-east is 2nd, North 4th, etc.</param>
/// <param name="dblAngle">angle in radians where 0 is east Pi/2 is north, Pi is west, and 3Pi/2 is south</param>
/// <returns></returns>
public Bitmap getLimbImage(ref Bitmap[] udrSpriteImage, double dblAngle)
{
return getLimbImage(ref udrSpriteImage, dblAngle, mainSprite.eMirror);
}
public Bitmap getLimbImage(ref Bitmap[] udrSpriteImage, double dblAngle, enuMirror eMirror)
{
angle = dblAngle;
while (angle < 0)
angle += (2.0 * Math.PI);
while (angle > 2.0 * Math.PI)
angle -= (2.0 * Math.PI);
setDir();
switch (eMirror)
{
case enuMirror.horizontal:
int intImageSourceDir_HFlip = getDir(classMath.cleanAngle(angle));
Bitmap bmpRetValHorizontalMirror = new Bitmap(getLimbImageFromArray_ByDir(ref udrSpriteImage, intImageSourceDir_HFlip));
bmpRetValHorizontalMirror.RotateFlip(RotateFlipType.RotateNoneFlipX);
return bmpRetValHorizontalMirror;
case enuMirror.vertical:
int intImageSourceDir_VFlip = getDir(angle);
Bitmap bmpRetValVerticalMirror = new Bitmap(getLimbImageFromArray_ByDir(ref udrSpriteImage, intImageSourceDir_VFlip));
bmpRetValVerticalMirror.RotateFlip(RotateFlipType.RotateNoneFlipY);
return bmpRetValVerticalMirror;
case enuMirror.VerticalAndHorizontal:
int intImageSourceDir_VHFlip = getDir(classMath.cleanAngle(-angle));
Bitmap bmpRetValVerticalHorizontalMirror = new Bitmap(getLimbImageFromArray_ByDir(ref udrSpriteImage, intImageSourceDir_VHFlip));
return bmpRetValVerticalHorizontalMirror;
default:
case enuMirror.none:
Bitmap bmpRetval = new Bitmap(getLimbImageFromArray_ByDir(ref udrSpriteImage, dir));
return bmpRetval;
}
}
public void setDir() { setDir(angle); }
public void setDir(double dblAngle)
{
dir = getDir(dblAngle);
angle = dir * (Math.PI / (mainSprite.ImagesPerRotation / 2.0));
}
public int getDir(double dblAngle)
{
double dblTestAngle = dblAngle - (Math.PI / mainSprite.ImagesPerRotation);
if (dblTestAngle < 0)
dblTestAngle += (Math.PI * 2.0);
int intPicIndex = (int)(Math.Ceiling(dblTestAngle / (Math.PI / (mainSprite.ImagesPerRotation / 2.0))));
if (intPicIndex == (int)mainSprite.ImagesPerRotation)
intPicIndex = 0;
return intPicIndex;
}
void loadImageIntoArray(ref Bitmap[] udrSpriteImage, int intDir)
{
// get address of this image's index
mainSprite.cFileStream.fs.Position = mainSprite.getLimbImageIndex(intMyLimbID, intDir);
long lngPosition = (long)classSpriteFileStream.formatter.Deserialize(mainSprite.cFileStream.fs);
if (lngPosition > 0)
{
mainSprite.cFileStream.fs.Position = lngPosition;
udrSpriteImage[intDir] = (Bitmap)classSpriteFileStream.formatter.Deserialize(mainSprite.cFileStream.fs);
}
}
public Bitmap getLimbImageFromArray_ByDir(int intDir) { return getLimbImageFromArray_ByDir(ref bmpSpriteLimb, intDir); }
/// <summary>
/// returns image appropriate for this limb at input direction
/// selected from array of N images
/// </summary>
/// <param name="udrSpriteImage">array of 4 images pointing in N angles where east is 0th, North-east is 2nd, North 4th, etc.</param>
/// <param name="intDir">indicates the desired direction of image where 0th is east, 4th is north, 8 is west and 12th south, etc.</param>
/// <returns></returns>
public Bitmap getLimbImageFromArray_ByDir(ref Bitmap[] udrSpriteLimbImage, int intDir)
{
if (udrSpriteLimbImage == null)
return null;
if (intDir < 0 || intDir >= mainSprite.ImagesPerRotation)
{
MessageBox.Show("error getLimbImageFromArray_ByDir");
return getLimbImageFromArray_ByDir(ref udrSpriteLimbImage, 0);
}
else
{
if (udrSpriteLimbImage.Length > 1)
{
if (intDir < (mainSprite.ImagesPerRotation / 4.0))
{
if (udrSpriteLimbImage[intDir]== null)
loadImageIntoArray(ref udrSpriteLimbImage, intDir);
return udrSpriteLimbImage[intDir];
}
else
{
if (bmpSpriteLimb[intDir] != null && false)
{
if (udrSpriteLimbImage[intDir] == null)
loadImageIntoArray(ref udrSpriteLimbImage, intDir);
return bmpSpriteLimb[intDir];
}
else
{
int intBaseImage = intDir % (int)(mainSprite.ImagesPerRotation / 4.0);
int intQuarterRotations = (int)Math.Floor((double)intDir / (mainSprite.ImagesPerRotation / 4.0));
Bitmap bmpRetVal;// = new Bitmap();
if (udrSpriteLimbImage[intBaseImage] == null)
loadImageIntoArray(ref udrSpriteLimbImage, intBaseImage);
bmpRetVal = (Bitmap)udrSpriteLimbImage[intBaseImage].Clone();
switch (intQuarterRotations)
{
case 3:
bmpRetVal.RotateFlip(RotateFlipType.Rotate270FlipNone);
break;
case 2:
bmpRetVal.RotateFlip(RotateFlipType.Rotate180FlipNone);
break;
case 1:
bmpRetVal.RotateFlip(RotateFlipType.Rotate90FlipNone);
break;
}
return bmpRetVal;
}
}
//}
}
else
{
if (udrSpriteLimbImage[intDir] == null)
loadImageIntoArray(ref udrSpriteLimbImage, intDir);
return udrSpriteLimbImage[intDir];
}
}
}
#endregion
public void addLimb(classSpriteLimb newLimb, string hingeName, classMath.classRadialCoor radMasterJoint, classMath.classRadialCoor radSlaveJoint)
{
if (mySlaveLimbs == null)
mySlaveLimbs = new classSpriteLimb[0];
// add new limb to this limb
Array.Resize<classSpriteLimb>(ref mySlaveLimbs, mySlaveLimbs.Length + 1);
mySlaveLimbs[mySlaveLimbs.Length - 1] = newLimb;
mySlaveLimbs[mySlaveLimbs.Length - 1].MasterHinge = new classSpriteHinge(hingeName, radMasterJoint, radSlaveJoint, this, newLimb);
mySlaveLimbs[mySlaveLimbs.Length - 1].MasterHinge.mainSprite = mainSprite;
newLimb.intMySlaveID = mySlaveLimbs.Length - 1;
// add new hinge to sprite's hinges
Array.Resize<Sprite.classSpriteHinge>(ref mainSprite.hinges, mainSprite.hinges.Length + 1);
mainSprite.hinges[mainSprite.hinges.Length - 1] = mySlaveLimbs[mySlaveLimbs.Length - 1].MasterHinge;
mainSprite.hinges[mainSprite.hinges.Length - 1].intMyHingeIndex = mainSprite.hinges.Length - 1;
// add new limb to sprite' limbs
Array.Resize<Sprite.classSpriteLimb>(ref mainSprite.limbs, mainSprite.limbs.Length + 1);
mainSprite.limbs[mainSprite.limbs.Length - 1] = newLimb;
newLimb.intMyLimbID = mainSprite.limbs.Length - 1;
}
public void subLimb(ref classSpriteLimb thisLimb)
{
if (thisLimb.myName.CompareTo(mySlaveLimbs[thisLimb.MySlaveID].myName) != 0)
MessageBox.Show("we have a problem!");
disposeAllHinges(ref thisLimb);
mySlaveLimbs[thisLimb.MySlaveID] = mySlaveLimbs[mySlaveLimbs.Length - 1];
Array.Resize<Sprite.classSpriteLimb>(ref mySlaveLimbs, mySlaveLimbs.Length - 1);
}
void disposeAllHinges(ref Sprite.classSpriteLimb thisLimb)
{
for (int intSlaveCounter = 0; intSlaveCounter < mySlaveLimbs.Length; intSlaveCounter++)
disposeAllHinges(ref mySlaveLimbs[intSlaveCounter]);
for (int intHingeCounter = 0; intHingeCounter < mainSprite.hinges.Length; intHingeCounter++)
if (mainSprite.hinges[intHingeCounter].name.CompareTo(thisLimb.MasterHinge.name) == 0)
{
mainSprite.hinges[intHingeCounter] = mainSprite.hinges[mainSprite.hinges.Length - 1];
Array.Resize<Sprite.classSpriteHinge>(ref mainSprite.hinges, mainSprite.hinges.Length - 1);
}
}
}
public class classSpriteMaker
{
udtSprite_StorageRetrieval udrStorageSprite;
const int conMaxNameStringSize = 50;
const string conStrNull = "---NULL---";
public const string conMasterLimbName = "-Master-Limb-";
public static classSpriteFileStream cFileStreamsTree;
public static classSpriteFileStream _defaultFS;
static string strDefaultFilestreamFilename = classSpriteFileStream.strWorkingDirectory + "DEFAULTfilestream.sp3";
public static classSpriteFileStream getDefaultFileStream()
{
if (_defaultFS != null)
if (_defaultFS.fs != null)
_defaultFS.fs.Close();
return new classSpriteFileStream(strDefaultFilestreamFilename);
}
classSpriteFileStream getFileStream(string strFilename)
{
if (cFileStreamsTree == null)
{
// debug start
if (System.IO.File.Exists(classSpriteFileStream.strCache_BmpAndTLInfo_Filename))
System.IO.File.Delete(classSpriteFileStream.strCache_BmpAndTLInfo_Filename);
if (System.IO.File.Exists(classSpriteFileStream.strCache_BmpInfo_RAMCacheRebuild))
System.IO.File.Delete(classSpriteFileStream.strCache_BmpInfo_RAMCacheRebuild);
// debug end
cFileStreamsTree = new classSpriteFileStream(strFilename);
return cFileStreamsTree;
}
else
{
strFilename = strFilename.ToUpper();
classSpriteFileStream cThisFS = cFileStreamsTree;
while (true)
{
if (strFilename.CompareTo(cThisFS.strFilename) > 0)
{
if (cThisFS.right != null)
cThisFS = cThisFS.right;
else
{
cThisFS.right = new classSpriteFileStream(strFilename);
return cThisFS.right;
}
}
else if (strFilename.CompareTo(cThisFS.strFilename) < 0)
{
if (cThisFS.left != null)
cThisFS = cThisFS.left;
else
{
cThisFS.left = new classSpriteFileStream(strFilename);
return cThisFS.left;
}
}
else
{
return cThisFS;
}
}
}
}
BinaryFormatter formatter = new BinaryFormatter();
public classSprite getSprite(bool masterLimbRotates, bool AlwaysVertical, string _myName)
{ return getSprite(masterLimbRotates, 4, AlwaysVertical, _myName); }
public classSprite getSprite(bool masterLimbRotates, int ImagesPerQuarterRotation, bool AlwaysVertical, string _myName)
{
classSprite spriteRetVal = new classSprite(ImagesPerQuarterRotation);
spriteRetVal.myName = _myName;
spriteRetVal.MasterLimb = new classSpriteLimb(ref spriteRetVal, masterLimbRotates, AlwaysVertical, conMasterLimbName);
return spriteRetVal;
}
#region "Storage and Retrieval"
public classSprite loadSprite(string strFilename)
{
int intcutchr = strFilename.IndexOf(".");
if (intcutchr > 0)
strFilename = strFilename.Substring(0, intcutchr);
strFilename += ".sp3";
if (System.IO.File.Exists(strFilename))
{
classSprite sprRetVal = loadSprite_V3(strFilename);
return sprRetVal;
}
else
{
strFilename = strFilename.Replace(".sp3", ".sp2");
if (System.IO.File.Exists(strFilename))
{
classSprite sprRetVal = loadSprite_V2(strFilename);
saveSprite(ref sprRetVal, strFilename);
return sprRetVal;
}
else
{
classSprite sprRetVal = loadSprite_V1(strFilename);
saveSprite(ref sprRetVal, strFilename);
return sprRetVal;
}
}
}
public classSprite loadSprite_V3(string strFilename)
{
udtSprite_StorageRetrieval udrThisSprite = new udtSprite_StorageRetrieval();
int intcutchr = strFilename.IndexOf(".");
if (intcutchr > 0)
strFilename = strFilename.Substring(0, intcutchr);
strFilename += ".sp3";
classSpriteFileStream cFilestream = getFileStream(strFilename);
cFilestream.fs.Position = 0;
udrThisSprite.myName = (string)formatter.Deserialize(cFilestream.fs);
udrThisSprite.intImagesPerRotation = (int)formatter.Deserialize(cFilestream.fs);
int intNumLimbs = (int)formatter.Deserialize(cFilestream.fs);
udrThisSprite.limbs = new udtLimb_StorageRetrieval[intNumLimbs];
for (int intLimbCounter = 0; intLimbCounter < intNumLimbs; intLimbCounter++)
{
udrThisSprite.limbs[intLimbCounter].myName = (string)formatter.Deserialize(cFilestream.fs);
udrThisSprite.limbs[intLimbCounter].IRotate = (bool)formatter.Deserialize(cFilestream.fs);
udrThisSprite.limbs[intLimbCounter].AlwaysVertical = (bool)formatter.Deserialize(cFilestream.fs);
udrThisSprite.limbs[intLimbCounter].bmp = new Bitmap[(int)(udrThisSprite.intImagesPerRotation / 4)];
udrThisSprite.limbs[intLimbCounter].radMaster = new classMath.classRadialCoor();
udrThisSprite.limbs[intLimbCounter].radMaster.angle = (double)formatter.Deserialize(cFilestream.fs);
udrThisSprite.limbs[intLimbCounter].radMaster.radius = (double)formatter.Deserialize(cFilestream.fs);
udrThisSprite.limbs[intLimbCounter].radSlave = new classMath.classRadialCoor();
udrThisSprite.limbs[intLimbCounter].radSlave.angle = (double)formatter.Deserialize(cFilestream.fs);
udrThisSprite.limbs[intLimbCounter].radSlave.radius = (double)formatter.Deserialize(cFilestream.fs);
udrThisSprite.limbs[intLimbCounter].MasterIndex = (int)formatter.Deserialize(cFilestream.fs);
udrThisSprite.limbs[intLimbCounter].hingeName = (string)formatter.Deserialize(cFilestream.fs);
}
classSprite retval = getSprite(udrThisSprite.limbs[0].IRotate, udrThisSprite.intImagesPerRotation / 4, udrThisSprite.limbs[0].AlwaysVertical, udrThisSprite.myName);
retval.cFileStream = cFilestream;
Bitmap bmpMaster = new Bitmap(2, 2);
using (Graphics g = Graphics.FromImage(bmpMaster))
{
using (SolidBrush br = new SolidBrush(Color.White))
{
g.FillRectangle(br, new Rectangle(0, 0, bmpMaster.Width, bmpMaster.Height));
}
}
retval.MasterLimb.initImages(bmpMaster);
for (int intLimbCounter = 0; intLimbCounter < udrThisSprite.limbs.Length; intLimbCounter++)
{
Sprite.classSpriteLimb masterLimb = retval.getLimbByName(udrThisSprite.limbs[udrThisSprite.limbs[intLimbCounter].MasterIndex].myName);
if (masterLimb == null)
masterLimb = retval.MasterLimb;
Sprite.classSpriteLimb newLimb = new Sprite.classSpriteLimb(ref retval,
udrThisSprite.limbs[intLimbCounter].IRotate,
udrThisSprite.limbs[intLimbCounter].AlwaysVertical,
udrThisSprite.limbs[intLimbCounter].myName.Trim());
masterLimb.addLimb(newLimb,
udrThisSprite.limbs[intLimbCounter].hingeName.Trim(),
new classMath.classRadialCoor(udrThisSprite.limbs[intLimbCounter].radMaster.angle, udrThisSprite.limbs[intLimbCounter].radMaster.radius),
new classMath.classRadialCoor(udrThisSprite.limbs[intLimbCounter].radSlave.angle, udrThisSprite.limbs[intLimbCounter].radSlave.radius));
}
// load configurations
int intNumConfigurations = (int)formatter.Deserialize(cFilestream.fs);
Array.Resize<classConfiguration>(ref retval.Configurations, intNumConfigurations);
for (int intConfigurationCounter = 0; intConfigurationCounter < retval.Configurations.Length; intConfigurationCounter++)
{
classConfiguration thisCon = new classConfiguration();
thisCon.mainSprite = retval;
thisCon.name = ((string)formatter.Deserialize(cFilestream.fs)).Trim();
int intNumberLimbs = (int)formatter.Deserialize(cFilestream.fs);
Array.Resize<classSpriteLimb>(ref thisCon.LimbDrawSequence, intNumberLimbs);
for (int intLimbCounter = 0; intLimbCounter < thisCon.LimbDrawSequence.Length; intLimbCounter++)
{
string strConLimbName = ((string)formatter.Deserialize(cFilestream.fs)).Trim();
thisCon.LimbDrawSequence[intLimbCounter] = retval.getLimbByName(strConLimbName);
if (thisCon.LimbDrawSequence[intLimbCounter] == null)
if (retval.MasterLimb.Name.ToUpper().Trim().CompareTo(strConLimbName.Trim().ToUpper()) == 0)
thisCon.LimbDrawSequence[intLimbCounter] = retval.MasterLimb;
}
int intNumSteps = (int)formatter.Deserialize(cFilestream.fs);
Array.Resize<classConfigurationStep>(ref thisCon.steps, intNumSteps);
for (int intStepCounter = 0; intStepCounter < thisCon.steps.Length; intStepCounter++)
{
thisCon.steps[intStepCounter] = new classConfigurationStep();
Array.Resize<classConfigurationStepHinge>(ref thisCon.steps[intStepCounter].hingeDetails, retval.hinges.Length);
thisCon.steps[intStepCounter].hingeDetails = new classConfigurationStepHinge[retval.hinges.Length];
for (int intHingeCounter = 0; intHingeCounter < thisCon.steps[intStepCounter].hingeDetails.Length; intHingeCounter++)
{
string strConStepHingeName = ((string)formatter.Deserialize(cFilestream.fs)).Trim();
thisCon.steps[intStepCounter].hingeDetails[intHingeCounter] = new classConfigurationStepHinge();
thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].hinge = retval.getHingeByName(strConStepHingeName);
thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].angle = (double)formatter.Deserialize(cFilestream.fs);
thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].RadCoor_Master = retval.hinges[intHingeCounter].RadCoor_Master;
thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].RadCoor_Slave = retval.hinges[intHingeCounter].RadCoor_Slave;
}
}
retval.Configurations[intConfigurationCounter] = thisCon;
}
retval.cFileStream.lngStartIndex = cFilestream.fs.Position;
long lngFubu = (long)formatter.Deserialize(cFilestream.fs);
retval.cFileStream.lngSizeLongIndexInFileStream = cFilestream.fs.Position - retval.cFileStream.lngStartIndex;
return retval;
}
public classSprite loadSprite_V2(string strFilename)
{
udtSprite_StorageRetrieval udrThisSprite = new udtSprite_StorageRetrieval();
int intcutchr = strFilename.IndexOf(".");
if (intcutchr > 0)
strFilename = strFilename.Substring(0, intcutchr);
strFilename += ".sp2";
FileStream fs = new FileStream(strFilename, FileMode.Open);
BinaryFormatter formatter = new BinaryFormatter();
udrThisSprite.myName = (string)formatter.Deserialize(fs);
udrThisSprite.intImagesPerRotation = 16; // original default value
int intNumLimbs = (int)formatter.Deserialize(fs);
udrThisSprite.limbs = new udtLimb_StorageRetrieval[intNumLimbs];
for (int intLimbCounter = 0; intLimbCounter < intNumLimbs; intLimbCounter++)
{
udrThisSprite.limbs[intLimbCounter].myName = (string)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].IRotate = (bool)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].AlwaysVertical = (bool)formatter.Deserialize(fs);
int intNumBaseImages = (int)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].bmp = new Bitmap[intNumBaseImages];
for (int intBaseImageCounter = 0; intBaseImageCounter < intNumBaseImages; intBaseImageCounter++)
udrThisSprite.limbs[intLimbCounter].bmp[intBaseImageCounter] = (Bitmap)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].radMaster = new classMath.classRadialCoor();
udrThisSprite.limbs[intLimbCounter].radMaster.angle = (double)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].radMaster.radius = (double)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].radSlave = new classMath.classRadialCoor();
udrThisSprite.limbs[intLimbCounter].radSlave.angle = (double)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].radSlave.radius = (double)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].MasterIndex = (int)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].hingeName = (string)formatter.Deserialize(fs);
}
classSprite retval = getSprite(udrThisSprite.limbs[0].IRotate, udrThisSprite.limbs[0].AlwaysVertical, udrThisSprite.myName);
for (int intLimbCounter = 1; intLimbCounter < udrThisSprite.limbs.Length; intLimbCounter++)
{
Sprite.classSpriteLimb masterLimb = retval.getLimbByName(udrThisSprite.limbs[udrThisSprite.limbs[intLimbCounter].MasterIndex].myName);
if (masterLimb == null)
masterLimb = retval.MasterLimb;
Sprite.classSpriteLimb newLimb = new Sprite.classSpriteLimb(ref retval,
udrThisSprite.limbs[intLimbCounter].IRotate,
udrThisSprite.limbs[intLimbCounter].AlwaysVertical,
udrThisSprite.limbs[intLimbCounter].myName.Trim());
masterLimb.addLimb(newLimb,
udrThisSprite.limbs[intLimbCounter].hingeName.Trim(),
new classMath.classRadialCoor(udrThisSprite.limbs[intLimbCounter].radMaster.angle, udrThisSprite.limbs[intLimbCounter].radMaster.radius),
new classMath.classRadialCoor(udrThisSprite.limbs[intLimbCounter].radSlave.angle, udrThisSprite.limbs[intLimbCounter].radSlave.radius));
}
// load limb draw sequence here -> no longer used in new sprite format
int intNumDrawPointers = (int)formatter.Deserialize(fs);
string[] strNames = new string[intNumDrawPointers];
for (int intDrawCounter = 0; intDrawCounter < intNumDrawPointers; intDrawCounter++)
{
string strNameLimb = ((string)formatter.Deserialize(fs)).Trim();
}
// load configurations
int intNumConfigurations = (int)formatter.Deserialize(fs);
Array.Resize<classConfiguration>(ref retval.Configurations, intNumConfigurations);
for (int intConfigurationCounter = 0; intConfigurationCounter < retval.Configurations.Length; intConfigurationCounter++)
{
classConfiguration thisCon = new classConfiguration();
thisCon.mainSprite = retval;
thisCon.name = ((string)formatter.Deserialize(fs)).Trim();
int intNumberLimbs = (int)formatter.Deserialize(fs);
Array.Resize<classSpriteLimb>(ref thisCon.LimbDrawSequence, intNumberLimbs);
for (int intLimbCounter = 0; intLimbCounter < thisCon.LimbDrawSequence.Length; intLimbCounter++)
{
string strConLimbName = ((string)formatter.Deserialize(fs)).Trim();
thisCon.LimbDrawSequence[intLimbCounter] = retval.getLimbByName(strConLimbName);
if (thisCon.LimbDrawSequence[intLimbCounter] == null)
if (retval.MasterLimb.Name.ToUpper().Trim().CompareTo(strConLimbName.Trim().ToUpper()) == 0)
thisCon.LimbDrawSequence[intLimbCounter] = retval.MasterLimb;
}
int intNumSteps = (int)formatter.Deserialize(fs);
Array.Resize<classConfigurationStep>(ref thisCon.steps, intNumSteps);
for (int intStepCounter = 0; intStepCounter < thisCon.steps.Length; intStepCounter++)
{
thisCon.steps[intStepCounter] = new classConfigurationStep();
Array.Resize<classConfigurationStepHinge>(ref thisCon.steps[intStepCounter].hingeDetails, intNumberLimbs);
for (int intHingeCounter = 0; intHingeCounter < thisCon.steps[intStepCounter].hingeDetails.Length; intHingeCounter++)
{
string strConStepHingeName = ((string)formatter.Deserialize(fs)).Trim();
thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].hinge = retval.getHingeByName(strConStepHingeName);
thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].angle = (double)formatter.Deserialize(fs);
}
}
retval.Configurations[intConfigurationCounter] = thisCon;
}
fs.Close();
return retval;
}
public classSprite loadSprite_V1(string strFilename)
{
udtSprite_StorageRetrieval udrThisSprite = new udtSprite_StorageRetrieval();
int intcutchr = strFilename.IndexOf(".");
if (intcutchr > 0)
strFilename = strFilename.Substring(0, intcutchr);
strFilename += ".spr";
FileStream fs = new FileStream(strFilename, FileMode.Open);
BinaryFormatter formatter = new BinaryFormatter();
udrThisSprite.myName = (string)formatter.Deserialize(fs);
udrThisSprite.intImagesPerRotation = 16; // original default value
int intNumLimbs = (int)formatter.Deserialize(fs);
udrThisSprite.limbs = new udtLimb_StorageRetrieval[intNumLimbs];
for (int intLimbCounter = 0; intLimbCounter < intNumLimbs; intLimbCounter++)
{
udrThisSprite.limbs[intLimbCounter].myName = (string)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].IRotate = (bool)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].AlwaysVertical = (bool)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].bmp = new Bitmap[1];
udrThisSprite.limbs[intLimbCounter].bmp[0] = (Bitmap)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].radMaster = new classMath.classRadialCoor();
udrThisSprite.limbs[intLimbCounter].radMaster.angle = (double)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].radMaster.radius = (double)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].radSlave = new classMath.classRadialCoor();
udrThisSprite.limbs[intLimbCounter].radSlave.angle = (double)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].radSlave.radius = (double)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].MasterIndex = (int)formatter.Deserialize(fs);
udrThisSprite.limbs[intLimbCounter].hingeName = (string)formatter.Deserialize(fs);
}
classSprite retval = getSprite(udrThisSprite.limbs[0].IRotate, udrThisSprite.limbs[0].AlwaysVertical, udrThisSprite.myName);
for (int intLimbCounter = 1; intLimbCounter < udrThisSprite.limbs.Length; intLimbCounter++)
{
Sprite.classSpriteLimb masterLimb = retval.getLimbByName(udrThisSprite.limbs[udrThisSprite.limbs[intLimbCounter].MasterIndex].myName);
if (masterLimb == null)
masterLimb = retval.MasterLimb;
Sprite.classSpriteLimb newLimb = new Sprite.classSpriteLimb(ref retval,
udrThisSprite.limbs[intLimbCounter].IRotate,
udrThisSprite.limbs[intLimbCounter].AlwaysVertical,
udrThisSprite.limbs[intLimbCounter].myName.Trim());
masterLimb.addLimb(newLimb,
udrThisSprite.limbs[intLimbCounter].hingeName.Trim(),
new classMath.classRadialCoor(udrThisSprite.limbs[intLimbCounter].radMaster.angle, udrThisSprite.limbs[intLimbCounter].radMaster.radius),
new classMath.classRadialCoor(udrThisSprite.limbs[intLimbCounter].radSlave.angle, udrThisSprite.limbs[intLimbCounter].radSlave.radius));
}
// load limb draw sequence here -> no longer used in new sprite format
int intNumDrawPointers = (int)formatter.Deserialize(fs);
string[] strNames = new string[intNumDrawPointers];
for (int intDrawCounter = 0; intDrawCounter < intNumDrawPointers; intDrawCounter++)
{
string strNameLimb = ((string)formatter.Deserialize(fs)).Trim();
}
// load configurations
int intNumConfigurations = (int)formatter.Deserialize(fs);
Array.Resize<classConfiguration>(ref retval.Configurations, intNumConfigurations);
for (int intConfigurationCounter = 0; intConfigurationCounter < retval.Configurations.Length; intConfigurationCounter++)
{
classConfiguration thisCon = new classConfiguration();
thisCon.mainSprite = retval;
thisCon.name = ((string)formatter.Deserialize(fs)).Trim();
int intNumberLimbs = (int)formatter.Deserialize(fs);
Array.Resize<classSpriteLimb>(ref thisCon.LimbDrawSequence, intNumberLimbs);
for (int intLimbCounter = 0; intLimbCounter < thisCon.LimbDrawSequence.Length; intLimbCounter++)
{
string strConLimbName = ((string)formatter.Deserialize(fs)).Trim();
thisCon.LimbDrawSequence[intLimbCounter] = retval.getLimbByName(strConLimbName);
if (thisCon.LimbDrawSequence[intLimbCounter] == null)
if (retval.MasterLimb.Name.ToUpper().Trim().CompareTo(strConLimbName.Trim().ToUpper()) == 0)
thisCon.LimbDrawSequence[intLimbCounter] = retval.MasterLimb;
}
int intNumSteps = (int)formatter.Deserialize(fs);
Array.Resize<classConfigurationStep>(ref thisCon.steps, intNumSteps);
for (int intStepCounter = 0; intStepCounter < thisCon.steps.Length; intStepCounter++)
{
thisCon.steps[intStepCounter] = new classConfigurationStep();
Array.Resize<classConfigurationStepHinge>(ref thisCon.steps[intStepCounter].hingeDetails, intNumberLimbs);
for (int intHingeCounter = 0; intHingeCounter < thisCon.steps[intStepCounter].hingeDetails.Length; intHingeCounter++)
{
string strConStepHingeName = ((string)formatter.Deserialize(fs)).Trim();
thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].hinge = retval.getHingeByName(strConStepHingeName);
thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].angle = (double)formatter.Deserialize(fs);
}
}
retval.Configurations[intConfigurationCounter] = thisCon;
}
fs.Close();
return retval;
}
/// <summary>
/// turns any string into a string of exact size (conMaxNameStringSize) for storage
/// </summary>
/// <param name="strName">input string of any length</param>
/// <returns>output copy of input parameter set to specific storage string length</returns>
string getNameFromString(string strName) { return (strName.Trim().PadRight(conMaxNameStringSize)).Substring(0, conMaxNameStringSize); }
public void saveSprite(ref Sprite.classSprite thisSprite, string strFilename)
{
udrStorageSprite = new udtSprite_StorageRetrieval();
udrStorageSprite.myName = getNameFromString(thisSprite.myName);
udrStorageSprite.intImagesPerRotation = (int)thisSprite.ImagesPerRotation;
udrStorageSprite.limbs = new udtLimb_StorageRetrieval[0];
createStorageSpriteLimbs(ref thisSprite.MasterLimb);
strFilename = strFilename.ToUpper().Replace(".SPR", ".SP3").Replace(".sp2", ".sp3");
if (thisSprite.cFileStream == null)
thisSprite.cFileStream = getFileStream(strFilename);
thisSprite.cFileStream.fs.Position = 0;
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.myName);
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.intImagesPerRotation);
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs.Length);
for (int intLimbCounter = 0; intLimbCounter < udrStorageSprite.limbs.Length; intLimbCounter++)
{
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs[intLimbCounter].myName);
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs[intLimbCounter].IRotate);
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs[intLimbCounter].AlwaysVertical);
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs[intLimbCounter].radMaster.angle);
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs[intLimbCounter].radMaster.radius);
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs[intLimbCounter].radSlave.angle);
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs[intLimbCounter].radSlave.radius);
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs[intLimbCounter].MasterIndex);
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs[intLimbCounter].hingeName);
}
// save configuration info
if (thisSprite.Configurations == null)
formatter.Serialize(thisSprite.cFileStream.fs, 0);
else
{
formatter.Serialize(thisSprite.cFileStream.fs, thisSprite.Configurations.Length);
for (int intConfigurationCounter = 0; intConfigurationCounter < thisSprite.Configurations.Length; intConfigurationCounter++)
{
classConfiguration thisCon = thisSprite.Configurations[intConfigurationCounter];
formatter.Serialize(thisSprite.cFileStream.fs, getNameFromString(thisCon.name));
formatter.Serialize(thisSprite.cFileStream.fs, thisCon.LimbDrawSequence.Length);
for (int intHingeCounter = 0; intHingeCounter < thisCon.LimbDrawSequence.Length; intHingeCounter++)
formatter.Serialize(thisSprite.cFileStream.fs, getNameFromString(thisCon.LimbDrawSequence[intHingeCounter].Name));
formatter.Serialize(thisSprite.cFileStream.fs, thisCon.steps.Length);
for (int intStepCounter = 0; intStepCounter < thisCon.steps.Length; intStepCounter++)
{
for (int intHingeCounter = 0; intHingeCounter < thisCon.steps[intStepCounter].hingeDetails.Length; intHingeCounter++)
{
if (thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].hinge == null)
{
formatter.Serialize(thisSprite.cFileStream.fs, (getNameFromString(conStrNull)));
formatter.Serialize(thisSprite.cFileStream.fs, (double)0.0);
}
else
{
formatter.Serialize(thisSprite.cFileStream.fs, getNameFromString(thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].hinge.name));
formatter.Serialize(thisSprite.cFileStream.fs, thisCon.steps[intStepCounter].hingeDetails[intHingeCounter].angle);
}
}
}
thisSprite.Configurations[intConfigurationCounter] = thisCon;
}
}
thisSprite.cFileStream.lngStartIndex = thisSprite.cFileStream.fs.Position;
formatter.Serialize(thisSprite.cFileStream.fs, (long)0); /// measure the length of a single long integer on the filestream
thisSprite.cFileStream.lngSizeLongIndexInFileStream = thisSprite.cFileStream.fs.Position - thisSprite.cFileStream.lngStartIndex;
/// make room for all image indices
for (int intLimbCounter = 0; intLimbCounter < thisSprite.limbs.Length; intLimbCounter++)
{
for (int intImageCounter = 0; intImageCounter < (int)(thisSprite.ImagesPerRotation / 4); intImageCounter++)
formatter.Serialize(thisSprite.cFileStream.fs, (long)(-1));
}
long lngIndexNextImage = thisSprite.cFileStream.fs.Position;
/// save images and record their indices
for (int intLimbCounter = 0; intLimbCounter < udrStorageSprite.limbs.Length; intLimbCounter++)
{
// test if all images exist
bool bolImagesExist = true;
for (int intImageCounter = 0; intImageCounter < udrStorageSprite.limbs[intLimbCounter].bmp.Length && intImageCounter < thisSprite.ImagesPerRotation / 4; intImageCounter++)
{
if (udrStorageSprite.limbs[intLimbCounter].bmp[intImageCounter] == null)
{
bolImagesExist = false;
break;
}
}
if (!bolImagesExist)
{
thisSprite.limbs[intLimbCounter].initImages(thisSprite.limbs[intLimbCounter].bmpSpriteLimb[0]);
udrStorageSprite.limbs[intLimbCounter].bmp = thisSprite.limbs[intLimbCounter].bmpSpriteLimb;
}
for (int intImageCounter = 0; intImageCounter < udrStorageSprite.limbs[intLimbCounter].bmp.Length && intImageCounter < thisSprite.ImagesPerRotation / 4; intImageCounter++)
{
long lngIndexThisImage = lngIndexNextImage;
thisSprite.cFileStream.fs.Position = lngIndexThisImage;
formatter.Serialize(thisSprite.cFileStream.fs, udrStorageSprite.limbs[intLimbCounter].bmp[intImageCounter]);
lngIndexNextImage = thisSprite.cFileStream.fs.Position;
thisSprite.cFileStream.fs.Position = thisSprite.getLimbImageIndex(intLimbCounter, intImageCounter);
formatter.Serialize(thisSprite.cFileStream.fs, lngIndexThisImage);
}
}
}
void createStorageSpriteLimbs(ref Sprite.classSpriteLimb thisLimb)
{
udtLimb_StorageRetrieval udrTemp = new udtLimb_StorageRetrieval();
udrTemp.radMaster = new classMath.classRadialCoor();
udrTemp.radSlave = new classMath.classRadialCoor();
if (thisLimb.MasterHinge != null)
{
Array.Resize<udtLimb_StorageRetrieval>(ref udrStorageSprite.limbs, udrStorageSprite.limbs.Length + 1);
udrTemp.myName = getNameFromString(thisLimb.Name);
udrTemp.AlwaysVertical = thisLimb.AlwaysVertical;
udrTemp.IRotate = thisLimb.IRotate;
udrTemp.bmp = new Bitmap[thisLimb.bmpSpriteLimb.Length];
for (int intBaseImageCounter = 0; intBaseImageCounter < (int)(thisLimb.bmpSpriteLimb.Length / 4); intBaseImageCounter++)
udrTemp.bmp[intBaseImageCounter] = thisLimb.bmpSpriteLimb[intBaseImageCounter];
udrTemp.radMaster.angle = thisLimb.MasterHinge.RadCoor_Master.angle;
udrTemp.radMaster.radius = thisLimb.MasterHinge.RadCoor_Master.radius;
udrTemp.radSlave.angle = thisLimb.MasterHinge.RadCoor_Slave.angle;
udrTemp.radSlave.radius = thisLimb.MasterHinge.RadCoor_Slave.radius;
udrTemp.MasterIndex = thisLimb.MasterHinge.Limb_Master.intMyLimbID;
udrTemp.hingeName = getNameFromString(thisLimb.MasterHinge.name);
udrStorageSprite.limbs[udrStorageSprite.limbs.Length - 1] = udrTemp;
}
if (thisLimb.mySlaveLimbs != null)
for (int intSlaveCounter = 0; intSlaveCounter < thisLimb.mySlaveLimbs.Length; intSlaveCounter++)
createStorageSpriteLimbs(ref thisLimb.mySlaveLimbs[intSlaveCounter]);
}
#endregion
}
public class classBmpAndPtTLInfo
{
public Bitmap bmp;
public Point ptTL;
public classConfigStepLimbPosition[] limbPositions;
public classConfigStepHingePosition[] hingePositions;
public classCacheTreeNodeKeys cKey;
public classBmpAndPtTLInfo Copy()
{
classBmpAndPtTLInfo cRetVal = new classBmpAndPtTLInfo();
cRetVal.bmp = new Bitmap(bmp);
cRetVal.ptTL = ptTL;
cRetVal.limbPositions = new classConfigStepLimbPosition[limbPositions.Length];
for (int intLimbcounter = 0; intLimbcounter < limbPositions.Length; intLimbcounter++)
cRetVal.limbPositions[intLimbcounter] = limbPositions[intLimbcounter].Copy();
cRetVal.hingePositions = new classConfigStepHingePosition[hingePositions.Length];
for (int intHingeCounter = 0; intHingeCounter < hingePositions.Length; intHingeCounter++)
cRetVal.hingePositions[intHingeCounter] = hingePositions[intHingeCounter].Copy();
return cRetVal;
}
}
public class classConfigStepLimbPosition
{
public classMath.classRadialCoor cRad;
public Point pt;
public double dblAngle;
public classConfigStepLimbPosition Copy()
{
classConfigStepLimbPosition cRetVal = new classConfigStepLimbPosition();
cRetVal.cRad = cRad.Copy();
cRetVal.pt = pt;
cRetVal.dblAngle = dblAngle;
return cRetVal;
}
}
public class classConfigStepHingePosition
{
public classMath.classRadialCoor cRad;
public Point pt;
public classConfigStepHingePosition Copy()
{
classConfigStepHingePosition cRetVal = new classConfigStepHingePosition();
cRetVal.cRad = cRad.Copy();
cRetVal.pt = pt;
return cRetVal;
}
}
public class classConfigurationStep
{
public classConfigurationStepHinge[] hingeDetails;
}
public class classCacheTreeNodeKeys
{
public enum enuKeyIndex {filename, ConfigIndex, StepNum, Angle, Size, Mirror };
public double[] dblKeys = new double[5];
public string strFilename;
public classCacheTreeNodeKeys(string StrFilename,
int intConfigIndex,
int intStepNum,
double dblAngle,
double dblSize,
enuMirror eMirror)
{
int intIndexLastBackSlash = StrFilename.LastIndexOf("\\");
if (intIndexLastBackSlash > 0)
strFilename = StrFilename.Substring(intIndexLastBackSlash + 1);
else
strFilename = StrFilename;
if (strFilename.Length > 4 && strFilename.Contains("."))
strFilename = strFilename.Substring(0, strFilename.Length - 4);
dblKeys[0] = (double)intConfigIndex;
dblKeys[1] = (double)intStepNum;
dblKeys[2] = Math.Round( dblAngle, 4);
dblKeys[3] =Math.Round( dblSize,4);
dblKeys[4] = (double)(int)eMirror;
}
public string Filename { get { return strFilename; } }
public int ConfigIndex { get { return (int)dblKeys[0]; } }
public int Step { get { return (int)dblKeys[1]; } }
public double Angle{ get { return (double)dblKeys[2]; } }
public double Size { get { return (double)dblKeys[3]; } }
public enuMirror Mirror { get { return (enuMirror)dblKeys[4]; } }
}
public class classCacheTernaryTree_CharKeys_Node
{
static int intIDCounter = 0;
public int intID;
public char chrKey = (char)0;
public classCacheTernaryTree_CharKeys_Node Up = null;
public classCacheTernaryTree_CharKeys_Node Down = null;
public classCacheTernaryTree_CharKeys_Node Next = null;
public classCacheTernaryTree_DoubleKeys_Node cTerDoubleNode;
public classCacheTernaryTree_CharKeys_Node(char Key)
{
chrKey = Key;
intID = intIDCounter++;
}
}
public class classCacheTernaryTree_DoubleKeys_Node
{
static int intIDCounter = 0;
public int intID;
public double dblKey = 0;
public classCacheTernaryTree_DoubleKeys_Node Up = null;
public classCacheTernaryTree_DoubleKeys_Node Down = null;
public classCacheTernaryTree_DoubleKeys_Node Next = null;
public long lngFSPosition = -1;
public classBmpAndPtTLInfo cBmpAndPtTLInfo = null;// optional RAM storage
public classCacheTernaryTree_DoubleKeys_Node(double Key)
{
dblKey = Key;
intID = intIDCounter++;
}
static public double convertCacheKey(object objKey, int intKeyIndex)
{
switch (intKeyIndex)
{
case 0: // uint FS_ID
return (double)(GraphicsUnit)objKey;
case 1: // int config index
case 2: // int step
case 3: // int dir
return (double)(int)objKey;
case 4: // double size
return (double)objKey;
case 5: // enuMirror mirror
return (double)(int)(enuMirror)objKey;
default:
return -1.0;
}
}
}
public class classConfigurationStepHinge
{
public classSpriteHinge hinge;
public double angle;
classMath.classRadialCoor cRadCoor_Master;
/// <summary>
/// radial coordinate location relative to center of image
/// </summary>
public classMath.classRadialCoor RadCoor_Master
{
get { return cRadCoor_Master; }
set { cRadCoor_Master = value; }
}
classMath.classRadialCoor cRadCoor_Slave;
/// <summary>
/// radial coordinate location relative to center of image
/// </summary>
public classMath.classRadialCoor RadCoor_Slave
{
get { return cRadCoor_Slave; }
set { cRadCoor_Slave = value; }
}
}
public class classConfiguration
{
public string name;
public classSprite mainSprite;
public classSpriteLimb[] LimbDrawSequence;
public classConfigurationStep[] steps;
/// <summary>
/// returns the index of a limb in this configuration's DrawSequence identified by its name string
/// </summary>
/// <param name="strLimbName">name of limb to find</param>
/// <returns>integer index of limb in drawSequence array, -1 if not found</returns>
public int getLimbDrawSequenceIndex(string strLimbName)
{
strLimbName = strLimbName.ToUpper().Trim();
for (int intLimbCounter = 0; intLimbCounter < LimbDrawSequence.Length; intLimbCounter++)
if (strLimbName.CompareTo(LimbDrawSequence[intLimbCounter].Name.Trim().ToUpper()) == 0)
return intLimbCounter;
return -1;
}
}
public class formSprite : PerPixelForm.PerPixelAlphaForm
{
public classSprite cSprite;
public formSprite()
{
FormBorderStyle = FormBorderStyle.None;
ShowInTaskbar = false;
Visible = false;
TopMost = true;
}
public void drawMe(int ConfigurationIndex, int ConfigurationStep, Point ptLoc, enuMirror Mirror, double angle, double size)
{
cSprite.DisplaySize = size;
_intConfiguration = ConfigurationIndex;
_intStep = ConfigurationStep;
_dblSize = size;
_eMirror = Mirror;
_dblAngle = angle;
drawMe();
Pos = ptLoc;
Visible = true;
BringToFront();
}
void drawMe()
{
classBmpAndPtTLInfo cBmpImage = cSprite.getImageOnBitmap(intConfiguration, intStep, dblAngle, dblSize, eMirror, false);
SetBitmap(cBmpImage.bmp);
}
bool _bolForceDraw = false;
public bool ForceDraw
{
get { return _bolForceDraw; }
set
{
_bolForceDraw = value;
drawMe();
}
}
int _intConfiguration;
public int intConfiguration
{
get { return _intConfiguration; }
set
{
_intConfiguration = value;
drawMe();
}
}
int _intStep;
public int intStep
{
get { return _intStep; }
set
{
_intStep = value;
drawMe();
}
}
double _dblSize;
public double dblSize
{
get { return _dblSize; }
set
{
_dblSize = value;
drawMe();
}
}
enuMirror _eMirror;
public enuMirror eMirror
{
get { return _eMirror; }
set
{
_eMirror = value;
drawMe();
}
}
int _intDir;
public int intDir
{
get { return _intDir; }
set
{
_intDir = value;
drawMe();
}
}
Point _pos;
public Point Pos
{
get { return _pos; }
set
{
_pos = value;
PlaceMe();
}
}
void PlaceMe()
{
classBmpAndPtTLInfo cBmpPtTLInfo = classSpriteFileStream.searchCache(new classCacheTreeNodeKeys(cSprite.cFileStream.strFilename, intConfiguration, intStep, intDir, cSprite.DisplaySize, eMirror));
int intGrabLimbIndex = 0;
if (cSprite.limStationary != null)
{
for (int intLimbCounter = 0; intLimbCounter < cBmpPtTLInfo.limbPositions.Length; intLimbCounter++)
{
if (cSprite.limStationary == cSprite.limbs[intLimbCounter])
{
intGrabLimbIndex = intLimbCounter;
break;
}
}
Left = _pos.X + cBmpPtTLInfo.ptTL.X - cBmpPtTLInfo.limbPositions[intGrabLimbIndex].pt.X;
Top = _pos.Y + cBmpPtTLInfo.ptTL.Y - cBmpPtTLInfo.limbPositions[intGrabLimbIndex].pt.Y;
return;
}
Left = _pos.X + cBmpPtTLInfo.ptTL.X;
Top = _pos.Y + cBmpPtTLInfo.ptTL.Y;
}
double _dblAngle;
public double dblAngle
{
get { return _dblAngle; }
set
{
_dblAngle = value;
drawMe();
}
}
public void loadSprite(string strFilename)
{
cSprite =classSprite.spriteMaker.loadSprite(strFilename);
}
}
public class classSpriteFileStream
{
/// <summary>
/// every base value (angle =0, size = 1.0) of every step of all configurations are stored in the cache-file and retrieved in subsequent sessions whether the bolIAmCached variable is set to true or not. Setting this boolean to true forces all variations of Size & Angle to be cached as well resulting in a longer RAM-cache load time at start-up.
/// </summary>
public bool bolIAmCached = true;
public FileStream fs;
public long lngStartIndex;
public long lngSizeLongIndexInFileStream;
public classSpriteFileStream left;
public classSpriteFileStream right;
public string strFilename;
/// <summary>
/// when bolDebug is true, the cache file is cleared and the RAM-cache is set to null at startup.
/// </summary>
public static bool bolDebug = false;
public static FileStream fsCache_BmpInfo;
public static FileStream fsCache_BmpInfo_Rebuild;
public static BinaryFormatter formatter = new BinaryFormatter();
static Semaphore semaCacheTree = new Semaphore(1, 1);
static Semaphore semaCacheFS = new Semaphore(1, 1);
public static string strWorkingDirectory = System.IO.Directory.GetCurrentDirectory()
.ToUpper(new System.Globalization.CultureInfo("en-US"))
.Replace("BIN\\RELEASE", "")
.Replace("BIN\\DEBUG", "");
public static string strCache_BmpAndTLInfo_Filename = strWorkingDirectory + "Cache_BmpAndPtTLInfo.fs";
public static string strCache_BmpInfo_RAMCacheRebuild = strWorkingDirectory + "Cache_BmpInfoRAMRebuild.fs";
static public classCacheTernaryTree_CharKeys_Node cache;
static uint uintIDCounter;
uint uintFS_ID;
public uint FS_ID
{
get { return uintFS_ID; }
}
static bool bolCacheFileInitialized = false;
public void clearCache()
{
if (fsCache_BmpInfo != null)
fsCache_BmpInfo.Close();
if (System.IO.File.Exists(strCache_BmpAndTLInfo_Filename))
System.IO.File.Delete(strCache_BmpAndTLInfo_Filename);
if (fsCache_BmpInfo_Rebuild != null)
fsCache_BmpInfo_Rebuild.Close();
if (System.IO.File.Exists(strCache_BmpInfo_RAMCacheRebuild))
System.IO.File.Delete(strCache_BmpInfo_RAMCacheRebuild);
fsCache_BmpInfo = new FileStream(strCache_BmpAndTLInfo_Filename, FileMode.Create);
fsCache_BmpInfo_Rebuild = new FileStream(strCache_BmpInfo_RAMCacheRebuild, FileMode.Create);
}
/// <summary>
/// opens cache files and initializes RAM cache trees given existing file
/// </summary>
public class FormOpenCache : Form
{
ProgressBar proBar = new ProgressBar();
Label lbl = new Label();
System.Windows.Forms.Timer tmr = new System.Windows.Forms.Timer();
string strTitleBase = "";
int intNumRecordsLoaded = 0;
public FormOpenCache()
{
Controls.Add(proBar);
Controls.Add(lbl);
strTitleBase = "loading RAM Cache : ";
lbl.AutoSize = true;
FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
BackColor = Color.WhiteSmoke;
ShowInTaskbar = false;
VisibleChanged += new EventHandler(openCache_VisibleChanged);
tmr.Interval = 5;
tmr.Tick += new EventHandler(tmr_Tick);
}
void openCache_VisibleChanged(object sender, EventArgs e)
{
if (Visible)
{
Left = (int)(Screen.PrimaryScreen.WorkingArea.Width * .1);
proBar.Width
= Width
= (Screen.PrimaryScreen.WorkingArea.Width - 2 * Left);
proBar.Left = 0;
lbl.Left = 0;
lbl.Top = 0;
proBar.Top = lbl.Top + lbl.Height;
Height = proBar.Top + proBar.Height;
Top = (Screen.PrimaryScreen.WorkingArea.Height - Height) / 2;
proBar.Visible = true;
BringToFront();
if (!System.IO.File.Exists(strCache_BmpAndTLInfo_Filename) || !System.IO.File.Exists(strCache_BmpInfo_RAMCacheRebuild))
{
fsCache_BmpInfo = new FileStream(strCache_BmpAndTLInfo_Filename, FileMode.Create);
fsCache_BmpInfo_Rebuild = new FileStream(strCache_BmpInfo_RAMCacheRebuild, FileMode.Create);
}
else
{
/// there is an existing cache file -> open its File-stream and rebuild RAM cache trees with it
fsCache_BmpInfo = new FileStream(strCache_BmpAndTLInfo_Filename, FileMode.Open);
fsCache_BmpInfo_Rebuild = new FileStream(strCache_BmpInfo_RAMCacheRebuild, FileMode.Open);
}
fsCache_BmpInfo.Position = 0;
proBar.Value = 0;
proBar.Maximum = (int)(fsCache_BmpInfo_Rebuild.Length % int.MaxValue);
tmr.Enabled = true;
}
}
void tmr_Tick(object sender, EventArgs e)
{
tmr.Enabled = false;
if (fsCache_BmpInfo_Rebuild.Position >= fsCache_BmpInfo_Rebuild.Length)
{
Dispose();
return;
}
// read the next record sequentially
// read key
lbl.Text = strTitleBase + intNumRecordsLoaded.ToString();
intNumRecordsLoaded++;
proBar.Value = (int)(fsCache_BmpInfo_Rebuild.Position % int.MaxValue);
long lngPosition =(long)formatter.Deserialize( fsCache_BmpInfo_Rebuild); // remember the position of the start of this BmpInfo record
classCacheTreeNodeKeys cKey = new classCacheTreeNodeKeys(
(string)formatter.Deserialize(fsCache_BmpInfo_Rebuild),
(int)(double)formatter.Deserialize(fsCache_BmpInfo_Rebuild),
(int)(double)formatter.Deserialize(fsCache_BmpInfo_Rebuild),
(double)formatter.Deserialize(fsCache_BmpInfo_Rebuild),
(double)formatter.Deserialize(fsCache_BmpInfo_Rebuild),
(enuMirror)(int)(double)formatter.Deserialize(fsCache_BmpInfo_Rebuild)
);
/// cache the location of this bmpInfo into the RAM tree
classCacheTernaryTree_DoubleKeys_Node cTerDoubleNode = null;
if (cache == null)
{ // first element into tree
cache = initTernary_Char_Tree(cKey.Filename);
}
// traverse char ternary tree to find filename
classCacheTernaryTree_CharKeys_Node cTerCharNode = cache;
bool bolLoop = true;
int intCharIndex = 0;
while (bolLoop)
{
if (cKey.strFilename[intCharIndex] > cTerCharNode.chrKey )
{
if (cTerCharNode.Down == null)
cTerCharNode.Down = new classCacheTernaryTree_CharKeys_Node(cKey.strFilename[intCharIndex]);
cTerCharNode = cTerCharNode.Down;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else if (cKey.strFilename[intCharIndex] < cTerCharNode.chrKey)
{
if (cTerCharNode.Up == null)
cTerCharNode.Up = new classCacheTernaryTree_CharKeys_Node(cKey.strFilename[intCharIndex]);
cTerCharNode = cTerCharNode.Up;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else
{
if (intCharIndex == cKey.strFilename.Length - 1)
{ // match found
if (cTerCharNode.cTerDoubleNode == null)
{
cTerCharNode.cTerDoubleNode
= cTerDoubleNode
= initTernary_Double_Tree(cKey);
}
else
cTerDoubleNode = cTerCharNode.cTerDoubleNode;
bolLoop = false;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else
{
intCharIndex++;
if (cTerCharNode.Next == null)
cTerCharNode.Next = new classCacheTernaryTree_CharKeys_Node(cKey.strFilename[intCharIndex]);
cTerCharNode = cTerCharNode.Next;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
}
}
int intKeyIndex = 0;
bolLoop = true;
while (bolLoop)
{
if (cKey.dblKeys[intKeyIndex] > cTerDoubleNode.dblKey)
{
if (cTerDoubleNode.Down == null)
cTerDoubleNode.Down = new classCacheTernaryTree_DoubleKeys_Node(cKey.dblKeys[intKeyIndex]);
cTerDoubleNode = cTerDoubleNode.Down;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else if (cKey.dblKeys[intKeyIndex] < cTerDoubleNode.dblKey)
{
if (cTerDoubleNode.Up == null)
cTerDoubleNode.Up = new classCacheTernaryTree_DoubleKeys_Node(cKey.dblKeys[intKeyIndex]);
cTerDoubleNode = cTerDoubleNode.Up;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else
{
if (intKeyIndex == cKey.dblKeys.Length - 1)
{ // match found
if (cTerDoubleNode.lngFSPosition > 0)
MessageBox.Show("error : rebuild RAM Cache repeating itself");
cTerDoubleNode.lngFSPosition = lngPosition;
bolLoop = false;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else
{
intKeyIndex++;
if (cTerDoubleNode.Next == null)
cTerDoubleNode.Next = new classCacheTernaryTree_DoubleKeys_Node(cKey.dblKeys[intKeyIndex]);
cTerDoubleNode = cTerDoubleNode.Next;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
}
}
//semaCacheTree.Release();
//semaCacheFS.Release();
if (fsCache_BmpInfo_Rebuild.Position < fsCache_BmpInfo_Rebuild.Length)
tmr.Enabled = true;
else
Dispose();
}
}
public classSpriteFileStream(string filename)
{
if (!bolCacheFileInitialized)
{
//if (bolDebug)
// clearCache();
FormOpenCache frmOpenCache = new FormOpenCache();
frmOpenCache.ShowDialog();
//clearCache();
bolCacheFileInitialized = true;
}
strFilename = filename.ToUpper();
if (System.IO.File.Exists(strFilename))
fs = new FileStream(strFilename, FileMode.Open);
else
fs = new FileStream(strFilename, FileMode.Create);
uintFS_ID = uintIDCounter++;
}
static bool CacheInRAM
{
get { return classSprite.CacheInRAM; }
}
/// <summary>
/// retrieves bmp-info for sprite from the cache-file stream using the information returned by the appendBmpPtTLInfoToFS()
/// </summary>
/// <param name="lngPositionOfInfoOnIndexCacheFS">position on index-cache-fs used to retrieve bmp-info</param>
/// <returns>requested bmp-info</returns>
static public classBmpAndPtTLInfo getBmpPtTLInfoFromFS(long lngFSPosition)
{
semaCacheFS.WaitOne();
fsCache_BmpInfo.Position = lngFSPosition;
classBmpAndPtTLInfo cBmpAndPtTLInfo = new classBmpAndPtTLInfo();
cBmpAndPtTLInfo.bmp = (Bitmap)formatter.Deserialize(fsCache_BmpInfo);
cBmpAndPtTLInfo.ptTL = (Point)formatter.Deserialize(fsCache_BmpInfo);
cBmpAndPtTLInfo.limbPositions = new classConfigStepLimbPosition[(int)formatter.Deserialize(fsCache_BmpInfo)];
for (int intLimbPositionCounter = 0; intLimbPositionCounter < cBmpAndPtTLInfo.limbPositions.Length; intLimbPositionCounter++)
{
cBmpAndPtTLInfo.limbPositions[intLimbPositionCounter] = new classConfigStepLimbPosition();
cBmpAndPtTLInfo.limbPositions[intLimbPositionCounter].dblAngle = (double)formatter.Deserialize(fsCache_BmpInfo);
cBmpAndPtTLInfo.limbPositions[intLimbPositionCounter].pt = (Point)formatter.Deserialize(fsCache_BmpInfo);
cBmpAndPtTLInfo.limbPositions[intLimbPositionCounter].cRad = new classMath.classRadialCoor( (double)formatter.Deserialize(fsCache_BmpInfo), (double)formatter.Deserialize(fsCache_BmpInfo));
}
cBmpAndPtTLInfo.hingePositions = new classConfigStepHingePosition[cBmpAndPtTLInfo.limbPositions.Length];
for (int intHingePositionCounter = 0; intHingePositionCounter < cBmpAndPtTLInfo.limbPositions.Length; intHingePositionCounter++)
{
cBmpAndPtTLInfo.hingePositions[intHingePositionCounter] = new classConfigStepHingePosition();
cBmpAndPtTLInfo.hingePositions[intHingePositionCounter].cRad = new classMath.classRadialCoor((double)formatter.Deserialize(fsCache_BmpInfo), (double)formatter.Deserialize(fsCache_BmpInfo));
cBmpAndPtTLInfo.hingePositions[intHingePositionCounter].pt = (Point)formatter.Deserialize(fsCache_BmpInfo);
}
semaCacheFS.Release();
return cBmpAndPtTLInfo;
}
/// <summary>
/// appends input bmp-info to the cache file-stream and returns the position of index in index-file
/// </summary>
/// <param name="cBmpAndPtTLInfo">data to be sotred</param>
/// <returns>position in index-cache-filestream used to retrieve info in getBmpPtTLInfoFromFs</returns>
static public long appendBmpPtTLInfoToFS(ref classBmpAndPtTLInfo cBmpAndPtTLInfo)
{
semaCacheFS.WaitOne();
// position bmpfile ready to append
long lngFSPosition = fsCache_BmpInfo.Length;
fsCache_BmpInfo.Position = lngFSPosition;
// write keyinfo on rebuild-RAMcache file
fsCache_BmpInfo_Rebuild.Position = fsCache_BmpInfo_Rebuild.Length;
formatter.Serialize(fsCache_BmpInfo_Rebuild, fsCache_BmpInfo.Position);
formatter.Serialize(fsCache_BmpInfo_Rebuild, cBmpAndPtTLInfo.cKey.Filename);
for (int intKeyCounter = 0; intKeyCounter < cBmpAndPtTLInfo.cKey.dblKeys.Length; intKeyCounter++)
formatter.Serialize(fsCache_BmpInfo_Rebuild, cBmpAndPtTLInfo.cKey.dblKeys[intKeyCounter]);
// write bmp-info onto bmpfile
formatter.Serialize(fsCache_BmpInfo, cBmpAndPtTLInfo.bmp);
formatter.Serialize(fsCache_BmpInfo, cBmpAndPtTLInfo.ptTL);
formatter.Serialize(fsCache_BmpInfo, cBmpAndPtTLInfo.limbPositions.Length);
for (int intLimbPositionCounter = 0; intLimbPositionCounter < cBmpAndPtTLInfo.limbPositions.Length; intLimbPositionCounter++)
{
formatter.Serialize(fsCache_BmpInfo, cBmpAndPtTLInfo.limbPositions[intLimbPositionCounter].dblAngle);
formatter.Serialize(fsCache_BmpInfo, cBmpAndPtTLInfo.limbPositions[intLimbPositionCounter].pt);
formatter.Serialize(fsCache_BmpInfo, cBmpAndPtTLInfo.limbPositions[intLimbPositionCounter].cRad.angle);
formatter.Serialize(fsCache_BmpInfo, cBmpAndPtTLInfo.limbPositions[intLimbPositionCounter].cRad.radius);
}
for (int intHingePositionCounter = 0; intHingePositionCounter < cBmpAndPtTLInfo.hingePositions.Length; intHingePositionCounter++)
{
formatter.Serialize(fsCache_BmpInfo, cBmpAndPtTLInfo.hingePositions[intHingePositionCounter].cRad.angle);
formatter.Serialize(fsCache_BmpInfo, cBmpAndPtTLInfo.hingePositions[intHingePositionCounter].cRad.radius);
formatter.Serialize(fsCache_BmpInfo, cBmpAndPtTLInfo.hingePositions[intHingePositionCounter].pt);
}
semaCacheFS.Release();
return lngFSPosition;
}
static public classBmpAndPtTLInfo searchCache(ref classCacheTernaryTree_DoubleKeys_Node cacheRootNode,
string strFilename,
int intConfig,
int intStep,
double dblAngle,
double dblSize,
enuMirror eMirror)
{ return searchCache(new classCacheTreeNodeKeys(strFilename, intConfig, intStep, dblAngle, dblSize, eMirror)); }
static public classBmpAndPtTLInfo searchCache(classCacheTreeNodeKeys cKey)
{
if (cache == null)
return null;
classCacheTernaryTree_DoubleKeys_Node cTerDoubleNode = null;
// search binary tree
classCacheTernaryTree_CharKeys_Node cTerCharNode = cache;
int intCharIndex = 0;
bool bolLoop = true;
while ( bolLoop)
{
char chrSearchKey = cKey.strFilename[intCharIndex];
if (chrSearchKey > cTerCharNode.chrKey)
{
if (cTerCharNode.Down == null)
return null;
else
cTerCharNode = cTerCharNode.Down;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else if (chrSearchKey < cTerCharNode.chrKey)
{
if (cTerCharNode.Up == null)
return null;
else
cTerCharNode = cTerCharNode.Up;
}
else
{//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
if (intCharIndex == cKey.strFilename.Length - 1)
{
if (cTerCharNode.cTerDoubleNode == null)
return null;
else
{
cTerDoubleNode = cTerCharNode.cTerDoubleNode;
bolLoop = false;
}
}
else
{
intCharIndex++;
cTerCharNode = cTerCharNode.Next;
}
}
}
int intKeyIndex = 0;
while (true)
{
double dblSearchKey = cKey.dblKeys[intKeyIndex];
if (dblSearchKey > cTerDoubleNode.dblKey)
{
if (cTerDoubleNode.Down == null)
return null;
else
cTerDoubleNode = cTerDoubleNode.Down;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else if (dblSearchKey < cTerDoubleNode.dblKey)
{
if (cTerDoubleNode.Up == null)
return null;
else
cTerDoubleNode = cTerDoubleNode.Up;
}
else
{//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
if (intKeyIndex == cKey.dblKeys.Length - 1)
{
if (CacheInRAM)
return cTerDoubleNode.cBmpAndPtTLInfo;
else
return getBmpPtTLInfoFromFS(cTerDoubleNode.lngFSPosition);
}
else
{
intKeyIndex++;
cTerDoubleNode = cTerDoubleNode.Next;
}
}
}
}
static classCacheTernaryTree_DoubleKeys_Node initTernary_Double_Tree(classCacheTreeNodeKeys cKey)
{
classCacheTernaryTree_DoubleKeys_Node cRetVal = new classCacheTernaryTree_DoubleKeys_Node(cKey.dblKeys[0]);
classCacheTernaryTree_DoubleKeys_Node cTerNode = cRetVal;
for (int intKeyCounter = 1; intKeyCounter < cKey.dblKeys.Length; intKeyCounter++)
{
cTerNode.Next = new classCacheTernaryTree_DoubleKeys_Node(cKey.dblKeys[intKeyCounter]);
cTerNode = cTerNode.Next;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
return cRetVal;
}
static classCacheTernaryTree_CharKeys_Node initTernary_Char_Tree(string strFilename)
{
classCacheTernaryTree_CharKeys_Node cRetVal = new classCacheTernaryTree_CharKeys_Node(strFilename[0]);
classCacheTernaryTree_CharKeys_Node cTerNode = cRetVal;
for (int intKeyCounter = 1; intKeyCounter < strFilename.Length; intKeyCounter++)
{
cTerNode.Next = new classCacheTernaryTree_CharKeys_Node(strFilename[intKeyCounter]);
cTerNode = cTerNode.Next;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
return cRetVal;
}
static public void Cache(ref classBmpAndPtTLInfo cBmpAndPtTLInfo, classCacheTreeNodeKeys cKey)
{
semaCacheTree.WaitOne();
classCacheTernaryTree_DoubleKeys_Node cTerDoubleNode = null;
cBmpAndPtTLInfo.cKey = cKey;
if (cache == null)
{ // first element into tree
cache = initTernary_Char_Tree(cKey.Filename);
cache.cTerDoubleNode = initTernary_Double_Tree(cKey);
}
// traverse char ternary tree to file appropriate file
classCacheTernaryTree_CharKeys_Node cTerCharNode = cache;
int intCharIndex = 0;
bool bolLoop = true;
while (bolLoop)
{
if (cKey.strFilename[intCharIndex] > cTerCharNode.chrKey)
{
if (cTerCharNode.Down == null)
cTerCharNode.Down = new classCacheTernaryTree_CharKeys_Node(cKey.strFilename[intCharIndex]);
cTerCharNode = cTerCharNode.Down;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else if (cKey.strFilename[intCharIndex] < cTerCharNode.chrKey)
{
if (cTerCharNode.Up == null)
cTerCharNode.Up = new classCacheTernaryTree_CharKeys_Node(cKey.strFilename[intCharIndex]);
cTerCharNode = cTerCharNode.Up;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else
{
if (intCharIndex == cKey.strFilename.Length - 1)
{ // match found
if (cTerCharNode.cTerDoubleNode == null)
{ // data not yet cached in HD
cTerCharNode.cTerDoubleNode = initTernary_Double_Tree(cKey);
}
cTerDoubleNode = cTerCharNode.cTerDoubleNode;
bolLoop = false;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else
{
intCharIndex++;
if (cTerCharNode.Next == null)
cTerCharNode.Next = new classCacheTernaryTree_CharKeys_Node(cKey.strFilename[intCharIndex]);
cTerCharNode = cTerCharNode.Next;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
}
}
// traverse double-keys ternary tree to cache this Bmp-info
int intKeyIndex = 0;
while (true)
{
if (cKey.dblKeys[intKeyIndex] > cTerDoubleNode.dblKey)
{
if (cTerDoubleNode.Down == null)
cTerDoubleNode.Down = new classCacheTernaryTree_DoubleKeys_Node(cKey.dblKeys[intKeyIndex]);
cTerDoubleNode = cTerDoubleNode.Down;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else if (cKey.dblKeys[intKeyIndex] < cTerDoubleNode.dblKey)
{
if (cTerDoubleNode.Up == null)
cTerDoubleNode.Up = new classCacheTernaryTree_DoubleKeys_Node(cKey.dblKeys[intKeyIndex]);
cTerDoubleNode = cTerDoubleNode.Up;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else
{
if (intKeyIndex == cKey.dblKeys.Length - 1)
{ // match found
if (cTerDoubleNode.lngFSPosition < 0)
{ // data not yet cached in HD
cTerDoubleNode.lngFSPosition = appendBmpPtTLInfoToFS(ref cBmpAndPtTLInfo);
}
if (CacheInRAM)
cTerDoubleNode.cBmpAndPtTLInfo = cBmpAndPtTLInfo;
semaCacheTree.Release();
return;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
else
{
intKeyIndex++;
if (cTerDoubleNode.Next == null)
cTerDoubleNode.Next = new classCacheTernaryTree_DoubleKeys_Node(cKey.dblKeys[intKeyIndex]);
cTerDoubleNode = cTerDoubleNode.Next;
}//0.ID, 1.Config, 2.Step, 3.Dir, 4.Size, 5.Mirror
}
}
}
}
public class classSprite
{
public static classSpriteMaker spriteMaker = new classSpriteMaker();
public classSpriteLimb limStationary;
public classSpriteLimb MasterLimb;
public classConfiguration[] Configurations;
classConfiguration _conCurrent;
public classConfiguration conCurrent { get { return _conCurrent; } }
int _intCurrent_Configuration;
public int intCurrent_Configuration
{
get {return _intCurrent_Configuration; }
set
{
if (value >= 0 && value < Configurations.Length)
{
_intCurrent_Configuration = value;
_conCurrent = Configurations[_intCurrent_Configuration];
}
}
}
public int intCurrent_ConfigurationStep;
int intImagesPerRotation;
double dblImagesPerRotation;
public classSpriteFileStream cFileStream;
public enuMirror eMirror;
/// <summary>
/// when set output configuration images are cached in RAM. Memory consumption is not checked and may result in excessively large memory costs if sprite images DisplaySize varies frequently.
/// </summary>
static bool bolRamCache;
public static bool CacheInRAM
{
get { return bolRamCache; }
set
{
bolRamCache = value;
}
}
public double ImagesPerRotation
{
get { return dblImagesPerRotation; }
set
{
intImagesPerRotation = (int)Math.Floor(value);
dblImagesPerRotation = (double)intImagesPerRotation;
}
}
public classSprite()
{
setImagesPerRotation(16);
}
public classSprite(int intImagesPerQuarterRotation)
{
setImagesPerRotation(intImagesPerQuarterRotation);
}
void setImagesPerRotation(int intImagesPerQuarterRotation)
{
ImagesPerRotation = intImagesPerQuarterRotation * 4;
}
public long getLimbImageIndex(int intLimb, int intImage)
{
return (long)(cFileStream.lngStartIndex + (cFileStream.lngSizeLongIndexInFileStream * ImagesPerRotation / 4) * intLimb + (cFileStream.lngSizeLongIndexInFileStream * intImage));
}
public Bitmap getLimbImage(int intLimb, int intImage)
{
cFileStream.fs.Position = getLimbImageIndex(intLimb, intImage);
cFileStream.fs.Position = (long)classSpriteFileStream.formatter.Deserialize(cFileStream.fs);
return (Bitmap)classSpriteFileStream.formatter.Deserialize(cFileStream.fs);
}
string strMyName = "";
public string myName
{
get { return strMyName; }
set { strMyName = value; }
}
double dblDisplaySize = 1.0;
/// <summary>
/// double variable factor which determines size of output image relative to original images size where 1.0 is the same
/// </summary>
public double DisplaySize
{
get { return dblDisplaySize; }
set { dblDisplaySize = value; }
}
public classSpriteLimb[] limbs = new classSpriteLimb[0];
public Sprite.classSpriteHinge[] hinges = new classSpriteHinge[0];
/// <summary>
/// displays the sprite in the specified configuration and step at a point on referenced bitmap
/// all of the sprite's hinges are set to their specified configuration and step values
/// </summary>
/// <param name="bmpOutput">reference bitmap on which the sprite is to be drawn</param>
/// <param name="intConfigurationIndex">sprite's output configuration index value</param>
/// <param name="intConfigurationStep">sprite's output configuration step value</param>
/// <param name="ptOnScreenLocation">point on the screen where the center of the sprite's master limb is to be located</param>
public void putConfigurationOnScreen(ref Bitmap bmpOutput,
int intConfigurationIndex,
int intConfigurationStep,
Point ptOnScreenLocation)
{
putConfigurationOnScreen(ref bmpOutput,
intConfigurationIndex,
intConfigurationStep,
ptOnScreenLocation,
0,
DisplaySize,
eMirror,
false);
}
/// <summary>
/// displays the sprite in the specified configuration and step at a point on referenced bitmap
/// all of the sprite's hinges are set to their specified configuration and step values
/// </summary>
/// <param name="bmpOutput">reference bitmap on which the sprite is to be drawn</param>
/// <param name="strConfigurationName">sprite's output configuration name</param>
/// <param name="intConfigurationStep">sprite's output configuration step value</param>
/// <param name="ptOnScreenLocation">point on the screen where the center of the sprite's master limb is to be located</param>
public void putConfigurationOnScreen(ref Bitmap bmpOutput,
string strConfigurationName,
int intConfigurationStep,
Point ptOnScreenLocation)
{
putConfigurationOnScreen(ref bmpOutput,
getIndexOfConfigurationByName(strConfigurationName),
intConfigurationStep,
ptOnScreenLocation,
0,
DisplaySize,
eMirror,
false);
}
/// <summary>
/// displays the sprite in the specified configuration and step at a point on referenced bitmap
/// all of the sprite's hinges are set to their specified configuration and step values
/// </summary>
/// <param name="bmpOutput">reference bitmap on which the sprite is to be drawn</param>
/// <param name="strConfigurationName">sprite's output configuration name</param>
/// <param name="intConfigurationStep">sprite's output configuration step value</param>
/// <param name="ptOnScreenLocation">point on the screen where the center of the sprite's master limb is to be located</param>
/// <param name="DisplaySize">double variable which is multiplied times all size relevant parameters in the drawing sequence 1.0=original image size</param>
/// <param name="mirror">configuration image reflected in any of four directions, (none, vertical, horizontal or both)</param>
public void putConfigurationOnScreen(ref Bitmap bmpOutput,
string strConfigurationName,
int intConfigurationStep,
Point ptOnScreenLocation,
double displaySize,
enuMirror mirror)
{
putConfigurationOnScreen(ref bmpOutput,
getIndexOfConfigurationByName(strConfigurationName),
intConfigurationStep,
ptOnScreenLocation,
0,
displaySize,
mirror,
false);
}
/// <summary>
/// displays the sprite in the specified configuration and step at a point on referenced bitmap
/// all of the sprite's hinges are set to their specified configuration and step values
/// </summary>
/// <param name="bmpOutput">reference bitmap on which the sprite is to be drawn</param>
/// <param name="intConfigurationIndex">sprite's output configuration index value</param>
/// <param name="intConfigurationStep">sprite's output configuration step value</param>
/// <param name="ptOnScreenLocation">point on the screen where the center of the sprite's master limb is to be located</param>
/// <param name="DisplaySize">double variable which is multiplied times all size relevant parameters in the drawing sequence 1.0=original image size</param>
/// <param name="mirror">configuration image reflected in any of four directions, (none, vertical, horizontal or both)</param>
public void putConfigurationOnScreen(ref Bitmap bmpOutput,
int intConfigurationIndex,
int intConfigurationStep,
Point ptOnScreenLocation,
double dblAngle,
double DisplaySize,
enuMirror mirror,
bool bolForceRebuild)
{
if (bmpOutput == null)
return;
if (Configurations == null
|| Configurations.Length <= intConfigurationIndex
|| intConfigurationIndex < 0
|| intConfigurationStep < 0
|| Configurations[intConfigurationIndex].steps == null
|| Configurations[intConfigurationIndex].steps.Length <= intConfigurationStep
)
return;
intCurrent_ConfigurationStep = intConfigurationStep;
intCurrent_Configuration = intConfigurationIndex;
eMirror = mirror;
if (MasterLimb.IRotate)
{
MasterLimb.Angle = dblAngle;
MasterLimb.setDir();
}
if (Configurations[intConfigurationIndex].steps != null)
{
classBmpAndPtTLInfo cBmpAndPtTLInfo = getImageOnBitmap(intConfigurationIndex, intConfigurationStep, dblAngle, DisplaySize, mirror, false);
using (Graphics g = Graphics.FromImage(cBmpAndPtTLInfo.bmp))
g.DrawImage(cBmpAndPtTLInfo.bmp, new Point(ptOnScreenLocation.X - cBmpAndPtTLInfo.ptTL.X, ptOnScreenLocation.Y - cBmpAndPtTLInfo.ptTL.Y));
}
if (eMirror == enuMirror.VerticalAndHorizontal)
rotateMasterLimbSlaveByPi();
}
/// <summary>
/// this function arranges the sprite's hinges according to the values stored in its configurations for a specific configuration & step
/// </summary>
/// <param name="intConfigurationIndex">configuration index to which hinges are to be set</param>
/// <param name="intConfigurationStep">configuration step to which hinges are to be set</param>
public void setSpriteHingesToConfiguration(int intConfigurationIndex, int intConfigurationStep)
{
intCurrent_Configuration = intConfigurationIndex;
intCurrent_ConfigurationStep = intConfigurationStep;
if (intConfigurationIndex >= 0 && intConfigurationIndex < Configurations.Length)
{
intCurrent_Configuration = intConfigurationIndex;
}
if (intConfigurationStep < 0)
intConfigurationStep = 0;
// set up hinges for unmirrored configuration
for (int intHingeCounter = 0;
intHingeCounter < Configurations[intConfigurationIndex].steps[intConfigurationStep].hingeDetails.Length;
intHingeCounter++)
try
{
hinges[intHingeCounter].Angle
= Configurations[intConfigurationIndex]
.steps[intConfigurationStep]
.hingeDetails[intHingeCounter]
.angle;
}
catch (Exception) { }
}
void rotateMasterLimbSlaveByPi()
{
enuMirror eRememberMirror = eMirror;
eMirror = enuMirror.none;
for (int intSlaveCounter = 0; intSlaveCounter < MasterLimb.mySlaveLimbs.Length; intSlaveCounter++)
MasterLimb.mySlaveLimbs[intSlaveCounter].MasterHinge.Angle = classMath.cleanAngle(MasterLimb.mySlaveLimbs[intSlaveCounter].MasterHinge.Angle + Math.PI);
eMirror = eRememberMirror;
}
SolidBrush brBack;
/// <summary>
/// set the color of sprite's outline. setting it to White resets to default;
/// </summary>
public Color ColorOutline
{
get
{
if (brBack != null)
return brBack.Color;
else
return Color.White;
}
set
{
if (value.R == Color.White.R
&& value.G == Color.White.G
&& value.B == Color.White.B
&& value.A == Color.White.A)
brBack = null;
else
brBack = new SolidBrush(value);
}
}
bool bolUseCachedImages = true;
public bool UseCachedImages
{
get { return bolUseCachedImages; }
set
{
bolUseCachedImages = value;
}
}
public void setBmpInfoImage(ref classBmpAndPtTLInfo cBmpInfo, ref classSpriteLimb[] limbDrawSequence, double dblAngle, double dblSize, enuMirror eMirror)
{
//dblAngle = 0;
Bitmap[] bmpLimbImages = new Bitmap[limbDrawSequence.Length];
Rectangle[] recDest = new Rectangle[limbDrawSequence.Length];
Point ptTL = new Point(), ptBR = new Point();
// cycle through each limb
for (int intLimbCounter = 0; intLimbCounter < cBmpInfo.limbPositions.Length; intLimbCounter++)
{
// reposition limb
cBmpInfo.limbPositions[intLimbCounter].pt = new Point((int)(cBmpInfo.limbPositions[intLimbCounter].cRad.radius * dblSize * Math.Cos(cBmpInfo.limbPositions[intLimbCounter].cRad.angle + dblAngle)),
(int)(cBmpInfo.limbPositions[intLimbCounter].cRad.radius * dblSize * Math.Sin(cBmpInfo.limbPositions[intLimbCounter].cRad.angle + dblAngle)));
// reposition hinge
cBmpInfo.hingePositions[intLimbCounter].pt = new Point((int)(cBmpInfo.hingePositions[intLimbCounter].cRad.radius * dblSize * Math.Cos(cBmpInfo.hingePositions[intLimbCounter].cRad.angle + dblAngle)),
(int)(cBmpInfo.hingePositions[intLimbCounter].cRad.radius * dblSize * Math.Sin(cBmpInfo.hingePositions[intLimbCounter].cRad.angle + dblAngle)));
// set up limb's image for this output
switch (eMirror)
{
case enuMirror.none:
bmpLimbImages[intLimbCounter] = new Bitmap(limbs[intLimbCounter].getLimbImage(cBmpInfo.limbPositions[intLimbCounter].dblAngle + dblAngle));
break;
case enuMirror.vertical:
bmpLimbImages[intLimbCounter] = new Bitmap(limbs[intLimbCounter].getLimbImage(ref limbs[intLimbCounter].bmpSpriteLimb, classMath.getMirrorAngle(cBmpInfo.limbPositions[intLimbCounter].dblAngle + dblAngle, enuMirror.vertical), enuMirror.none));
bmpLimbImages[intLimbCounter].RotateFlip(RotateFlipType.RotateNoneFlipY);
break;
case enuMirror.horizontal:
bmpLimbImages[intLimbCounter] = new Bitmap(limbs[intLimbCounter].getLimbImage(ref limbs[intLimbCounter].bmpSpriteLimb, classMath.getMirrorAngle(cBmpInfo.limbPositions[intLimbCounter].dblAngle + dblAngle, enuMirror.horizontal), enuMirror.none));
bmpLimbImages[intLimbCounter].RotateFlip(RotateFlipType.RotateNoneFlipX);
break;
case enuMirror.VerticalAndHorizontal:
bmpLimbImages[intLimbCounter] = new Bitmap(limbs[intLimbCounter].getLimbImage(cBmpInfo.limbPositions[intLimbCounter].dblAngle + dblAngle));
break;
}
if (ptTL.X > cBmpInfo.limbPositions[intLimbCounter].pt.X - (int)(bmpLimbImages[intLimbCounter].Width * dblSize / 2))
ptTL.X = cBmpInfo.limbPositions[intLimbCounter].pt.X - (int)(bmpLimbImages[intLimbCounter].Width * dblSize / 2);
if (ptTL.Y > cBmpInfo.limbPositions[intLimbCounter].pt.Y - (int)(bmpLimbImages[intLimbCounter].Height * dblSize / 2))
ptTL.Y = cBmpInfo.limbPositions[intLimbCounter].pt.Y - (int)(bmpLimbImages[intLimbCounter].Height * dblSize / 2);
if (ptBR.X < cBmpInfo.limbPositions[intLimbCounter].pt.X + (int)(bmpLimbImages[intLimbCounter].Width * dblSize / 2))
ptBR.X = cBmpInfo.limbPositions[intLimbCounter].pt.X + (int)(bmpLimbImages[intLimbCounter].Width * dblSize / 2);
if (ptBR.Y < cBmpInfo.limbPositions[intLimbCounter].pt.Y + (int)(bmpLimbImages[intLimbCounter].Height * dblSize / 2))
ptBR.Y = cBmpInfo.limbPositions[intLimbCounter].pt.Y + (int)(bmpLimbImages[intLimbCounter].Height * dblSize / 2);
}
// create new output image
Size szNewImage = new Size(ptBR.X - ptTL.X, ptBR.Y - ptTL.Y);
if (szNewImage.Height < 1) szNewImage.Height = 1;
if (szNewImage.Width < 1) szNewImage.Width = 1;
cBmpInfo.ptTL = new Point(-ptTL.X, -ptTL.Y);
// build Dest rectangles
for (int intLimbCounter = 0; intLimbCounter < cBmpInfo.limbPositions.Length; intLimbCounter++)
{
// set up image dest-rect
recDest[intLimbCounter] = new Rectangle((int)(cBmpInfo.ptTL.X + cBmpInfo.limbPositions[intLimbCounter].pt.X - bmpLimbImages[intLimbCounter].Width * dblSize / 2),
(int)(cBmpInfo.ptTL.Y + cBmpInfo.limbPositions[intLimbCounter].pt.Y - bmpLimbImages[intLimbCounter].Height * dblSize / 2),
(int)(bmpLimbImages[intLimbCounter].Width * dblSize),
(int)(bmpLimbImages[intLimbCounter].Height * dblSize));
}
cBmpInfo.bmp = new Bitmap(szNewImage.Width, szNewImage.Height);
// draw limbs in draw sequence where they belong on new image
using (Graphics g = Graphics.FromImage(cBmpInfo.bmp))
{
if (brBack != null)
g.FillRectangle(brBack, new Rectangle(0, 0, cBmpInfo.bmp.Width, cBmpInfo.bmp.Height));
for (int intLimCounter = 0; intLimCounter < limbDrawSequence.Length; intLimCounter++)
{
Rectangle recSrc = new Rectangle(0, 0, bmpLimbImages[limbDrawSequence[intLimCounter].intMyLimbID].Width, bmpLimbImages[limbDrawSequence[intLimCounter].intMyLimbID].Height);
bmpLimbImages[limbDrawSequence[intLimCounter].intMyLimbID].MakeTransparent();
g.DrawImage(bmpLimbImages[limbDrawSequence[intLimCounter].intMyLimbID], recDest[limbDrawSequence[intLimCounter].intMyLimbID], recSrc, GraphicsUnit.Pixel);
}
}
if (MakeSpriteTransparent)
cBmpInfo.bmp.MakeTransparent();
dblDisplaySize = dblSize;
MasterLimb.Angle = dblAngle;
}
public classBmpAndPtTLInfo getImageOnBitmap(int intConfigurationIndex, int intStep, double Angle, double DisplaySize, enuMirror mirror, bool bolForceRebuild)
{
MasterLimb.Angle = Angle;
MasterLimb.setDir();
dblDisplaySize = DisplaySize;
eMirror = mirror;
if (Configurations == null
|| Configurations.Length < intConfigurationIndex
|| intConfigurationIndex < 0)
return null;
intCurrent_Configuration = intConfigurationIndex;
intCurrent_ConfigurationStep = intStep;
classBmpAndPtTLInfo cBmpPtTLInfo = null;
classCacheTreeNodeKeys cCacheKey = null;
// try fetching the exact image we're looking for
cCacheKey = new classCacheTreeNodeKeys(cFileStream.strFilename,
intConfigurationIndex,
intStep,
Angle,
DisplaySize,
mirror);
cBmpPtTLInfo = classSpriteFileStream.searchCache(cCacheKey);
if (cBmpPtTLInfo != null
&& !bolForceRebuild
&& UseCachedImages)
{
return cBmpPtTLInfo;
}
// try fetching the same image at default size=1.0 & angle=0
classCacheTreeNodeKeys cCacheKey_DefaultSizeAndAngle = new classCacheTreeNodeKeys(cFileStream.strFilename,
intConfigurationIndex,
intStep,
0,
1.0,
mirror);
cBmpPtTLInfo = classSpriteFileStream.searchCache(cCacheKey_DefaultSizeAndAngle);
if (cBmpPtTLInfo != null
&& !bolForceRebuild
&& UseCachedImages)
{
cBmpPtTLInfo = cBmpPtTLInfo.Copy(); // make a copy (or the RAM-cached data will be corrupted)
// resize & angle default image to desired image
setBmpInfoImage(ref cBmpPtTLInfo, ref Configurations[intConfigurationIndex].LimbDrawSequence, Angle, dblDisplaySize, mirror);
if (cFileStream.bolIAmCached)
{
// create cache-key for new image
cCacheKey = new classCacheTreeNodeKeys(cFileStream.strFilename, intConfigurationIndex, intStep, Angle, dblDisplaySize, mirror);
// cache new image and return value
classSpriteFileStream.Cache(ref cBmpPtTLInfo, cCacheKey);
}
return cBmpPtTLInfo;
}
// no cached image can be found -> build it
Point ptTL = new Point(0, 0);
Point ptBR = new Point(0, 0);
classSpriteLimb[] limDrawSequence = conCurrent.LimbDrawSequence;
switch (mirror)
{
case enuMirror.none:
MasterLimb.Loc = new Point(0, 0);
eMirror = enuMirror.none;
if (dblDisplaySize == 1.0 && Angle == 0)
{
// put image together for size 1.0 & angle=0, using the original hinge connection angles
MasterLimb.Angle = 0;
MasterLimb.setDir();
setSpriteHingesToConfiguration(intConfigurationIndex, intStep);
putImageOntoScreen_recursion(ref MasterLimb, 1.0);
cBmpPtTLInfo = new classBmpAndPtTLInfo();
cBmpPtTLInfo.ptTL = new Point(-MasterLimb.myCurrentImage.Width / 2, -MasterLimb.myCurrentImage.Height / 2);
ptBR = new Point(MasterLimb.myCurrentImage.Width / 2, MasterLimb.myCurrentImage.Height / 2);
for (int intHingeCounter = 0; intHingeCounter < hinges.Length; intHingeCounter++)
{
Sprite.classSpriteLimb thisLimb = hinges[intHingeCounter].Limb_Slave;
if (thisLimb.recDest.Left < cBmpPtTLInfo.ptTL.X)
cBmpPtTLInfo.ptTL.X = thisLimb.recDest.Left;
if (thisLimb.recDest.Left + thisLimb.recDest.Width > ptBR.X)
ptBR.X = thisLimb.recDest.Left + thisLimb.recDest.Width;
if (thisLimb.recDest.Top < cBmpPtTLInfo.ptTL.Y)
cBmpPtTLInfo.ptTL.Y = thisLimb.recDest.Top;
if (thisLimb.recDest.Top + thisLimb.recDest.Height > ptBR.Y)
ptBR.Y = thisLimb.recDest.Top + thisLimb.recDest.Height;
}
if (ptBR.X == cBmpPtTLInfo.ptTL.X)
ptBR.X += 1;
if (ptBR.Y == cBmpPtTLInfo.ptTL.Y)
ptBR.Y += 1;
cBmpPtTLInfo.ptTL.X *= -1;
cBmpPtTLInfo.ptTL.Y *= -1;
// draw onto output bitmap
cBmpPtTLInfo.bmp = new Bitmap(ptBR.X + cBmpPtTLInfo.ptTL.X, ptBR.Y + cBmpPtTLInfo.ptTL.Y);
using (Graphics g = Graphics.FromImage(cBmpPtTLInfo.bmp))
{
if (brBack != null)
g.FillRectangle(brBack, new Rectangle(0, 0, cBmpPtTLInfo.bmp.Width, cBmpPtTLInfo.bmp.Height));
if (limDrawSequence != null)
{
cBmpPtTLInfo.limbPositions = new classConfigStepLimbPosition[limDrawSequence.Length];
cBmpPtTLInfo.hingePositions = new classConfigStepHingePosition[limDrawSequence.Length];
for (int intLimbCounter = 0; intLimbCounter < limDrawSequence.Length; intLimbCounter++)
{
Sprite.classSpriteLimb thisLimb = limDrawSequence[intLimbCounter];
if (thisLimb != null)
{
thisLimb.myCurrentImage.MakeTransparent();
if (thisLimb.MasterHinge != null)
thisLimb.MasterHinge.Loc = new Point(thisLimb.MasterHinge.Loc.X + cBmpPtTLInfo.ptTL.X, thisLimb.MasterHinge.Loc.Y + cBmpPtTLInfo.ptTL.Y);
int intDrawSequenceIndex = Configurations[intCurrent_Configuration].getLimbDrawSequenceIndex(thisLimb.Name.ToString());
cBmpPtTLInfo.limbPositions[limDrawSequence[intDrawSequenceIndex].intMyLimbID] = new classConfigStepLimbPosition();
if (intDrawSequenceIndex >= 0)
{
cBmpPtTLInfo.limbPositions[limDrawSequence[intDrawSequenceIndex].intMyLimbID] = new classConfigStepLimbPosition();
cBmpPtTLInfo.limbPositions[limDrawSequence[intDrawSequenceIndex].intMyLimbID].pt = thisLimb.Loc;
cBmpPtTLInfo.limbPositions[limDrawSequence[intDrawSequenceIndex].intMyLimbID].dblAngle = thisLimb.Angle;
}
g.DrawImage(new Bitmap(thisLimb.myCurrentImage, thisLimb.recDest.Size), new Point(cBmpPtTLInfo.ptTL.X + thisLimb.recDest.Location.X, cBmpPtTLInfo.ptTL.Y + thisLimb.recDest.Location.Y));
}
}
for (int intHingeCounter = 0; intHingeCounter < cBmpPtTLInfo.hingePositions.Length; intHingeCounter++)
{
cBmpPtTLInfo.hingePositions[intHingeCounter] = new classConfigStepHingePosition();
cBmpPtTLInfo.hingePositions[intHingeCounter].pt.X = hinges[intHingeCounter].Loc.X - cBmpPtTLInfo.ptTL.X;
cBmpPtTLInfo.hingePositions[intHingeCounter].pt.Y = hinges[intHingeCounter].Loc.Y - cBmpPtTLInfo.ptTL.Y;
hinges[intHingeCounter].Loc = cBmpPtTLInfo.hingePositions[intHingeCounter].pt;
}
}
}
// calculate radial positions of each limb & hinge for this unmirrored, unrotated, standard-sized config/step image
for (int intLimbCounter = 0; intLimbCounter < cBmpPtTLInfo.limbPositions.Length; intLimbCounter++)
{
cBmpPtTLInfo.limbPositions[intLimbCounter].cRad = new classMath.classRadialCoor(classMath.arcTan(cBmpPtTLInfo.limbPositions[intLimbCounter].pt.X, cBmpPtTLInfo.limbPositions[intLimbCounter].pt.Y),
classMath.getRootOfSquares(cBmpPtTLInfo.limbPositions[intLimbCounter].pt.X, cBmpPtTLInfo.limbPositions[intLimbCounter].pt.Y));
cBmpPtTLInfo.hingePositions[intLimbCounter].cRad = new classMath.classRadialCoor(classMath.arcTan(cBmpPtTLInfo.hingePositions[intLimbCounter].pt.X, cBmpPtTLInfo.hingePositions[intLimbCounter].pt.Y),
classMath.getRootOfSquares(cBmpPtTLInfo.hingePositions[intLimbCounter].pt.X, cBmpPtTLInfo.hingePositions[intLimbCounter].pt.Y));
}
//if (cFileStream.bolIAmCached)
{
classCacheTreeNodeKeys cCacheKeyDefault = new classCacheTreeNodeKeys(cCacheKey.strFilename,
cCacheKey.ConfigIndex,
cCacheKey.Step,
0,
1.0,
cCacheKey.Mirror);
classSpriteFileStream.Cache(ref cBmpPtTLInfo,
cCacheKeyDefault);
}
return cBmpPtTLInfo;
}
else
{
// load original sized unrotated unmirrored image default sized image
cBmpPtTLInfo = getImageOnBitmap(intConfigurationIndex, intStep, 0, 1.0, enuMirror.none, false).Copy();
setBmpInfoImage(ref cBmpPtTLInfo, ref Configurations[intConfigurationIndex].LimbDrawSequence, Angle, DisplaySize, enuMirror.none);
if (cFileStream.bolIAmCached)
{
cCacheKey = new classCacheTreeNodeKeys(cFileStream.strFilename, intConfigurationIndex, intStep, Angle, DisplaySize, enuMirror.none);
classSpriteFileStream.Cache(ref cBmpPtTLInfo,
cCacheKey);
}
return cBmpPtTLInfo;
}
default: // mirrored image
if (MasterLimb.Angle == 0)
{
// load original image default size, angle no-mirror
cBmpPtTLInfo = getImageOnBitmap(intConfigurationIndex, intStep, 0, 1.0, enuMirror.none, false).Copy();
// flip all limb positions, limb angles & hinge positions according to the desired mirror pos/angle
switch (mirror)
{
case enuMirror.horizontal:
// get an image for the original unmirrored configuration
// scan through each limb and adjust positions and angles for each limb to reflect Mirror=horizontal
for (int intLimbCounter = 0; intLimbCounter < cBmpPtTLInfo.limbPositions.Length; intLimbCounter++)
{
cBmpPtTLInfo.limbPositions[intLimbCounter].pt = new Point(-cBmpPtTLInfo.limbPositions[intLimbCounter].pt.X,
cBmpPtTLInfo.limbPositions[intLimbCounter].pt.Y);
cBmpPtTLInfo.limbPositions[intLimbCounter].dblAngle =classMath.getMirrorAngle( cBmpPtTLInfo.limbPositions[intLimbCounter].dblAngle, enuMirror.horizontal);
cBmpPtTLInfo.hingePositions[intLimbCounter].pt = new Point(-cBmpPtTLInfo.hingePositions[intLimbCounter].pt.X,
cBmpPtTLInfo.hingePositions[intLimbCounter].pt.Y);
}
break;
case enuMirror.vertical:
// get an image for the original unmirrored configuration
// scan through each limb and adjust positions and angles for each limb to reflect Mirror=eMirror
for (int intLimbCounter = 0; intLimbCounter < cBmpPtTLInfo.limbPositions.Length; intLimbCounter++)
{
cBmpPtTLInfo.limbPositions[intLimbCounter].pt = new Point(cBmpPtTLInfo.limbPositions[intLimbCounter].pt.X,
-cBmpPtTLInfo.limbPositions[intLimbCounter].pt.Y);
cBmpPtTLInfo.limbPositions[intLimbCounter].dblAngle = classMath.getMirrorAngle( cBmpPtTLInfo.limbPositions[intLimbCounter].dblAngle, enuMirror.vertical);
cBmpPtTLInfo.hingePositions[intLimbCounter].pt = new Point(cBmpPtTLInfo.hingePositions[intLimbCounter].pt.X,
-cBmpPtTLInfo.hingePositions[intLimbCounter].pt.Y);
}
break;
default:
case enuMirror.VerticalAndHorizontal:
// get an image for the original unmirrored configuration
// scan through each limb and adjust positions and angles for each limb to reflect Mirror=eMirror
for (int intLimbCounter = 0; intLimbCounter < cBmpPtTLInfo.limbPositions.Length; intLimbCounter++)
{
cBmpPtTLInfo.limbPositions[intLimbCounter].pt = new Point(-cBmpPtTLInfo.limbPositions[intLimbCounter].pt.X,
-cBmpPtTLInfo.limbPositions[intLimbCounter].pt.Y);
cBmpPtTLInfo.limbPositions[intLimbCounter].dblAngle = classMath.cleanAngle(cBmpPtTLInfo.limbPositions[intLimbCounter].dblAngle + Math.PI);
cBmpPtTLInfo.hingePositions[intLimbCounter].pt = new Point(-cBmpPtTLInfo.hingePositions[intLimbCounter].pt.X,
-cBmpPtTLInfo.hingePositions[intLimbCounter].pt.Y);
}
break;
}
// calculate radial positions of each limb & hinge, and limb angle for mirror of original unmirrored/unrotated bmp
for (int intLimbCounter = 0; intLimbCounter < cBmpPtTLInfo.limbPositions.Length; intLimbCounter++)
{
cBmpPtTLInfo.limbPositions[intLimbCounter].cRad = new classMath.classRadialCoor(classMath.arcTan(cBmpPtTLInfo.limbPositions[intLimbCounter].pt.X, cBmpPtTLInfo.limbPositions[intLimbCounter].pt.Y),
classMath.getRootOfSquares(cBmpPtTLInfo.limbPositions[intLimbCounter].pt.X, cBmpPtTLInfo.limbPositions[intLimbCounter].pt.Y));
cBmpPtTLInfo.hingePositions[intLimbCounter].cRad = new classMath.classRadialCoor(classMath.arcTan(cBmpPtTLInfo.hingePositions[intLimbCounter].pt.X, cBmpPtTLInfo.hingePositions[intLimbCounter].pt.Y),
classMath.getRootOfSquares(cBmpPtTLInfo.hingePositions[intLimbCounter].pt.X, cBmpPtTLInfo.hingePositions[intLimbCounter].pt.Y));
}
// cache the image
setBmpInfoImage(ref cBmpPtTLInfo, ref Configurations[intConfigurationIndex].LimbDrawSequence, 0, 1.0, mirror);
//if (cFileStream.bolIAmCached)
classSpriteFileStream.Cache(ref cBmpPtTLInfo, new classCacheTreeNodeKeys(cCacheKey.strFilename, cCacheKey.ConfigIndex, cCacheKey.Step, 0, 1.0, mirror));
// resize, cache resized image and return
if (DisplaySize != 1.0)
{
cBmpPtTLInfo = cBmpPtTLInfo.Copy();
setBmpInfoImage(ref cBmpPtTLInfo, ref Configurations[intConfigurationIndex].LimbDrawSequence, 0,DisplaySize, mirror);
if (cFileStream.bolIAmCached)
{
cCacheKey = new classCacheTreeNodeKeys(cFileStream.strFilename, intConfigurationIndex, intStep, 0, DisplaySize, mirror);
classSpriteFileStream.Cache(ref cBmpPtTLInfo, cCacheKey);
}
}
return cBmpPtTLInfo;
}
else
{ // get unrotated mirror image
cBmpPtTLInfo = getImageOnBitmap(intCurrent_Configuration, intCurrent_ConfigurationStep, 0, 1.0, mirror, false).Copy();
setBmpInfoImage(ref cBmpPtTLInfo, ref Configurations[intConfigurationIndex].LimbDrawSequence, Angle, DisplaySize, mirror);
if (cFileStream.bolIAmCached)
{
cCacheKey = new classCacheTreeNodeKeys(cFileStream.strFilename, intConfigurationIndex, intStep, Angle, dblDisplaySize, mirror);
classSpriteFileStream.Cache(ref cBmpPtTLInfo,
cCacheKey);
}
return cBmpPtTLInfo;
}
}
}
bool bolMakeSpriteTransparent = true;
public bool MakeSpriteTransparent
{
get { return bolMakeSpriteTransparent; }
set { bolMakeSpriteTransparent = value; }
}
/// <summary>
/// this function receives a limb which has already been angled and positioned
/// this limb then places all of its slaves limbs by setting their respective positions & angles
/// then calls itself once for each slave that recurses with each of these limbs
/// </summary>
/// <param name="thisLimb">reference to this recursion's master-limb which will recurse for each of its slave limbs</param>
/// <param name="dblLocalSizeFactor">factor by which original image is multiplied when calculating positions of slave limbs</param>
public void putImageOntoScreen_recursion(ref classSpriteLimb thisLimb,
double dblLocalSizeFactor)
{
thisLimb.setDir();
thisLimb.myCurrentImage = thisLimb.getLimbImage();
thisLimb.recDest = new Rectangle(new Point(thisLimb.Loc.X - (int)(thisLimb.myCurrentImage.Width * dblLocalSizeFactor / 2),
thisLimb.Loc.Y - (int)(thisLimb.myCurrentImage.Height * dblLocalSizeFactor / 2)),
new Size((int)((double)thisLimb.myCurrentImage.Size.Width * dblLocalSizeFactor),
(int)((double)thisLimb.myCurrentImage.Size.Height * dblLocalSizeFactor)));
if (thisLimb.recDest.Width < 1)
thisLimb.recDest.Width = 1;
if (thisLimb.recDest.Height < 1)
thisLimb.recDest.Height = 1;
classConfigurationStepHinge[] udrHingeDetails = Configurations[intCurrent_Configuration].steps[intCurrent_ConfigurationStep].hingeDetails;
if (thisLimb.mySlaveLimbs != null)
for (int intSlaveCounter = 0; intSlaveCounter < thisLimb.mySlaveLimbs.Length; intSlaveCounter++)
{
classSpriteHinge cMasterHinge = udrHingeDetails[thisLimb.mySlaveLimbs[intSlaveCounter].intMyLimbID].hinge;
classMath.classRadialCoor cRadMH_MasterRad = udrHingeDetails[thisLimb.mySlaveLimbs[intSlaveCounter].intMyLimbID].RadCoor_Master;
classMath.classRadialCoor cRadMH_SlaveRad= udrHingeDetails[thisLimb.mySlaveLimbs[intSlaveCounter].intMyLimbID].RadCoor_Slave;
double dblNewAngle = classMath.cleanAngle(thisLimb.Angle
+ cMasterHinge.Angle);
thisLimb.mySlaveLimbs[intSlaveCounter].Angle = dblNewAngle;
double dblAngleOfHingeAwayFromMaster =
classMath.cleanAngle((cRadMH_MasterRad.radius > 1
? cRadMH_MasterRad.angle
: 0)
+ thisLimb.Angle);
cMasterHinge.Loc = new Point(thisLimb.Loc.X + (int)(cRadMH_MasterRad.radius * dblLocalSizeFactor * Math.Cos(dblAngleOfHingeAwayFromMaster )),
thisLimb.Loc.Y + (int)(cRadMH_MasterRad.radius * dblLocalSizeFactor * Math.Sin(dblAngleOfHingeAwayFromMaster)));
double dblAngleAwayFromHingeLoc = classMath.cleanAngle((cRadMH_SlaveRad.radius > 1
? cRadMH_SlaveRad.angle + Math.PI
: 0)
+ thisLimb.mySlaveLimbs[intSlaveCounter].Angle);
thisLimb.mySlaveLimbs[intSlaveCounter].Loc = new Point(cMasterHinge.Loc.X + (int)(cRadMH_SlaveRad.radius * dblLocalSizeFactor * Math.Cos(dblAngleAwayFromHingeLoc)),
cMasterHinge.Loc.Y + (int)(cRadMH_SlaveRad.radius * dblLocalSizeFactor * Math.Sin(dblAngleAwayFromHingeLoc)));
putImageOntoScreen_recursion(ref thisLimb.mySlaveLimbs[intSlaveCounter],
dblLocalSizeFactor);
}
}
/// <summary>
/// returns a pointer to the limb identified by name
/// </summary>
/// <param name="LimbName">name of the limb to be searched</param>
/// <returns>returns a pointer to an object of type classSpriteLimb</returns>
public Sprite.classSpriteLimb getLimbByName(string LimbName)
{
LimbName = LimbName.Trim().ToUpper();
for (int intLimbCounter =0; intLimbCounter < limbs.Length; intLimbCounter++)
{
if (limbs[intLimbCounter].Name.Trim().ToUpper() == LimbName)
return limbs[intLimbCounter];
}
if (MasterLimb.Name.Trim().CompareTo(LimbName) == 0)
return MasterLimb;
return null;
}
/// <summary>
/// returns a pointer to the hinge identified by name
/// </summary>
/// <param name="HingeName">name of hinge to be searched</param>
/// <returns>returns a pointer to an object of type classSpriteHinge </returns>
public Sprite.classSpriteHinge getHingeByName(string HingeName)
{
HingeName = HingeName.ToUpper();
for (int intHingeCounter = 0; intHingeCounter < hinges.Length; intHingeCounter++)
if (hinges[intHingeCounter].name.ToUpper().CompareTo(HingeName) == 0)
return hinges[intHingeCounter];
return null;
}
public Sprite.classConfiguration getConfigurationByName(string ConfigurationName)
{
ConfigurationName = ConfigurationName.Trim().ToUpper();
for (int intConfigurationCounter = 0; intConfigurationCounter < Configurations.Length; intConfigurationCounter++)
if (Configurations[intConfigurationCounter].name.Trim().ToUpper().CompareTo(ConfigurationName) == 0)
return Configurations[intConfigurationCounter];
return null;
}
public int getIndexOfConfigurationByName(string ConfigurationName)
{
if (Configurations == null)
return -1;
ConfigurationName = ConfigurationName.Trim().ToUpper();
for (int intConfigurationCounter = 0; intConfigurationCounter < Configurations.Length; intConfigurationCounter++)
if (Configurations[intConfigurationCounter].name.Trim().ToUpper().CompareTo(ConfigurationName) == 0)
return intConfigurationCounter;
return -1;
}
public int getIndexOfHingeByName(string hingeName)
{
hingeName = hingeName.Trim().ToUpper();
for (int intHingeCounter = 0; intHingeCounter < hinges.Length; intHingeCounter++)
if (hinges[intHingeCounter].name.Trim().ToUpper().CompareTo(hingeName) == 0)
return intHingeCounter;
return -1;
}
public int getIndexOfLimbByName(string limbName)
{
limbName = limbName.Trim().ToUpper();
for (int intlimbCounter = 0; intlimbCounter < hinges.Length; intlimbCounter++)
if (hinges[intlimbCounter].Limb_Slave.Name.Trim().ToUpper().CompareTo(limbName) == 0)
return intlimbCounter;
return -1;
}
}
public class classPixilateColorFind
{
public Color clr;
public int numFound;
static classPixilateColorFind[] cPreviouslyCreated = new classPixilateColorFind[0];
static int intCurrentUse;
public static classPixilateColorFind getPixilateColorFind()
{
if (cPreviouslyCreated.Length > 0 && intCurrentUse < cPreviouslyCreated.Length)
{
return cPreviouslyCreated[intCurrentUse++];
}
else
{
Array.Resize<classPixilateColorFind>(ref cPreviouslyCreated, cPreviouslyCreated.Length + 1);
cPreviouslyCreated[cPreviouslyCreated.Length - 1] = new classPixilateColorFind();
return cPreviouslyCreated[intCurrentUse++];
}
}
public static void clear()
{
intCurrentUse = 0;
}
}
public class classSpriteComposite
{
public classSpriteCompositeElement[] cSpriteCompositeElementArray = new classSpriteCompositeElement[0];
public classSpriteCompositeElement cMaster;
public int[] intDrawSequence = new int[0];
public Point ptTL;
public classSpriteComposite(ref classSprite cSpriteMaster)
{
classSpriteComposite cMyReference = this;
cMaster = new classSpriteCompositeElement(ref cMyReference);
cMaster.cSprite = cSpriteMaster;
intDrawSequence = new int[1];
intDrawSequence[0] = 0;
}
public void animate()
{
for (int intSpriteCounter = 0; intSpriteCounter < cSpriteCompositeElementArray.Length; intSpriteCounter++)
{
classSpriteCompositeElement cThisCompEle = cSpriteCompositeElementArray[intSpriteCounter];
classSprite cSpr = cThisCompEle.cSprite;
cThisCompEle.intConfigurationStep = (cThisCompEle.intConfigurationStep + 1) % cSpr.Configurations[cThisCompEle.intConfigurationIndex].steps.Length;
}
}
public Bitmap drawComposite(double dblAngle, double dblSize, enuMirror eMirror)
{
cMaster.Mirror = eMirror;
cMaster.Angle = dblAngle;
for (int intCECounter = 0; intCECounter < cSpriteCompositeElementArray.Length; intCECounter++)
{
classSpriteCompositeElement cThisCE = cSpriteCompositeElementArray[intCECounter];
cThisCE.cBmp = cThisCE.cSprite.getImageOnBitmap(cThisCE.intConfigurationIndex, cThisCE.intConfigurationStep,cThisCE.Angle,dblSize, cThisCE.Mirror, false);
}
ptTL =new Point( -cSpriteCompositeElementArray[0].cBmp.ptTL.X, -cSpriteCompositeElementArray[0].cBmp.ptTL.Y);
Point ptBR = new Point(ptTL.X + cSpriteCompositeElementArray[0].cBmp.bmp.Width , ptTL.Y + cSpriteCompositeElementArray[0].cBmp.bmp.Height);
cMaster.ptTL = new Point(0, 0);
cMaster.PositionSlaves(ref ptTL, ref ptBR);
cMaster.ptTL = new Point(0,0);
Size sz = new Size(ptBR.X - ptTL.X, ptBR.Y - ptTL.Y);
Bitmap bmpRetVal = new Bitmap(sz.Width, sz.Height);
ptTL.X *= -1; ptTL.Y *= -1;
using (Graphics g = Graphics.FromImage(bmpRetVal))
{
g.FillRectangle(classPensAndBrushes.brWhite, new Rectangle(0,0, bmpRetVal.Width, bmpRetVal.Height));
for (int intIndexCounter = 0; intIndexCounter < intDrawSequence.Length; intIndexCounter++)
{
classSpriteCompositeElement cThisCE = cSpriteCompositeElementArray[intDrawSequence[intIndexCounter]];
Rectangle recSrc = new Rectangle(0, 0, cThisCE.cBmp.bmp.Width , cThisCE.cBmp.bmp.Height);
Rectangle recDest = new Rectangle(ptTL.X + cThisCE.ptTL.X - cThisCE.cBmp.ptTL.X,
ptTL.Y + cThisCE.ptTL.Y - cThisCE.cBmp.ptTL.Y,
cThisCE.cBmp.bmp.Width,
cThisCE.cBmp.bmp.Height);
g.DrawImage(cThisCE.cBmp.bmp, recDest, recSrc, GraphicsUnit.Pixel);
}
}
bmpRetVal.MakeTransparent();
return bmpRetVal;
}
}
public class classSpriteCompositeElement
{
public classSprite cSprite;
public classSpriteComposite cComposite;
public classSpriteCompositeElement cMaster;
int intIndexMasterLimbLink;
public int IndexMasterLimbLink
{
get { return intIndexMasterLimbLink; }
set
{
if (value >= 0 && value < cMaster.cSprite.limbs.Length)
{
intIndexMasterLimbLink = value;
cSprite.limStationary = cMaster.cSprite.limbs[intIndexMasterLimbLink];
}
}
}
public bool bolAngleTracksMaster = false;
double dblAngle = 0;
public double Angle
{
get { return dblAngle; }
set
{
dblAngle = value;
for (int intMySlaves = 0; intMySlaves < cSlaves.Length; intMySlaves++)
if (cSlaves[intMySlaves].bolAngleTracksMaster)
cSlaves[intMySlaves].Angle = dblAngle;
}
}
public int intConfigurationIndex;
public int intConfigurationStep;
public double dblSizeRelativeToMaster = 1.0;
public classBmpAndPtTLInfo cBmp = new classBmpAndPtTLInfo();
public Point ptTL;
public bool bolMirrorFollowsMaster = true;
enuMirror eMirror = enuMirror.none;
public enuMirror Mirror
{
get { return eMirror; }
set
{
eMirror = value;
for (int intMySlaves = 0; intMySlaves < cSlaves.Length; intMySlaves++)
{
if (cSlaves[intMySlaves].bolMirrorFollowsMaster)
cSlaves[intMySlaves].Mirror = eMirror;
}
}
}
public classSpriteCompositeElement[] cSlaves = new classSpriteCompositeElement[0];
public int intMyIndex;
public classSpriteCompositeElement(ref classSpriteComposite cSpriteComposite)
{
cComposite = cSpriteComposite;
Array.Resize<classSpriteCompositeElement>(ref cComposite.cSpriteCompositeElementArray, cComposite.cSpriteCompositeElementArray.Length + 1);
cComposite.cSpriteCompositeElementArray[cComposite.cSpriteCompositeElementArray.Length - 1] = this;
intMyIndex = cComposite.cSpriteCompositeElementArray.Length - 1;
intMyDrawSequenceIndex = cComposite.intDrawSequence.Length;
Array.Resize<int>(ref cComposite.intDrawSequence, cComposite.intDrawSequence.Length + 1);
cComposite.intDrawSequence[cComposite.intDrawSequence.Length - 1] = intMyIndex;
}
int intMyDrawSequenceIndex = -1;
public int myDrawSequenceIndex
{
get { return intMyDrawSequenceIndex; }
set
{
if (value >= 0 && value < cComposite.intDrawSequence.Length && value != intMyDrawSequenceIndex)
{
if (value < intMyDrawSequenceIndex)
{
for (int intIndexCounter = intMyDrawSequenceIndex; intIndexCounter > value; intIndexCounter--)
cComposite.intDrawSequence[intIndexCounter - 1] = cComposite.intDrawSequence[intIndexCounter];
}
else
{
for (int intIndexCounter = intMyDrawSequenceIndex; intIndexCounter < value; intIndexCounter++)
cComposite.intDrawSequence[intIndexCounter + 1] = cComposite.intDrawSequence[intIndexCounter];
}
}
intMyDrawSequenceIndex = value;
cComposite.intDrawSequence[intMyDrawSequenceIndex] = intMyIndex;
}
}
public void addSlave(ref classSprite cSprite_NewSlave, int intIndexMasterLimbLink, double dblDrawSizeRelativeToMaster)
{
Array.Resize<classSpriteCompositeElement>(ref cSlaves, cSlaves.Length + 1);
classSpriteCompositeElement cNewSlave = new classSpriteCompositeElement(ref cComposite);
cNewSlave.cComposite = cComposite;
cNewSlave.cSprite = cSprite_NewSlave;
cNewSlave.cMaster = this;
cNewSlave.dblSizeRelativeToMaster = dblDrawSizeRelativeToMaster;
cNewSlave.intIndexMasterLimbLink = intIndexMasterLimbLink;
cSlaves[cSlaves.Length - 1] = cNewSlave;
rebuildIndex();
}
public void removeSlave(ref classSpriteCompositeElement cSprite_Remove)
{
for (int intSlaveCounter = 0; intSlaveCounter < cSlaves.Length; intSlaveCounter++)
{
if (cSlaves[intSlaveCounter] == cSprite_Remove)
{
for (int intSlavesSlavesCounter = cSprite_Remove.cSlaves.Length; intSlavesSlavesCounter >= 0; intSlavesSlavesCounter--)
cSprite_Remove.removeSlave(ref cSprite_Remove.cSlaves[intSlavesSlavesCounter]);
cSlaves[intSlaveCounter] = cSlaves[cSlaves.Length - 1];
Array.Resize<classSpriteCompositeElement>(ref cSlaves, cSlaves.Length - 1);
break;
}
}
for (int intSpriteCounter = 0; intSpriteCounter < cComposite.cSpriteCompositeElementArray.Length; intSpriteCounter++)
{
if (cComposite.cSpriteCompositeElementArray[intSpriteCounter] == cSprite_Remove)
{
cComposite.cSpriteCompositeElementArray[intSpriteCounter] = cComposite.cSpriteCompositeElementArray[cComposite.cSpriteCompositeElementArray.Length - 1];
Array.Resize<classSpriteCompositeElement>(ref cComposite.cSpriteCompositeElementArray, cComposite.cSpriteCompositeElementArray.Length - 1);
break;
}
}
rebuildIndex();
}
void rebuildIndex()
{
for (int intSpriteCounter = 0; intSpriteCounter < cComposite.cSpriteCompositeElementArray.Length; intSpriteCounter++ )
{
cComposite.cSpriteCompositeElementArray[intSpriteCounter].intMyIndex = intSpriteCounter;
}
}
public void PositionSlaves(ref Point ptFrame_TL, ref Point ptFrame_BR)
{
for (int intSlaveCounter = 0; intSlaveCounter < cSlaves.Length; intSlaveCounter++)
{
classSpriteCompositeElement cThisSlave = cSlaves[intSlaveCounter];
cThisSlave.ptTL = new Point(cBmp.limbPositions[cThisSlave.intIndexMasterLimbLink].pt.X + ptTL.X,
cBmp.limbPositions[cThisSlave.intIndexMasterLimbLink].pt.Y + ptTL.Y);
cThisSlave.PositionSlaves(ref ptFrame_TL, ref ptFrame_BR);
}
if (ptFrame_TL.X > ptTL.X - cBmp.ptTL.X)
ptFrame_TL.X = ptTL.X - cBmp.ptTL.X;
if (ptFrame_TL.Y > ptTL.Y - cBmp.ptTL.Y)
ptFrame_TL.Y = ptTL.Y - cBmp.ptTL.Y;
if (ptFrame_BR.X < ptTL.X - cBmp.ptTL.X + cBmp.bmp.Width)
ptFrame_BR.X = ptTL.X - cBmp.ptTL.X + cBmp.bmp.Width;
if (ptFrame_BR.Y < ptTL.Y - cBmp.ptTL.Y + cBmp.bmp.Height)
ptFrame_BR.Y = ptTL.Y - cBmp.ptTL.Y + cBmp.bmp.Height;
}
/// <summary>
/// generates the recDest required to place this CE's cBmp onto the Sprite-composite's output image
/// </summary>
/// <returns></returns>
public Rectangle getDrawRectangle()
{
Rectangle recRetVal = new Rectangle();
return recRetVal;
}
}
}