package com.graphicsengine.component;

import com.graphicsengine.component.ActorComponent.EntityData;
import com.graphicsengine.spritemesh.SpriteGeometryMesh;
import com.nucleus.component.CPUComponentBuffer;
import com.nucleus.component.Component;
import com.nucleus.component.ComponentBuffer;
import com.nucleus.geometry.AttributeBuffer;
import com.nucleus.geometry.Mesh;
import com.nucleus.geometry.Mesh.Builder;
import com.nucleus.geometry.shape.ShapeBuilder;
import com.nucleus.renderer.NucleusRenderer;
import com.nucleus.texturing.Texture2D;
import com.nucleus.texturing.TextureType;

/**
 * Sprite component, this is a collection of a number of (similar) sprite objects that have entity (actor) data and can
 * be rendered using one draw call.
 * Target usage is geometry shaders (GLES 3.2) or compute shaders (GLES 3.1)
 * 
 * The class can be serialized using gson
 * 
 * @author Richard Sahlin
 *
 */
public class SpriteComponent extends ActorComponent<SpriteGeometryMesh> implements EntityData {

    transient protected AttributeBuffer attributes;
    transient protected CPUComponentBuffer entityData;

    @Override
    public Component createInstance() {
        return new SpriteComponent();
    }

    @Override
    public void set(Component source) {
        set((SpriteComponent) source);
    }

    private void set(SpriteComponent source) {
        super.set(source);
    }

    @Override
    protected void createBuffers(EntityMapper mapper) {
        entityData = new CPUComponentBuffer(count, mapper.attributesPerEntity);
        addBuffer(0, entityData);
    }

    @Override
    public ComponentBuffer getEntityBuffer() {
        return getBuffer(0);
    }

    @Override
    public void bindAttributeBuffer(AttributeBuffer buffer) {
        this.attributes = buffer;
    }

    @Override
    public void updateAttributeData(NucleusRenderer renderer) {
        attributes.setBufferPosition(0);
        attributes.put(entityData.getData());
    }

    /**
     * Returns the texture type used for this component.
     * TODO: Shall this be stored as a Component enum instead?
     * 
     * @return Type of texture used
     */
    public TextureType getTextureType() {
        return textureType;
    }

    /**
     * Returns the number of frames available in the texture
     * 
     * @return
     */
    public int getFrameCount() {
        return mesh.getTexture(Texture2D.TEXTURE_0).getFrameCount();
    }

    @Override
    protected Builder<Mesh> createBuilderInstance(NucleusRenderer renderer) {
        return new SpriteGeometryMesh.Builder(renderer);
    }

    @Override
    protected ShapeBuilder createShapeBuilder() {
        // We are using point mode - do not create shapebuilder
        return null;
    }

    @Override
    public void setEntity(int entity, int entityOffset, float[] data, int offset, int length) {
        ComponentBuffer entityBuffer = getEntityBuffer();
        entityBuffer.put(entity, entityOffset, data, offset, length);
    }

}

@@ -1107,16 +1107,116 @@
 ityData;
+%0A    transient protected CPUComponentBuffer spriteData;%0A    transient protected EntityMapper mapper;
 %0A%0A    @O
@@ -1555,24 +1555,104 @@
 r mapper) %7B%0A
+        spriteData = new CPUComponentBuffer(count, mapper.attributesPerVertex);%0A
         enti
@@ -1744,19 +1744,83 @@
 (0, 
-entityData)
+spriteData);%0A        addBuffer(1, entityData);%0A        this.mapper = mapper
 ;%0A  
@@ -1910,17 +1910,17 @@
 tBuffer(
-0
+1
 );%0A    %7D
@@ -2180,22 +2180,22 @@
 tes.put(
-entity
+sprite
 Data.get
@@ -3110,55 +3110,65 @@
     
-ComponentBuffer entityBuffer = getEntityBuffer(
+entityData.put(entity, entityOffset, data, offset, length
 );%0A 
@@ -3178,69 +3178,174 @@
     
+if (
 entity
-Buffer.put(entity, entityOffset, data, offset, length);
+Offset %3C mapper.attributesPerVertex) %7B%0A            spriteData.put(entity, entityOffset, data, offset, mapper.attributesPerVertex - entityOffset);%0A%0A        %7D
 %0A   

Fix due to change in graphics-by-gl