void MemoryTestFixture::reproduceIssue_Loop()
{
	spAtlas* atlas = nullptr;
	spSkeletonData* skeletonData = nullptr;
	spAnimationStateData* stateData = nullptr;
	spAnimationState* state = nullptr;

	//////////////////////////////////////////////////////////////////////////
	// Initialize Animations
	LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);

	///////////////////////////////////////////////////////////////////////////

	if (state)
		state->listener = (spAnimationStateListener)&spineAnimStateHandler;

	spAnimationState_setAnimationByName(state, 0, "walk", false);

	// run normal update
	for (int i = 0; i < 50; ++i) {
		const float timeSlice = 1.0f / 60.0f;
		spSkeleton_update(skeleton, timeSlice);
		spAnimationState_update(state, timeSlice);
		spAnimationState_apply(state, skeleton);
	}

	DisposeAll(skeleton, state, stateData, skeletonData, atlas);
}
void SkeletonAnimationFbo::updateSkeletonAnimation()
{
    if (!isSkeletonValid()) {
        update();
        return;
    }

    if (!mEventCache.isEmpty()){
        Q_FOREACH(SpineEvent* event, mEventCache)
            SAFE_DELETE(event);
        mEventCache.clear();
    }

    qint64 mSecs = 0;
    if (!mTimer.isValid())
        mTimer.start();
    else
        mSecs = mTimer.restart();

    const float deltaTime = mSecs/1000.0 * mTimeScale;
    spSkeleton_update(mspSkeleton, deltaTime);
    spAnimationState_update(mspAnimationState, deltaTime);
    spAnimationState_apply(mspAnimationState, mspSkeleton);
    spSkeleton_updateWorldTransform(mspSkeleton);

    const QRectF rect = calculateSkeletonRect();
    setSourceSize(QSize(rect.width(), rect.height()));
    setImplicitSize(rect.width(), rect.height());
    setPosition(QPointF(rect.left(), -1.0f*(rect.top() + rect.height())));
    update();
}
void MemoryTestFixture::reproduceIssue_777()
{
	spAtlas* atlas = nullptr;
	spSkeletonData* skeletonData = nullptr;
	spAnimationStateData* stateData = nullptr;
	spSkeleton* skeleton = nullptr;
	spAnimationState* state = nullptr;

	//////////////////////////////////////////////////////////////////////////
	// Initialize Animations
	LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);

	///////////////////////////////////////////////////////////////////////////
	// Run animation
	spSkeleton_setToSetupPose(skeleton);
	SpineEventMonitor eventMonitor(state);
	//eventMonitor.SetDebugLogging(true);

	// Set Animation and Play for 5 frames
	spAnimationState_setAnimationByName(state, 0, "walk", true);
	for (int i = 0; i < 5; ++i) {
		const float timeSlice = 1.0f / 60.0f;
		spSkeleton_update(skeleton, timeSlice);
		spAnimationState_update(state, timeSlice);
		spAnimationState_apply(state, skeleton);
	}

	// Change animation twice in a row
	spAnimationState_setAnimationByName(state, 0, "walk", false);
	spAnimationState_setAnimationByName(state, 0, "run", false);

	// run normal update
	for (int i = 0; i < 5; ++i) {
		const float timeSlice = 1.0f / 60.0f;
		spSkeleton_update(skeleton, timeSlice);
		spAnimationState_update(state, timeSlice);
		spAnimationState_apply(state, skeleton);
	}

	// Now we'd lose mixingFrom (the first "walk" entry we set above) and should leak
	spAnimationState_setAnimationByName(state, 0, "run", false);

	//////////////////////////////////////////////////////////////////////////
	// Cleanup Animations
	DisposeAll(skeleton, state, stateData, skeletonData, atlas);
}
static void testRunner(const char* jsonName, const char* atlasName)
{
	///////////////////////////////////////////////////////////////////////////
	// Global Animation Information
	spAtlas* atlas = spAtlas_createFromFile(atlasName, 0);
	ASSERT(atlas != 0);

	spSkeletonData* skeletonData = readSkeletonJsonData(jsonName, atlas);
	ASSERT(skeletonData != 0);

	spAnimationStateData* stateData = spAnimationStateData_create(skeletonData);
	ASSERT(stateData != 0);
	stateData->defaultMix = 0.2f; // force mixing

	///////////////////////////////////////////////////////////////////////////
	// Animation Instance 
	spSkeleton* skeleton = spSkeleton_create(skeletonData);
	ASSERT(skeleton != 0);

	spAnimationState* state = spAnimationState_create(stateData);
	ASSERT(state != 0);


	///////////////////////////////////////////////////////////////////////////
	// Run animation
	spSkeleton_setToSetupPose(skeleton);
	SpineEventMonitor eventMonitor(state);
//	eventMonitor.SetDebugLogging(true);


	AnimList anims; // Let's chain all the animations together as a test
	size_t count = enumerateAnimations(anims, skeletonData);
	if (count > 0) spAnimationState_setAnimationByName(state, 0, anims[0].c_str(), false);
	for (size_t i = 1; i < count; ++i) {
		spAnimationState_addAnimationByName(state, 0, anims[i].c_str(), false, 0.0f);
	}

	// Run Loop
	for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i) {
		const float timeSlice = 1.0f / 60.0f;
		spSkeleton_update(skeleton, timeSlice);
		spAnimationState_update(state, timeSlice);
		spAnimationState_apply(state, skeleton);
	}

	
	///////////////////////////////////////////////////////////////////////////
	// Dispose Instance
	spSkeleton_dispose(skeleton);
	spAnimationState_dispose(state);

	///////////////////////////////////////////////////////////////////////////
	// Dispose Global
	spAnimationStateData_dispose(stateData);
	spSkeletonData_dispose(skeletonData);
	spAtlas_dispose(atlas);
}
//////////////////////////////////////////////////////////////////////////
// Reproduce Memory leak as described in Issue #776
// https://github.com/EsotericSoftware/spine-runtimes/issues/776
void MemoryTestFixture::reproduceIssue_776()
{
	spAtlas* atlas = nullptr;
	spSkeletonData* skeletonData = nullptr;
	spAnimationStateData* stateData = nullptr;
	spSkeleton* skeleton = nullptr;
	spAnimationState* state = nullptr;

	//////////////////////////////////////////////////////////////////////////
	// Initialize Animations
	LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);

	///////////////////////////////////////////////////////////////////////////
	// Run animation
	spSkeleton_setToSetupPose(skeleton);
	InterruptMonitor eventMonitor(state);
	//eventMonitor.SetDebugLogging(true);

	// Interrupt the animation on this specific sequence of spEventType(s)
	eventMonitor
		.AddInterruptEvent(SP_ANIMATION_INTERRUPT, "jump")
		.AddInterruptEvent(SP_ANIMATION_START);

	spAnimationState_setAnimationByName(state, 0, "walk", true);
	spAnimationState_addAnimationByName(state, 0, "jump", false, 0.0f);
	spAnimationState_addAnimationByName(state, 0, "run",  true,  0.0f);
	spAnimationState_addAnimationByName(state, 0, "jump", false, 3.0f);
	spAnimationState_addAnimationByName(state, 0, "walk", true,  0.0f);
	spAnimationState_addAnimationByName(state, 0, "idle", false, 1.0f);

	for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i) {
		const float timeSlice = 1.0f / 60.0f;
		spSkeleton_update(skeleton, timeSlice);
		spAnimationState_update(state, timeSlice);
		spAnimationState_apply(state, skeleton);
	}

	//////////////////////////////////////////////////////////////////////////
	// Cleanup Animations
	DisposeAll(skeleton, state, stateData, skeletonData, atlas);
}
ENTITY_COMPONENT_METHOD(ComponentSpine, update)
{
    if(!self.skeleton)
    {
        return 0;
    }

    auto dt = System::getInstance().getCurrentDt();
    auto & mesh = self.mesh;

    Transform transform;

    getTransformFromComponent(state, transform);

    mesh.setPosition(transform.position);
    mesh.setRotation(transform.rotation);
    mesh.setScale(transform.scale);

    spSkeleton_update(self.skeleton, dt * self.timeFactor);
    spAnimationState_update(self.animationState, dt * self.timeFactor);
    spAnimationState_apply(self.animationState, self.skeleton);
    spSkeleton_updateWorldTransform(self.skeleton);

    auto vertices = self.mesh.getVertexBuffer().map();
    auto indices = self.mesh.getIndexBuffer().map();
    uint vertex_count = 0;
    uint index_count = 0;

    for(int i = 0; i < self.skeleton->slotsCount; ++i)
    {
        auto slot = self.skeleton->drawOrder[i];
        auto attachment = slot->attachment;

        if(!attachment)
        {
            continue;
        }

        switch(attachment->type)
        {
            case SP_ATTACHMENT_REGION:
            {
                Vector2 computed_vertices[4];
                auto region_attachment = (spRegionAttachment*)attachment;
                auto color = Vector4(
                    self.skeleton->r * slot->r,
                    self.skeleton->g * slot->g,
                    self.skeleton->b * slot->b,
                    self.skeleton->a * slot->a
                    );

                self.mesh.setTexture(* (graphics::Texture*)((spAtlasRegion*)region_attachment->rendererObject)->page->rendererObject);

                spRegionAttachment_computeWorldVertices(region_attachment, slot->bone, (float *)computed_vertices);

                vertices[vertex_count].color = color;
                vertices[vertex_count].position = computed_vertices[0];
                vertices[vertex_count].texCoords.x = region_attachment->uvs[SP_VERTEX_X1];
                vertices[vertex_count].texCoords.y = region_attachment->uvs[SP_VERTEX_Y1];

                vertices[vertex_count + 1].color = color;
                vertices[vertex_count + 1].position = computed_vertices[1];
                vertices[vertex_count + 1].texCoords.x = region_attachment->uvs[SP_VERTEX_X2];
                vertices[vertex_count + 1].texCoords.y = region_attachment->uvs[SP_VERTEX_Y2];

                vertices[vertex_count + 2].color = color;
                vertices[vertex_count + 2].position = computed_vertices[2];
                vertices[vertex_count + 2].texCoords.x = region_attachment->uvs[SP_VERTEX_X3];
                vertices[vertex_count + 2].texCoords.y = region_attachment->uvs[SP_VERTEX_Y3];

                vertices[vertex_count + 3].color = color;
                vertices[vertex_count + 3].position = computed_vertices[3];
                vertices[vertex_count + 3].texCoords.x = region_attachment->uvs[SP_VERTEX_X4];
                vertices[vertex_count + 3].texCoords.y = region_attachment->uvs[SP_VERTEX_Y4];


                indices[index_count + 0] = vertex_count + 0;
                indices[index_count + 1] = vertex_count + 1;
                indices[index_count + 2] = vertex_count + 2;
                indices[index_count + 3] = vertex_count + 2;
                indices[index_count + 4] = vertex_count + 3;
                indices[index_count + 5] = vertex_count + 0;

                vertex_count += 4;
                index_count += 6;
            }
            break;

            case SP_ATTACHMENT_MESH:
            {
                auto mesh = (spMeshAttachment*)attachment;
                auto initial_vertex_count = vertex_count;
                auto color = Vector4(
                    self.skeleton->r * slot->r,
                    self.skeleton->g * slot->g,
                    self.skeleton->b * slot->b,
                    self.skeleton->a * slot->a
                    );

                float *_vertices = mesh->vertices;
                const spBone* bone = slot->bone;
                float x = bone->skeleton->x + bone->worldX, y = bone->skeleton->y + bone->worldY;

                self.mesh.setTexture(* (graphics::Texture*)((spAtlasRegion*)mesh->rendererObject)->page->rendererObject);

                if(slot->attachmentVerticesCount == mesh->verticesCount)
                {
                    _vertices = slot->attachmentVertices;
                }

                for(int i = 0; i < mesh->verticesCount; i += 2)
                {
                    const float vx = _vertices[i], vy = _vertices[i + 1];
                    auto & vertex = vertices[initial_vertex_count + i / 2];
                    vertex.position.x = vx * bone->m00 + vy * bone->m01 + x;
                    vertex.position.y = vx * bone->m10 + vy * bone->m11 + y;
                    vertex.texCoords.u = mesh->uvs[i];
                    vertex.texCoords.v = mesh->uvs[i + 1];
                    vertex.color = color;
                    ++vertex_count;
                }

                for(int i = 0; i < mesh->trianglesCount; ++i)
                {
                    int index = mesh->triangles[i] << 1;
                    indices[index_count] = initial_vertex_count + index / 2;
                    ++index_count;
                }
            }
            break;

            case SP_ATTACHMENT_SKINNED_MESH:
            {
                auto mesh = (spSkinnedMeshAttachment*)attachment;
                auto initial_vertex_count = vertex_count;
                auto color = Vector4(
                    self.skeleton->r * slot->r,
                    self.skeleton->g * slot->g,
                    self.skeleton->b * slot->b,
                    self.skeleton->a * slot->a
                    );

                self.mesh.setTexture(* (graphics::Texture*)((spAtlasRegion*)mesh->rendererObject)->page->rendererObject);

                int w = 0, v = 0, b = 0, f = 0;
                float x = slot->bone->skeleton->x, y = slot->bone->skeleton->y;
                spBone** skeletonBones = slot->bone->skeleton->bones;

                if(slot->attachmentVerticesCount == 0)
                {
                    for(; v < mesh->bonesCount; w += 2)
                    {
                        float wx = 0, wy = 0;
                        const int nn = mesh->bones[v] + v;
                        v++;
                        for(; v <= nn; v++, b += 3)
                        {
                            const spBone* bone = skeletonBones[mesh->bones[v]];
                            const float vx = mesh->weights[b], vy = mesh->weights[b + 1], weight = mesh->weights[b + 2];
                            wx += (vx * bone->m00 + vy * bone->m01 + bone->worldX) * weight;
                            wy += (vx * bone->m10 + vy * bone->m11 + bone->worldY) * weight;
                        }
                        auto & vertex = vertices[initial_vertex_count + w / 2];
                        ++vertex_count;
                        vertex.position.x = wx + x;
                        vertex.position.y = wy + y;
                        vertex.texCoords.u = mesh->uvs[w];
                        vertex.texCoords.v = mesh->uvs[w + 1];
                        vertex.color = color;
                    }
                }
                else
                {
                    const float* ffd = slot->attachmentVertices;
                    for(; v < mesh->bonesCount; w += 2)
                    {
                        float wx = 0, wy = 0;
                        const int nn = mesh->bones[v] + v;
                        v++;
                        for(; v <= nn; v++, b += 3, f += 2)
                        {
                            const spBone* bone = skeletonBones[mesh->bones[v]];
                            const float vx = mesh->weights[b] + ffd[f], vy = mesh->weights[b + 1] + ffd[f + 1], weight = mesh->weights[b + 2];
                            wx += (vx * bone->m00 + vy * bone->m01 + bone->worldX) * weight;
                            wy += (vx * bone->m10 + vy * bone->m11 + bone->worldY) * weight;
                        }
                        auto & vertex = vertices[initial_vertex_count + w / 2];
                        ++vertex_count;
                        vertex.position.x = wx + x;
                        vertex.position.y = wy + y;
                        vertex.texCoords.u = mesh->uvs[w];
                        vertex.texCoords.v = mesh->uvs[w + 1];
                        vertex.color = color;
                    }
                }

                for(int i = 0; i < mesh->trianglesCount; ++i)
                {
                    int index = mesh->triangles[i] << 1;
                    indices[index_count] = initial_vertex_count + index / 2;
                    ++index_count;
                }
            }
            break;

            default:
            break;
        }
    }

    self.mesh.setVertexCount(vertex_count);
    self.mesh.setIndexCount(index_count);
    self.mesh.getVertexBuffer().unMap();
    self.mesh.getIndexBuffer().unMap();
}
Beispiel #7
0
void WIPAnimator::update(f32 dt)
{
	if(!_frame_ref)
		return;

	f32 iww = 1.f/g_app_manager->get_window_width();
	f32 iwh = 1.f/g_app_manager->get_window_height();

	f32 sw = _out_buffer->get_width()*iww;
	f32 sh = _out_buffer->get_height()*iwh;

	f32 hw =g_app_manager->get_window_width()*0.5f;
	f32 hh = g_app_manager->get_window_height()*0.65f;


	_out_buffer->begin();
	glClear(GL_COLOR_BUFFER_BIT);
	_out_buffer->end();
	spSkeleton_update(skeleton, dt);
	spAnimationState_update(state, dt * time_scale);
	spAnimationState_apply(state, skeleton);
	spSkeleton_updateWorldTransform(skeleton);
	_out_buffer->begin();
	for(int i=0;i<skeleton->slotCount; ++i)
	{
		spSlot* slot = skeleton->drawOrder[i];
		spAttachment* attachment = slot->attachment;
		if (!attachment) continue;
		WIPTexture* p = 0;
		if (attachment->type == SP_ATTACHMENT_REGION) 
		{
			//available
			spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment;
			p = (WIPTexture*)((spAtlasRegion*)regionAttachment->rendererObject)->page->rendererObject;
			spRegionAttachment_computeWorldVertices(regionAttachment,  slot->skeleton->x, slot->skeleton->y,slot->bone, _world_vertices);
		}

		if(p)
		{
			spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment;
			int tex_x = p->get_width();
			int tex_y = p->get_height();

			RenderQuad uv_q;
			uv_q.lt.x = regionAttachment->uvs[SP_VERTEX_X1];
			uv_q.lt.y =regionAttachment->uvs[SP_VERTEX_Y1];
			uv_q.lb.x = regionAttachment->uvs[SP_VERTEX_X2];
			uv_q.lb.y =regionAttachment->uvs[SP_VERTEX_Y2];
			uv_q.rt.x = regionAttachment->uvs[SP_VERTEX_X4];
			uv_q.rt.y =regionAttachment->uvs[SP_VERTEX_Y4];
			uv_q.rb.x = regionAttachment->uvs[SP_VERTEX_X3];
			uv_q.rb.y =regionAttachment->uvs[SP_VERTEX_Y3];

			int x1 = _world_vertices[SP_VERTEX_X1];
			int y1 = _world_vertices[SP_VERTEX_Y1];
			int x2 = _world_vertices[SP_VERTEX_X2];
			int y2 = _world_vertices[SP_VERTEX_Y2];
			int x4 = _world_vertices[SP_VERTEX_X3];
			int y4 = _world_vertices[SP_VERTEX_Y3];
			int x3 = _world_vertices[SP_VERTEX_X4];
			int y3 = _world_vertices[SP_VERTEX_Y4];

			

			RenderQuad q;
			q.lb.x = x1+hw;
			q.lb.y = y1+hh;
			q.lt.x = x2+hw;
			q.lt.y = y2+hh;
			q.rb.x = x3+hw;
			q.rb.y = y3+hh;
			q.rt.x = x4+hw;
			q.rt.y = y4+hh;

			
			
			g_renderer->render(p,&q,&uv_q);
			

		}
		
	}
	_out_buffer->end();
	_frame_ref->texture = _out_buffer;
	_frame_ref->framebox->set_quickly(0,0,0,1,1,1,1,0,0,0);

	
}
void SkeletonRenderer::update (float deltaTime) {
	spSkeleton_update(_skeleton, deltaTime * _timeScale);
}
void Skeleton::update (float deltaTime) {
	spSkeleton_update(skeleton, deltaTime * timeScale);
}
Beispiel #10
0
void Skeleton::update(unsigned long dt)
{
    const float delta = dt / 1000.0f;
    spSkeleton_update(skeleton_, delta);
    spAnimationState_update(state_, delta * time_scale_);
    spAnimationState_apply(state_, skeleton_);
    spSkeleton_updateWorldTransform(skeleton_);

    // This solution is not ideal. We iterate over the bones twice: First to
    // determine number of vertices, second to update the vertex buffer.
    num_vertices_ = get_vertex_count(skeleton_, &texture_);
    if (num_vertices_ > max_vertices_)
    {
        max_vertices_ = num_vertices_;
        vertices_ = std::make_unique<SpriteVertex[]>(max_vertices_);
    }

    size_t i = 0;
    for_each(skeleton_, [this, &i](spSlot* slot) {
        if (!slot->attachment)
            return;

        switch (slot->attachment->type)
        {
            case SP_ATTACHMENT_REGION: {
                float vertices[8];
                spRegionAttachment* region =
                    reinterpret_cast<spRegionAttachment*>(slot->attachment);
                R_ASSERT(texture_ == get_texture(region),
                         kErrorMultipleTexturesUnsupported);
                spRegionAttachment_computeWorldVertices(
                    region, slot->bone, vertices);

                const char r = skeleton_->r * slot->r * 0xff;
                const char g = skeleton_->g * slot->g * 0xff;
                const char b = skeleton_->b * slot->b * 0xff;
                const char a = skeleton_->a * slot->a * 0xff;

                vertices_[i].color.r = r;
                vertices_[i].color.g = g;
                vertices_[i].color.b = b;
                vertices_[i].color.a = a;
                vertices_[i].texcoord.x = region->uvs[SP_VERTEX_X1];
                vertices_[i].texcoord.y = region->uvs[SP_VERTEX_Y1];
                vertices_[i].position.x = vertices[SP_VERTEX_X1];
                vertices_[i].position.y = vertices[SP_VERTEX_Y1];

                vertices_[++i].color.r = r;
                vertices_[i].color.g = g;
                vertices_[i].color.b = b;
                vertices_[i].color.a = a;
                vertices_[i].texcoord.x = region->uvs[SP_VERTEX_X2];
                vertices_[i].texcoord.y = region->uvs[SP_VERTEX_Y2];
                vertices_[i].position.x = vertices[SP_VERTEX_X2];
                vertices_[i].position.y = vertices[SP_VERTEX_Y2];

                vertices_[++i].color.r = r;
                vertices_[i].color.g = g;
                vertices_[i].color.b = b;
                vertices_[i].color.a = a;
                vertices_[i].texcoord.x = region->uvs[SP_VERTEX_X3];
                vertices_[i].texcoord.y = region->uvs[SP_VERTEX_Y3];
                vertices_[i].position.x = vertices[SP_VERTEX_X3];
                vertices_[i].position.y = vertices[SP_VERTEX_Y3];

                ++i;
                vertices_[i] = vertices_[i - 1];

                vertices_[++i].color.r = r;
                vertices_[i].color.g = g;
                vertices_[i].color.b = b;
                vertices_[i].color.a = a;
                vertices_[i].texcoord.x = region->uvs[SP_VERTEX_X4];
                vertices_[i].texcoord.y = region->uvs[SP_VERTEX_Y4];
                vertices_[i].position.x = vertices[SP_VERTEX_X4];
                vertices_[i].position.y = vertices[SP_VERTEX_Y4];

                ++i;
                vertices_[i] = vertices_[i - 5];

                ++i;
                break;
            }
            case SP_ATTACHMENT_BOUNDING_BOX:
                break;
            case SP_ATTACHMENT_MESH: {
                spMeshAttachment* mesh =
                    reinterpret_cast<spMeshAttachment*>(slot->attachment);
                R_ASSERT(texture_ == get_texture(mesh),
                         kErrorMultipleTexturesUnsupported);
                i += update_mesh(&vertices_[i], skeleton_, mesh, slot);
                break;
            }
            case SP_ATTACHMENT_SKINNED_MESH: {
                spSkinnedMeshAttachment* mesh =
                    reinterpret_cast<spSkinnedMeshAttachment*>(
                        slot->attachment);
                R_ASSERT(texture_ == get_texture(mesh),
                         kErrorMultipleTexturesUnsupported);
                i += update_mesh(&vertices_[i], skeleton_, mesh, slot);
                break;
            }
        }
        if (slot->data->blendMode != SP_BLEND_MODE_NORMAL)  // TODO: Implement.
            LOGE("Non-normal blend mode not yet implemented");
    });

    vertex_buffer_.upload(vertices_.get(), i * sizeof(SpriteVertex));
}
Beispiel #11
0
 void SpineDrawable::update(float delta)
 {
     spSkeleton_update(skeleton, delta);
     spAnimationState_update(animationState, delta);
 }
Beispiel #12
0
void SkeletonDrawable::update (float deltaTime) {
	spSkeleton_update(skeleton, deltaTime);
	spAnimationState_update(state, deltaTime * timeScale);
	spAnimationState_apply(state, skeleton);
	spSkeleton_updateWorldTransform(skeleton);
}