Rev 1488 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 797 | chris | 1 | using System; |
| 2 | using System.Collections.Generic; |
||
| 3 | using System.Linq; |
||
| 4 | using System.Text; |
||
| 5 | using System.Threading.Tasks; |
||
| 1488 | chris | 6 | using System.Drawing; |
| 797 | chris | 7 | |
| 8 | using BauzoidNET.math; |
||
| 9 | using BauzoidNET.graphics.renderstates; |
||
| 10 | using BauzoidNET.graphics.texture; |
||
| 11 | using BauzoidNET.graphics.model; |
||
| 12 | |||
| 801 | chris | 13 | using Tao.OpenGl; |
| 14 | |||
| 797 | chris | 15 | namespace BauzoidNET.graphics.sprite |
| 16 | { |
||
| 17 | public class Sprite : GraphicsObject |
||
| 18 | { |
||
| 1304 | chris | 19 | public const int NUM_INDICES_PER_REGION = 6; |
| 20 | public const int NUM_ATTRIBUTES_PER_REGION = 4; |
||
| 21 | |||
| 797 | chris | 22 | protected Texture mTexture = null; |
| 1304 | chris | 23 | |
| 24 | private SpriteRegion[] mRegions = null; |
||
| 25 | |||
| 797 | chris | 26 | protected SimpleGeometry mMesh = null; |
| 1304 | chris | 27 | |
| 28 | protected String mTextureFilename = null; |
||
| 1488 | chris | 29 | protected Bitmap mTextureBitmap = null; |
| 1304 | chris | 30 | |
| 31 | protected String mRegionDefFilename = null; |
||
| 797 | chris | 32 | |
| 33 | /** Constructor. Does not load anything yet |
||
| 34 | */ |
||
| 35 | public Sprite(Graphics graphics, String filename) |
||
| 36 | : base(graphics) |
||
| 37 | { |
||
| 1304 | chris | 38 | mTextureFilename = filename; |
| 797 | chris | 39 | } |
| 40 | |||
| 1488 | chris | 41 | public Sprite(Graphics graphics, Bitmap bm) |
| 42 | : base(graphics) |
||
| 43 | { |
||
| 44 | mTextureBitmap = bm; |
||
| 45 | } |
||
| 46 | |||
| 1304 | chris | 47 | public Sprite(Graphics graphics, String textureFile, String atlasFile) |
| 48 | : this(graphics, textureFile) |
||
| 49 | { |
||
| 50 | mRegionDefFilename = atlasFile; |
||
| 51 | } |
||
| 1488 | chris | 52 | |
| 53 | public Sprite(Graphics graphics, Bitmap bm, String atlasFile) |
||
| 54 | : this(graphics, bm) |
||
| 55 | { |
||
| 56 | mRegionDefFilename = atlasFile; |
||
| 57 | } |
||
| 797 | chris | 58 | |
| 59 | public void init() |
||
| 60 | { |
||
| 1488 | chris | 61 | if ((mTextureFilename == null) && (mTextureBitmap == null)) |
| 1304 | chris | 62 | return; |
| 63 | |||
| 64 | // load texture synchronously |
||
| 1488 | chris | 65 | if (mTextureFilename != null) |
| 66 | mTexture = new Texture(getGraphics(), mTextureFilename); |
||
| 67 | else if (mTextureBitmap != null) |
||
| 68 | mTexture = new Texture(getGraphics(), mTextureBitmap); |
||
| 1304 | chris | 69 | |
| 70 | if (mRegionDefFilename != null) |
||
| 71 | { |
||
| 72 | List<SpriteUtil.SpriteRegionInfo> atlas = SpriteUtil.readSpriteRegionInfo(mRegionDefFilename); |
||
| 73 | |||
| 74 | SpriteRegion[] regions = new SpriteRegion[atlas.Count]; |
||
| 75 | for (int i = 0; i < atlas.Count; i++) |
||
| 76 | { |
||
| 77 | regions[i] = new SpriteRegion(this, i, atlas[i].x, atlas[i].y, atlas[i].w, atlas[i].h, true); |
||
| 78 | } |
||
| 79 | |||
| 80 | setRegions(regions); |
||
| 81 | } |
||
| 82 | else |
||
| 83 | { |
||
| 84 | // create default geometry for entire sprite (make 1 region) |
||
| 85 | SpriteRegion[] regions = new SpriteRegion[1]; |
||
| 86 | regions[0] = new SpriteRegion(this, 0, 0, 0, getTextureWidth(), getTextureHeight(), true); |
||
| 87 | |||
| 88 | setRegions(regions); |
||
| 89 | } |
||
| 797 | chris | 90 | } |
| 91 | |||
| 1304 | chris | 92 | public void dispose() |
| 93 | { |
||
| 94 | if (mRegions != null) |
||
| 95 | mRegions = null; |
||
| 805 | chris | 96 | |
| 1304 | chris | 97 | if (mTexture != null) |
| 98 | { |
||
| 99 | mTexture.dispose(); |
||
| 100 | mTexture = null; |
||
| 101 | } |
||
| 102 | } |
||
| 805 | chris | 103 | |
| 1304 | chris | 104 | public void setRegions(SpriteRegion[] regions) |
| 105 | { |
||
| 106 | if (mMesh != null) |
||
| 107 | { |
||
| 108 | mMesh.dispose(); |
||
| 109 | mMesh = null; |
||
| 110 | } |
||
| 805 | chris | 111 | |
| 1304 | chris | 112 | mRegions = regions; |
| 113 | mMesh = createGeometry(); |
||
| 114 | } |
||
| 805 | chris | 115 | |
| 1304 | chris | 116 | public SimpleGeometry createGeometry() |
| 797 | chris | 117 | { |
| 1304 | chris | 118 | float[] vertices = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.POSITION_COORD_PER_ELEMENT * mRegions.Length]; |
| 119 | float[] texCoords = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.TEXCOORD_COORD_PER_ELEMENT * mRegions.Length]; |
||
| 120 | float[] colors = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.COLOR_COORD_PER_ELEMENT * mRegions.Length]; |
||
| 797 | chris | 121 | |
| 1304 | chris | 122 | // two triangles per region |
| 123 | short[] indices = new short[NUM_INDICES_PER_REGION * mRegions.Length]; |
||
| 797 | chris | 124 | |
| 1304 | chris | 125 | for (int i = 0; i < mRegions.Length; i++) |
| 797 | chris | 126 | { |
| 1304 | chris | 127 | SpriteRegion r = getRegion(i); |
| 797 | chris | 128 | |
| 1304 | chris | 129 | float[] v = |
| 797 | chris | 130 | { |
| 1304 | chris | 131 | -1.0f, -1.0f, 0.0f, |
| 132 | 1.0f, -1.0f, 0.0f, |
||
| 133 | 1.0f, 1.0f, 0.0f, |
||
| 134 | -1.0f, 1.0f, 0.0f |
||
| 135 | }; |
||
| 136 | |||
| 137 | float[] t = |
||
| 138 | { |
||
| 139 | r.left, r.top, |
||
| 140 | r.right, r.top, |
||
| 141 | r.right, r.bottom, |
||
| 142 | r.left, r.bottom |
||
| 143 | }; |
||
| 144 | |||
| 145 | float[] c = |
||
| 146 | { |
||
| 147 | 1, 1, 1, 1, |
||
| 148 | 1, 1, 1, 1, |
||
| 149 | 1, 1, 1, 1, |
||
| 150 | 1, 1, 1, 1 |
||
| 151 | }; |
||
| 152 | |||
| 153 | Array.Copy(v, 0, vertices, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.POSITION_COORD_PER_ELEMENT * i, v.Length); |
||
| 154 | Array.Copy(t, 0, texCoords, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.TEXCOORD_COORD_PER_ELEMENT * i, t.Length); |
||
| 155 | Array.Copy(c, 0, colors, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.COLOR_COORD_PER_ELEMENT * i, c.Length); |
||
| 803 | chris | 156 | |
| 1304 | chris | 157 | int n = i*NUM_INDICES_PER_REGION; |
| 158 | short baseIndex = (short)(i * NUM_ATTRIBUTES_PER_REGION); |
||
| 159 | indices[n++] = baseIndex; indices[n++] = (short)(baseIndex + 1); indices[n++] = (short)(baseIndex + 2); |
||
| 160 | indices[n++] = baseIndex; indices[n++] = (short)(baseIndex + 2); indices[n++] = (short)(baseIndex + 3); |
||
| 161 | } |
||
| 801 | chris | 162 | |
| 1304 | chris | 163 | SimpleGeometry mesh = new SimpleGeometry(getGraphics(), Geometry.PrimitiveType.TRIANGLES); |
| 164 | mesh.setPositions(vertices); |
||
| 165 | mesh.setTexCoords(texCoords); |
||
| 166 | mesh.setColors(colors); |
||
| 167 | mesh.setIndices(indices); |
||
| 168 | |||
| 169 | return mesh; |
||
| 170 | } |
||
| 801 | chris | 171 | |
| 1304 | chris | 172 | /** Create a single SpriteInstance for a single region. */ |
| 173 | public SpriteInstance createSpriteInstance(int regionIndex) |
||
| 174 | { |
||
| 175 | return new SpriteInstance(getRegion(regionIndex)); |
||
| 176 | } |
||
| 801 | chris | 177 | |
| 1304 | chris | 178 | /** Create a multiple SpriteInstances, each for a single region. */ |
| 179 | public void createSpriteInstances(SpriteInstance[] instances) |
||
| 180 | { |
||
| 181 | if (instances.Length < mRegions.Length) |
||
| 182 | return; |
||
| 801 | chris | 183 | |
| 1304 | chris | 184 | for (int i = 0; i < instances.Length; i++) |
| 185 | { |
||
| 186 | instances[i] = createSpriteInstance(i); |
||
| 187 | } |
||
| 188 | } |
||
| 801 | chris | 189 | |
| 1304 | chris | 190 | /** Create a multiple SpriteInstances, each for a single region. */ |
| 191 | public SpriteInstance[] createSpriteInstances() |
||
| 192 | { |
||
| 193 | SpriteInstance[] frames = new SpriteInstance[mRegions.Length]; |
||
| 194 | createSpriteInstances(frames); |
||
| 195 | return frames; |
||
| 196 | } |
||
| 801 | chris | 197 | |
| 1304 | chris | 198 | /** Create a single SpriteInstance for all regions. */ |
| 199 | public SpriteInstance createSpriteInstanceForAll() |
||
| 200 | { |
||
| 201 | SpriteInstance instance = new SpriteInstance(mRegions); |
||
| 202 | return instance; |
||
| 203 | } |
||
| 801 | chris | 204 | |
| 1304 | chris | 205 | /** Peforms the actual render without any model matrix handling. */ |
| 1499 | chris | 206 | public void performRender(int region, float alpha, Vector4 color, Vector4 fogColor) |
| 1304 | chris | 207 | { |
| 208 | RenderStates rs = getRenderStates(); |
||
| 209 | SpriteShader shader = getGraphics().getSpriteShader(); |
||
| 797 | chris | 210 | |
| 1304 | chris | 211 | // draw sprite |
| 1499 | chris | 212 | shader.activate(getTexture(), alpha, color, fogColor); |
| 1304 | chris | 213 | { |
| 214 | rs.blending.setEnabled(true); |
||
| 215 | rs.culling.setEnabled(false); |
||
| 216 | rs.activate(); |
||
| 217 | rs.blending.activate(true); |
||
| 218 | { |
||
| 219 | mMesh.render(getMeshStartIndex(region), NUM_INDICES_PER_REGION); |
||
| 220 | } |
||
| 221 | rs.deactivate(); |
||
| 222 | } |
||
| 223 | shader.deactivate(); |
||
| 224 | } |
||
| 225 | |||
| 797 | chris | 226 | /** Get the sprite texture's total width. */ |
| 227 | public int getTextureWidth() |
||
| 228 | { |
||
| 229 | if (mTexture == null) |
||
| 230 | return 0; |
||
| 231 | return mTexture.getWidth(); |
||
| 232 | } |
||
| 233 | |||
| 234 | /** Get the sprite texture's total height. */ |
||
| 235 | public int getTextureHeight() |
||
| 236 | { |
||
| 237 | if (mTexture == null) |
||
| 238 | return 0; |
||
| 239 | return mTexture.getHeight(); |
||
| 240 | } |
||
| 241 | |||
| 242 | /** Get a reference to the texture. */ |
||
| 243 | public Texture getTexture() |
||
| 244 | { |
||
| 245 | return mTexture; |
||
| 246 | } |
||
| 247 | |||
| 248 | /** Set a new texture, with the old one (if any) getting destroyed. */ |
||
| 249 | public void setTexture(Texture texture) |
||
| 250 | { |
||
| 251 | if (mTexture != null) |
||
| 252 | mTexture.dispose(); |
||
| 253 | |||
| 254 | mTexture = texture; |
||
| 255 | } |
||
| 256 | |||
| 1304 | chris | 257 | /** Get number of defined regions. */ |
| 258 | public int getRegionCount() |
||
| 797 | chris | 259 | { |
| 1304 | chris | 260 | if (mRegions == null) |
| 261 | return 0; |
||
| 262 | |||
| 263 | return mRegions.Length; |
||
| 797 | chris | 264 | } |
| 265 | |||
| 1304 | chris | 266 | /** Get region. */ |
| 267 | public SpriteRegion getRegion(int i) |
||
| 797 | chris | 268 | { |
| 1304 | chris | 269 | if (mRegions == null) |
| 270 | return null; |
||
| 271 | |||
| 272 | return mRegions[i]; |
||
| 797 | chris | 273 | } |
| 274 | |||
| 1304 | chris | 275 | /** Get regions array.*/ |
| 276 | public SpriteRegion[] getRegions() |
||
| 797 | chris | 277 | { |
| 1304 | chris | 278 | return mRegions; |
| 797 | chris | 279 | } |
| 280 | |||
| 1304 | chris | 281 | /** Get starting index for region mesh rendering. */ |
| 282 | private int getMeshStartIndex(int regionIndex) |
||
| 797 | chris | 283 | { |
| 1304 | chris | 284 | return (regionIndex * NUM_INDICES_PER_REGION); |
| 797 | chris | 285 | } |
| 286 | } |
||
| 287 | } |