This week only. Pastebin PRO Accounts Christmas Special! Don't miss out!Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Nov 3rd, 2013  |  syntax: Java  |  size: 19.12 KB  |  views: 196  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /* Copyright 2011 See AUTHORS file.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. *   http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. ******************************************************************************/
  15.  
  16. package com.esotericsoftware.spine;
  17.  
  18. import com.badlogic.gdx.Gdx;
  19. import com.badlogic.gdx.graphics.Color;
  20. import com.badlogic.gdx.graphics.GL10;
  21. import com.badlogic.gdx.graphics.GL11;
  22. import com.badlogic.gdx.graphics.GL20;
  23. import com.badlogic.gdx.graphics.GLCommon;
  24. import com.badlogic.gdx.graphics.Mesh;
  25. import com.badlogic.gdx.graphics.Mesh.VertexDataType;
  26. import com.badlogic.gdx.graphics.Texture;
  27. import com.badlogic.gdx.graphics.VertexAttribute;
  28. import com.badlogic.gdx.graphics.VertexAttributes.Usage;
  29. import com.badlogic.gdx.graphics.glutils.ShaderProgram;
  30. import com.badlogic.gdx.math.Matrix4;
  31. import com.badlogic.gdx.utils.Disposable;
  32.  
  33. /** <p>
  34. * A SpineSpriteBatch is used to draw 2D rectangles that reference a texture (region). The class will batch the drawing commands and
  35. * optimize them for processing by the GPU.
  36. * </p>
  37. *
  38. * <p>
  39. * To draw something with a SpineSpriteBatch one has to first call the {@link SpineSpriteBatch#begin()} method which will setup appropriate
  40. * render states. When you are done with drawing you have to call {@link SpineSpriteBatch#end()} which will actually draw the things
  41. * you specified.
  42. * </p>
  43. *
  44. * <p>
  45. * All drawing commands of the SpineSpriteBatch operate in screen coordinates. The screen coordinate system has an x-axis pointing to
  46. * the right, an y-axis pointing upwards and the origin is in the lower left corner of the screen. You can also provide your own
  47. * transformation and projection matrices if you so wish.
  48. * </p>
  49. *
  50. * <p>
  51. * A SpineSpriteBatch is managed. In case the OpenGL context is lost all OpenGL resources a SpineSpriteBatch uses internally get
  52. * invalidated. A context is lost when a user switches to another application or receives an incoming call on Android. A
  53. * SpineSpriteBatch will be automatically reloaded after the OpenGL context is restored.
  54. * </p>
  55. *
  56. * <p>
  57. * A SpineSpriteBatch is a pretty heavy object so you should only ever have one in your program.
  58. * </p>
  59. *
  60. * <p>
  61. * A SpineSpriteBatch works with OpenGL ES 1.x and 2.0. In the case of a 2.0 context it will use its own custom shader to draw all
  62. * provided sprites. You can set your own custom shader via {@link #setShader(ShaderProgram)}.
  63. * </p>
  64. *
  65. * <p>
  66. * A SpineSpriteBatch has to be disposed if it is no longer used.
  67. * </p>
  68. *
  69. * @author mzechner */
  70. public class SpineSpriteBatch implements Disposable {
  71.         private Mesh mesh;
  72.         private Mesh[] buffers;
  73.  
  74.         private Texture lastTexture = null;
  75.         private int idx = 0;
  76.         private int currBufferIdx = 0;
  77.         private final float[] vertices;
  78.  
  79.         private final Matrix4 transformMatrix = new Matrix4();
  80.         private final Matrix4 projectionMatrix = new Matrix4();
  81.         private final Matrix4 combinedMatrix = new Matrix4();
  82.  
  83.         private boolean drawing = false;
  84.  
  85.         private boolean blendingDisabled = false;
  86.         private int blendSrcFunc = GL11.GL_SRC_ALPHA;
  87.         private int blendDstFunc = GL11.GL_ONE_MINUS_SRC_ALPHA;
  88.  
  89.         private final ShaderProgram shader;
  90.         private boolean ownsShader;
  91.  
  92.         float color = Color.WHITE.toFloatBits();
  93.         /** number of render calls since last {@link #begin()} **/
  94.         public int renderCalls = 0;
  95.  
  96.         /** number of rendering calls ever, will not be reset, unless it's done manually **/
  97.         public int totalRenderCalls = 0;
  98.  
  99.         /** the maximum number of sprites rendered in one batch so far **/
  100.         public int maxSpritesInBatch = 0;
  101.         private ShaderProgram customShader = null;
  102.  
  103.         /** Constructs a new SpineSpriteBatch. Sets the projection matrix to an orthographic projection with y-axis point upwards, x-axis
  104.          * point to the right and the origin being in the bottom left corner of the screen. The projection will be pixel perfect with
  105.          * respect to the screen resolution. */
  106.         public SpineSpriteBatch () {
  107.                 this(1000);
  108.         }
  109.  
  110.         /** Constructs a SpineSpineSpriteBatch with the specified size and (if GL2) the default shader. See
  111.          * {@link #SpineSpineSpriteBatch(int, ShaderProgram)}. */
  112.         public SpineSpriteBatch (int size) {
  113.                 this(size, null);
  114.         }
  115.  
  116.         /** <p>
  117.          * Constructs a new SpineSpineSpriteBatch. Sets the projection matrix to an orthographic projection with y-axis point upwards, x-axis
  118.          * point to the right and the origin being in the bottom left corner of the screen. The projection will be pixel perfect with
  119.          * respect to the screen resolution.
  120.          * </p>
  121.          *
  122.          * <p>
  123.          * The size parameter specifies the maximum size of a single batch in number of sprites
  124.          * </p>
  125.          *
  126.          * <p>
  127.          * The defaultShader specifies the shader to use. Note that the names for uniforms for this default shader are different than
  128.          * the ones expect for shaders set with {@link #setShader(ShaderProgram)}. See the {@link #createDefaultShader()} method.
  129.          * </p>
  130.          *
  131.          * @param size the batch size in number of sprites
  132.          * @param defaultShader the default shader to use. This is not owned by the SpineSpineSpriteBatch and must be disposed separately. */
  133.         public SpineSpriteBatch (int size, ShaderProgram defaultShader) {
  134.                 this(size, 1, defaultShader);
  135.         }
  136.  
  137.         /** Constructs a SpineSpineSpriteBatch with the specified size and number of buffers and (if GL2) the default shader. See
  138.          * {@link #SpineSpineSpriteBatch(int, int, ShaderProgram)}. */
  139.         public SpineSpriteBatch (int size, int buffers) {
  140.                 this(size, buffers, null);
  141.         }
  142.  
  143.         /** <p>
  144.          * Constructs a new SpineSpriteBatch. Sets the projection matrix to an orthographic projection with y-axis point upwards, x-axis
  145.          * point to the right and the origin being in the bottom left corner of the screen. The projection will be pixel perfect with
  146.          * respect to the screen resolution.
  147.          * </p>
  148.          *
  149.          * <p>
  150.          * The size parameter specifies the maximum size of a single batch in number of sprites
  151.          * </p>
  152.          *
  153.          * <p>
  154.          * The defaultShader specifies the shader to use. Note that the names for uniforms for this default shader are different than
  155.          * the ones expect for shaders set with {@link #setShader(ShaderProgram)}. See the {@link #createDefaultShader()} method.
  156.          * </p>
  157.          *
  158.          * @param size the batch size in number of sprites
  159.          * @param buffers the number of buffers to use. only makes sense with VBOs. This is an expert function.
  160.          * @param defaultShader the default shader to use. This is not owned by the SpineSpriteBatch and must be disposed separately. */
  161.         public SpineSpriteBatch (int size, int buffers, ShaderProgram defaultShader) {
  162.                 this.buffers = new Mesh[buffers];
  163.  
  164.                 for (int i = 0; i < buffers; i++) {
  165.                         this.buffers[i] = new Mesh(VertexDataType.VertexArray, false, size * 4, size * 6, new VertexAttribute(Usage.Position, 2,
  166.                                 ShaderProgram.POSITION_ATTRIBUTE), new VertexAttribute(Usage.ColorPacked, 4, ShaderProgram.COLOR_ATTRIBUTE),
  167.                                 new VertexAttribute(Usage.TextureCoordinates, 2, ShaderProgram.TEXCOORD_ATTRIBUTE + "0"),
  168.                                 new VertexAttribute(Usage.Generic, 1, "a_rot"));
  169.                 }
  170.  
  171.                 projectionMatrix.setToOrtho2D(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
  172.  
  173.                 vertices = new float[size * 24];
  174.  
  175.                 int len = size * 6;
  176.                 short[] indices = new short[len];
  177.                 short j = 0;
  178.                 for (int i = 0; i < len; i += 6, j += 4) {
  179.                         indices[i + 0] = (short)(j + 0);
  180.                         indices[i + 1] = (short)(j + 1);
  181.                         indices[i + 2] = (short)(j + 2);
  182.                         indices[i + 3] = (short)(j + 2);
  183.                         indices[i + 4] = (short)(j + 3);
  184.                         indices[i + 5] = (short)(j + 0);
  185.                 }
  186.                 for (int i = 0; i < buffers; i++) {
  187.                         this.buffers[i].setIndices(indices);
  188.                 }
  189.                 mesh = this.buffers[0];
  190.  
  191.                 if (Gdx.graphics.isGL20Available() && defaultShader == null) {
  192.                         shader = createDefaultShader();
  193.                         ownsShader = true;
  194.                 } else
  195.                         shader = defaultShader;
  196.         }
  197.  
  198.         /** Returns a new instance of the default shader used by SpineSpriteBatch for GL2 when no shader is specified. */
  199.         static public ShaderProgram createDefaultShader () {
  200.                 String vertexShader = "attribute vec4 " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" //
  201.                         + "attribute vec4 " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" //
  202.                         + "attribute vec2 " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" //
  203.                         + "attribute float a_rot;\n" //
  204.                         + "uniform mat4 u_projTrans;\n" //
  205.                         + "varying vec4 v_color;\n" //
  206.                         + "varying vec2 v_texCoords;\n" //
  207.                         + "varying vec3 v_lightDir;\n" //
  208.                         + "const vec3 lightDir = normalize(vec3(-0.0, -1.0, 0.2));\n" //
  209.                         + "\n" //
  210.                         + "void main()\n" //
  211.                         + "{\n" //
  212.                         + "   v_color = " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" //
  213.                         + "   vec2 rad = vec2(-sin(a_rot), cos(a_rot));\n" //
  214.                         + "   v_lightDir = vec3(mat2(rad.y, -rad.x, rad.x, rad.y) * lightDir.xy,lightDir.z);\n" //
  215.                         + "   v_texCoords = " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" //
  216.                         + "   gl_Position =  u_projTrans * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" //
  217.                         + "}\n";
  218.                 String fragmentShader = "#ifdef GL_ES\n" //
  219.                         + "#define LOWP lowp\n" //
  220.                         + "precision mediump float;\n" //
  221.                         + "#else\n" //
  222.                         + "#define LOWP \n" //
  223.                         + "#endif\n" //
  224.                         + "varying LOWP vec4 v_color;\n" //
  225.                         + "varying vec2 v_texCoords;\n" //
  226.                         + "varying vec3 v_lightDir;\n" //
  227.                         + "uniform sampler2D u_texture;\n" //
  228.                         + "uniform sampler2D u_texture2;\n" //
  229.                         + "void main()\n"//
  230.                         + "{\n" //
  231.                         + "   vec4 albedo = texture2D(u_texture, v_texCoords);\n" //
  232.                         + "   vec3 normal = texture2D(u_texture2, v_texCoords).xyz * 2.0 - 1.0;\n" //
  233.                         + "   float light = clamp(dot(normalize(v_lightDir), normal), 0.0, 1.0) ;\n" //
  234.                         + "  gl_FragColor = v_color * vec4((light*light * albedo.rgb), albedo.a);\n" //
  235.                         + "}";
  236.  
  237.                 ShaderProgram shader = new ShaderProgram(vertexShader, fragmentShader);
  238.                 if (shader.isCompiled() == false) throw new IllegalArgumentException("couldn't compile shader: " + shader.getLog());
  239.                 return shader;
  240.         }
  241.  
  242.         /** Sets up the SpineSpriteBatch for drawing. This will disable depth buffer writting. It enables blending and texturing. If you have
  243.          * more texture units enabled than the first one you have to disable them before calling this. Uses a screen coordinate system
  244.          * by default where everything is given in pixels. You can specify your own projection and modelview matrices via
  245.          * {@link #setProjectionMatrix(Matrix4)} and {@link #setTransformMatrix(Matrix4)}. */
  246.         public void begin () {
  247.                 if (drawing) throw new IllegalStateException("you have to call SpineSpriteBatch.end() first");
  248.                 renderCalls = 0;
  249.  
  250.                 Gdx.gl.glDepthMask(false);
  251.                 if (Gdx.graphics.isGL20Available()) {
  252.                         if (customShader != null)
  253.                                 customShader.begin();
  254.                         else
  255.                                 shader.begin();
  256.                 } else {
  257.                         Gdx.gl.glEnable(GL10.GL_TEXTURE_2D);
  258.                 }
  259.                 setupMatrices();
  260.  
  261.                 idx = 0;
  262.                 lastTexture = null;
  263.                 drawing = true;
  264.         }
  265.  
  266.         /** Finishes off rendering. Enables depth writes, disables blending and texturing. Must always be called after a call to
  267.          * {@link #begin()} */
  268.         public void end () {
  269.                 if (!drawing) throw new IllegalStateException("SpineSpriteBatch.begin must be called before end.");
  270.                 if (idx > 0) renderMesh();
  271.                 lastTexture = null;
  272.                 idx = 0;
  273.                 drawing = false;
  274.  
  275.                 GLCommon gl = Gdx.gl;
  276.                 gl.glDepthMask(true);
  277.                 if (isBlendingEnabled()) gl.glDisable(GL10.GL_BLEND);
  278.  
  279.                 if (Gdx.graphics.isGL20Available()) {
  280.                         if (customShader != null)
  281.                                 customShader.end();
  282.                         else
  283.                                 shader.end();
  284.                 } else {
  285.                         gl.glDisable(GL10.GL_TEXTURE_2D);
  286.                 }
  287.         }
  288.        
  289.         /** Sets the color used to tint images when they are added to the SpineSpriteBatch. Default is {@link Color#WHITE}. */
  290.         public void setColor (Color tint) {
  291.                 color = tint.toFloatBits();
  292.         }
  293.  
  294.  
  295.         /** Draws a rectangle using the given vertices. There must be 4 vertices, each made up of 5 elements in this order: x, y, color,
  296.          * u, v. The {@link #getColor()} from the SpineSpriteBatch is not applied. */
  297.         public void draw (Texture texture, float[] spriteVertices, int offset, int length) {
  298.                 if (!drawing) throw new IllegalStateException("SpineSpriteBatch.begin must be called before draw.");
  299.  
  300.                 if (texture != lastTexture) {
  301.                         switchTexture(texture);
  302.                 }
  303.  
  304.                 int remainingVertices = vertices.length - idx;
  305.                 if (remainingVertices == 0) {
  306.                         renderMesh();
  307.                         remainingVertices = vertices.length;
  308.                 }
  309.                 int vertexCount = Math.min(remainingVertices, length - offset);
  310.                 System.arraycopy(spriteVertices, offset, vertices, idx, vertexCount);
  311.                 offset += vertexCount;
  312.                 idx += vertexCount;
  313.  
  314.                 while (offset < length) {
  315.                         renderMesh();
  316.                         vertexCount = Math.min(vertices.length, length - offset);
  317.                         System.arraycopy(spriteVertices, offset, vertices, 0, vertexCount);
  318.                         offset += vertexCount;
  319.                         idx += vertexCount;
  320.                 }
  321.         }
  322.  
  323.  
  324.         /** Causes any pending sprites to be rendered, without ending the SpineSpriteBatch. */
  325.         public void flush () {
  326.                 renderMesh();
  327.         }
  328.  
  329.         private void renderMesh () {
  330.                 if (idx == 0) return;
  331.  
  332.                 renderCalls++;
  333.                 totalRenderCalls++;
  334.                 int spritesInBatch = idx / 20;
  335.                 if (spritesInBatch > maxSpritesInBatch) maxSpritesInBatch = spritesInBatch;
  336.  
  337.                 lastTexture.bind();
  338.                 mesh.setVertices(vertices, 0, idx);
  339.                 mesh.getIndicesBuffer().position(0);
  340.                 mesh.getIndicesBuffer().limit(spritesInBatch * 6);
  341.  
  342.                 if (blendingDisabled) {
  343.                         Gdx.gl.glDisable(GL20.GL_BLEND);
  344.                 } else {
  345.                         Gdx.gl.glEnable(GL20.GL_BLEND);
  346.                         if (blendSrcFunc != -1) Gdx.gl.glBlendFunc(blendSrcFunc, blendDstFunc);
  347.                 }
  348.  
  349.                 if (Gdx.graphics.isGL20Available()) {
  350.                         if (customShader != null)
  351.                                 mesh.render(customShader, GL10.GL_TRIANGLES, 0, spritesInBatch * 6);
  352.                         else
  353.                                 mesh.render(shader, GL10.GL_TRIANGLES, 0, spritesInBatch * 6);
  354.                 } else {
  355.                         mesh.render(GL10.GL_TRIANGLES, 0, spritesInBatch * 6);
  356.                 }
  357.  
  358.                 idx = 0;
  359.                 currBufferIdx++;
  360.                 if (currBufferIdx == buffers.length) currBufferIdx = 0;
  361.                 mesh = buffers[currBufferIdx];
  362.         }
  363.  
  364.         /** Disables blending for drawing sprites. */
  365.         public void disableBlending () {
  366.                 if (blendingDisabled) return;
  367.                 renderMesh();
  368.                 blendingDisabled = true;
  369.         }
  370.  
  371.         /** Enables blending for sprites */
  372.         public void enableBlending () {
  373.                 if (!blendingDisabled) return;
  374.                 renderMesh();
  375.                 blendingDisabled = false;
  376.         }
  377.  
  378.         /** Sets the blending function to be used when rendering sprites.
  379.          *
  380.          * @param srcFunc the source function, e.g. GL11.GL_SRC_ALPHA. If set to -1, SpineSpriteBatch won't change the blending function.
  381.          * @param dstFunc the destination function, e.g. GL11.GL_ONE_MINUS_SRC_ALPHA */
  382.         public void setBlendFunction (int srcFunc, int dstFunc) {
  383.                 renderMesh();
  384.                 blendSrcFunc = srcFunc;
  385.                 blendDstFunc = dstFunc;
  386.         }
  387.  
  388.         /** Disposes all resources associated with this SpineSpriteBatch */
  389.         public void dispose () {
  390.                 for (int i = 0; i < buffers.length; i++)
  391.                         buffers[i].dispose();
  392.                 if (ownsShader && shader != null) shader.dispose();
  393.         }
  394.  
  395.         /** Returns the current projection matrix. Changing this will result in undefined behaviour.
  396.          *
  397.          * @return the currently set projection matrix */
  398.         public Matrix4 getProjectionMatrix () {
  399.                 return projectionMatrix;
  400.         }
  401.  
  402.         /** Returns the current transform matrix. Changing this will result in undefined behaviour.
  403.          *
  404.          * @return the currently set transform matrix */
  405.         public Matrix4 getTransformMatrix () {
  406.                 return transformMatrix;
  407.         }
  408.  
  409.         /** Sets the projection matrix to be used by this SpineSpriteBatch. If this is called inside a {@link #begin()}/{@link #end()} block.
  410.          * the current batch is flushed to the gpu.
  411.          *
  412.          * @param projection the projection matrix */
  413.         public void setProjectionMatrix (Matrix4 projection) {
  414.                 if (drawing) flush();
  415.                 projectionMatrix.set(projection);
  416.                 if (drawing) setupMatrices();
  417.         }
  418.  
  419.         /** Sets the transform matrix to be used by this SpineSpriteBatch. If this is called inside a {@link #begin()}/{@link #end()} block.
  420.          * the current batch is flushed to the gpu.
  421.          *
  422.          * @param transform the transform matrix */
  423.         public void setTransformMatrix (Matrix4 transform) {
  424.                 if (drawing) flush();
  425.                 transformMatrix.set(transform);
  426.                 if (drawing) setupMatrices();
  427.         }
  428.  
  429.         private void setupMatrices () {
  430.                 if (!Gdx.graphics.isGL20Available()) {
  431.                         GL10 gl = Gdx.gl10;
  432.                         gl.glMatrixMode(GL10.GL_PROJECTION);
  433.                         gl.glLoadMatrixf(projectionMatrix.val, 0);
  434.                         gl.glMatrixMode(GL10.GL_MODELVIEW);
  435.                         gl.glLoadMatrixf(transformMatrix.val, 0);
  436.                 } else {
  437.                         combinedMatrix.set(projectionMatrix).mul(transformMatrix);
  438.                         if (customShader != null) {
  439.                                 customShader.setUniformMatrix("u_projTrans", combinedMatrix);
  440.                                 customShader.setUniformi("u_texture", 0);
  441.                                 customShader.setUniformi("u_texture2", 1);
  442.                         } else {
  443.                                 shader.setUniformMatrix("u_projTrans", combinedMatrix);
  444.                                 shader.setUniformi("u_texture", 0);
  445.                                 shader.setUniformi("u_texture2", 1);
  446.                         }
  447.                 }
  448.         }
  449.  
  450.         private void switchTexture (Texture texture) {
  451.                 renderMesh();
  452.                 lastTexture = texture;
  453.         }
  454.  
  455.         /** Sets the shader to be used in a GLES 2.0 environment. Vertex position attribute is called "a_position", the texture
  456.          * coordinates attribute is called called "a_texCoord0", the color attribute is called "a_color". See
  457.          * {@link ShaderProgram#POSITION_ATTRIBUTE}, {@link ShaderProgram#COLOR_ATTRIBUTE} and {@link ShaderProgram#TEXCOORD_ATTRIBUTE}
  458.          * which gets "0" appened to indicate the use of the first texture unit. The combined transform and projection matrx is is
  459.          * uploaded via a mat4 uniform called "u_projTrans". The texture sampler is passed via a uniform called "u_texture".</p>
  460.          *
  461.          * Call this method with a null argument to use the default shader.</p>
  462.          *
  463.          * This method will flush the batch before setting the new shader, you can call it in between {@link #begin()} and
  464.          * {@link #end()}.
  465.          *
  466.          * @param shader the {@link ShaderProgram} or null to use the default shader. */
  467.         public void setShader (ShaderProgram shader) {
  468.                 if (drawing) {
  469.                         flush();
  470.                         if (customShader != null)
  471.                                 customShader.end();
  472.                         else
  473.                                 this.shader.end();
  474.                 }
  475.                 customShader = shader;
  476.                 if (drawing) {
  477.                         if (customShader != null)
  478.                                 customShader.begin();
  479.                         else
  480.                                 this.shader.begin();
  481.                         setupMatrices();
  482.                 }
  483.         }
  484.  
  485.         /** @return whether blending for sprites is enabled */
  486.         public boolean isBlendingEnabled () {
  487.                 return !blendingDisabled;
  488.         }
  489.  
  490.         static public final int X1 = 0;
  491.         static public final int Y1 = 1;
  492.         static public final int C1 = 2;
  493.         static public final int U1 = 3;
  494.         static public final int V1 = 4;
  495.         static public final int R1 = 5;
  496.        
  497.         static public final int X2 = 6;
  498.         static public final int Y2 = 7;
  499.         static public final int C2 = 8;
  500.         static public final int U2 = 9;
  501.         static public final int V2 = 10;
  502.         static public final int R2 = 11;
  503.        
  504.         static public final int X3 = 12;
  505.         static public final int Y3 = 13;
  506.         static public final int C3 = 14;
  507.         static public final int U3 = 15;
  508.         static public final int V3 = 16;
  509.         static public final int R3 = 17;
  510.        
  511.         static public final int X4 = 18;
  512.         static public final int Y4 = 19;
  513.         static public final int C4 = 20;
  514.         static public final int U4 = 21;
  515.         static public final int V4 = 22;
  516.         static public final int R4 = 23;
  517. }
clone this paste RAW Paste Data