mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-21 01:36:02 +08:00
Blend modes for all runtimes.
This commit is contained in:
parent
142e770e5b
commit
f8a76c6455
@ -54,7 +54,7 @@
|
||||
{ "name": "goggles", "bone": "head", "attachment": "goggles" },
|
||||
{ "name": "front_bracer", "bone": "front_bracer", "attachment": "front_bracer" },
|
||||
{ "name": "front_fist", "bone": "front_fist", "attachment": "front_fist_closed" },
|
||||
{ "name": "muzzle", "bone": "gunTip", "additive": true },
|
||||
{ "name": "muzzle", "bone": "gunTip", "blend": "additive" },
|
||||
{ "name": "head-bb", "bone": "head" }
|
||||
],
|
||||
"skins": {
|
||||
|
||||
46
spine-as3/spine-as3/src/spine/BlendMode.as
Normal file
46
spine-as3/spine-as3/src/spine/BlendMode.as
Normal file
@ -0,0 +1,46 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License
|
||||
* Version 2.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
* non-transferable license to install, execute and perform the Spine Runtimes
|
||||
* Software (the "Software") solely for internal use. Without the written
|
||||
* permission of Esoteric Software (typically granted by licensing Spine), you
|
||||
* may not (a) modify, translate, adapt or otherwise create derivative works,
|
||||
* improvements of the Software or develop new applications using the Software
|
||||
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
|
||||
* trademark, patent or other intellectual property or proprietary rights
|
||||
* notices on or in the Software, including any copy thereof. Redistributions
|
||||
* in binary or source form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine {
|
||||
|
||||
public class BlendMode {
|
||||
public static const normal:BlendMode = new BlendMode(0);
|
||||
public static const additive:BlendMode = new BlendMode(1);
|
||||
public static const multiply:BlendMode = new BlendMode(2);
|
||||
public static const screen:BlendMode = new BlendMode(3);
|
||||
|
||||
public var ordinal:int;
|
||||
|
||||
public function BlendMode (ordinal:int) {
|
||||
this.ordinal = ordinal;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -145,7 +145,7 @@ public class SkeletonJson {
|
||||
}
|
||||
|
||||
slotData.attachmentName = slotMap["attachment"];
|
||||
slotData.additiveBlending = slotMap["additive"];
|
||||
slotData.blendMode = BlendMode[slotMap["blend"] || "normal"];
|
||||
|
||||
skeletonData.slots[skeletonData.slots.length] = slotData;
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ public class SlotData {
|
||||
public var b:Number = 1;
|
||||
public var a:Number = 1;
|
||||
public var attachmentName:String;
|
||||
public var additiveBlending:Boolean;
|
||||
public var blendMode:BlendMode;
|
||||
|
||||
public function SlotData (name:String, boneData:BoneData) {
|
||||
if (name == null) throw new ArgumentError("name cannot be null.");
|
||||
|
||||
@ -52,6 +52,8 @@ import spine.attachments.RegionAttachment;
|
||||
public class SkeletonSprite extends Sprite {
|
||||
static private var tempPoint:Point = new Point();
|
||||
static private var tempMatrix:Matrix = new Matrix();
|
||||
static private var blendModes:Vector.<String> = new <String>[
|
||||
BlendMode.NORMAL, BlendMode.ADD, BlendMode.MULTIPLY, BlendMode.SCREEN];
|
||||
|
||||
private var _skeleton:Skeleton;
|
||||
public var timeScale:Number = 1;
|
||||
@ -119,7 +121,7 @@ public class SkeletonSprite extends Sprite {
|
||||
regionAttachment["wrapper"] = wrapper;
|
||||
}
|
||||
|
||||
wrapper.blendMode = slot.data.additiveBlending ? BlendMode.ADD : BlendMode.NORMAL;
|
||||
wrapper.blendMode = blendModes[slot.data.blendMode.ordinal];
|
||||
|
||||
var colorTransform:ColorTransform = wrapper.transform.colorTransform;
|
||||
colorTransform.redMultiplier = skeleton.r * slot.r * regionAttachment.r;
|
||||
|
||||
@ -53,7 +53,7 @@ typedef struct spSlot {
|
||||
spSlot() :
|
||||
data(0),
|
||||
bone(0),
|
||||
r(0), b(0), g(0), a(0),
|
||||
r(0), g(0), b(0), a(0),
|
||||
attachment(0),
|
||||
attachmentVerticesCapacity(0),
|
||||
attachmentVerticesCount(0),
|
||||
|
||||
@ -37,12 +37,16 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
SP_BLEND_MODE_NORMAL, SP_BLEND_MODE_ADDITIVE, SP_BLEND_MODE_MULTIPLY, SP_BLEND_MODE_SCREEN
|
||||
} spBlendMode;
|
||||
|
||||
typedef struct spSlotData {
|
||||
const char* const name;
|
||||
const spBoneData* const boneData;
|
||||
const char* attachmentName;
|
||||
float r, g, b, a;
|
||||
int/*bool*/additiveBlending;
|
||||
spBlendMode blendMode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
spSlotData() :
|
||||
@ -50,7 +54,7 @@ typedef struct spSlotData {
|
||||
boneData(0),
|
||||
attachmentName(0),
|
||||
r(0), g(0), b(0), a(0),
|
||||
additiveBlending(0) {
|
||||
blendMode(SP_BLEND_MODE_NORMAL) {
|
||||
}
|
||||
#endif
|
||||
} spSlotData;
|
||||
@ -62,6 +66,11 @@ void spSlotData_dispose (spSlotData* self);
|
||||
void spSlotData_setAttachmentName (spSlotData* self, const char* attachmentName);
|
||||
|
||||
#ifdef SPINE_SHORT_NAMES
|
||||
typedef spBlendMode BlendMode;
|
||||
#define BLEND_MODE_NORMAL SP_BLEND_MODE_NORMAL
|
||||
#define BLEND_MODE_ADDITIVE SP_BLEND_MODE_ADDITIVE
|
||||
#define BLEND_MODE_MULTIPLY SP_BLEND_MODE_MULTIPLY
|
||||
#define BLEND_MODE_SCREEN SP_BLEND_MODE_SCREEN
|
||||
typedef spSlotData SlotData;
|
||||
#define SlotData_create(...) spSlotData_create(__VA_ARGS__)
|
||||
#define SlotData_dispose(...) spSlotData_dispose(__VA_ARGS__)
|
||||
|
||||
@ -519,7 +519,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
||||
for (slotMap = slots->child, i = 0; slotMap; slotMap = slotMap->next, ++i) {
|
||||
spSlotData* slotData;
|
||||
const char* color;
|
||||
Json *attachmentItem;
|
||||
Json *item;
|
||||
|
||||
const char* boneName = Json_getString(slotMap, "bone", 0);
|
||||
spBoneData* boneData = spSkeletonData_findBone(skeletonData, boneName);
|
||||
@ -539,10 +539,18 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
||||
slotData->a = toColor(color, 3);
|
||||
}
|
||||
|
||||
attachmentItem = Json_getItem(slotMap, "attachment");
|
||||
if (attachmentItem) spSlotData_setAttachmentName(slotData, attachmentItem->valueString);
|
||||
item = Json_getItem(slotMap, "attachment");
|
||||
if (item) spSlotData_setAttachmentName(slotData, item->valueString);
|
||||
|
||||
slotData->additiveBlending = Json_getInt(slotMap, "additive", 0);
|
||||
item = Json_getItem(slotMap, "blend");
|
||||
if (item) {
|
||||
if (strcmp(item->valueString, "additive") == 0)
|
||||
slotData->blendMode = SP_BLEND_MODE_ADDITIVE;
|
||||
else if (strcmp(item->valueString, "multiply") == 0)
|
||||
slotData->blendMode = SP_BLEND_MODE_MULTIPLY;
|
||||
else if (strcmp(item->valueString, "screen") == 0)
|
||||
slotData->blendMode = SP_BLEND_MODE_SCREEN;
|
||||
}
|
||||
|
||||
skeletonData->slots[i] = slotData;
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
_skeleton->b = nodeColor.b / (float)255;
|
||||
_skeleton->a = self.opacity / (float)255;
|
||||
|
||||
int additive = -1;
|
||||
int blendMode = -1;
|
||||
ccColor4B color;
|
||||
const float* uvs = 0;
|
||||
int verticesCount = 0;
|
||||
@ -199,10 +199,22 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
default: ;
|
||||
}
|
||||
if (texture) {
|
||||
if (slot->data->additiveBlending != additive) {
|
||||
if (slot->data->blendMode != blendMode) {
|
||||
[batch flush];
|
||||
ccGLBlendFunc(_blendFunc.src, slot->data->additiveBlending ? GL_ONE : _blendFunc.dst);
|
||||
additive = slot->data->additiveBlending;
|
||||
blendMode = slot->data->blendMode;
|
||||
switch (slot->data->blendMode) {
|
||||
case SP_BLEND_MODE_ADDITIVE:
|
||||
ccGLBlendFunc(_premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE);
|
||||
break;
|
||||
case SP_BLEND_MODE_MULTIPLY:
|
||||
ccGLBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
|
||||
break;
|
||||
case SP_BLEND_MODE_SCREEN:
|
||||
ccGLBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
|
||||
break;
|
||||
default:
|
||||
ccGLBlendFunc(_premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
}
|
||||
color.a = _skeleton->a * slot->a * a * 255;
|
||||
float multiplier = _premultipliedAlpha ? color.a : 255;
|
||||
|
||||
@ -42,7 +42,8 @@
|
||||
CCDrawNode* _drawNode;
|
||||
bool _ownsSkeletonData;
|
||||
spAtlas* _atlas;
|
||||
float* worldVertices;
|
||||
float* _worldVertices;
|
||||
CCBlendMode* screenMode;
|
||||
}
|
||||
|
||||
+ (id) skeletonWithData:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData;
|
||||
|
||||
@ -62,7 +62,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
- (void) initialize:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData {
|
||||
_ownsSkeletonData = ownsSkeletonData;
|
||||
|
||||
worldVertices = MALLOC(float, 1000); // Max number of vertices per mesh.
|
||||
_worldVertices = MALLOC(float, 1000); // Max number of vertices per mesh.
|
||||
|
||||
_skeleton = spSkeleton_create(skeletonData);
|
||||
_rootBone = _skeleton->bones[0];
|
||||
@ -74,6 +74,12 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
[self addChild:_drawNode];
|
||||
|
||||
[self setShader:[CCShader positionTextureColorShader]];
|
||||
|
||||
_premultipliedAlpha = true;
|
||||
screenMode = [CCBlendMode blendModeWithOptions:@{
|
||||
CCBlendFuncSrcColor: @(GL_ONE),
|
||||
CCBlendFuncDstColor: @(GL_ONE_MINUS_SRC_COLOR)}
|
||||
];
|
||||
}
|
||||
|
||||
- (id) initWithData:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData {
|
||||
@ -127,7 +133,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
if (_ownsSkeletonData) spSkeletonData_dispose(_skeleton->data);
|
||||
if (_atlas) spAtlas_dispose(_atlas);
|
||||
spSkeleton_dispose(_skeleton);
|
||||
FREE(worldVertices);
|
||||
FREE(_worldVertices);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@ -138,7 +144,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
_skeleton->b = nodeColor.blue;
|
||||
_skeleton->a = self.displayedOpacity;
|
||||
|
||||
int additive = -1;
|
||||
int blendMode = -1;
|
||||
const float* uvs = 0;
|
||||
int verticesCount = 0;
|
||||
const int* triangles = 0;
|
||||
@ -151,7 +157,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
switch (slot->attachment->type) {
|
||||
case SP_ATTACHMENT_REGION: {
|
||||
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
||||
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
|
||||
spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices);
|
||||
texture = [self getTextureForRegion:attachment];
|
||||
uvs = attachment->uvs;
|
||||
verticesCount = 8;
|
||||
@ -165,7 +171,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
}
|
||||
case SP_ATTACHMENT_MESH: {
|
||||
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
|
||||
spMeshAttachment_computeWorldVertices(attachment, slot, worldVertices);
|
||||
spMeshAttachment_computeWorldVertices(attachment, slot, _worldVertices);
|
||||
texture = [self getTextureForMesh:attachment];
|
||||
uvs = attachment->uvs;
|
||||
verticesCount = attachment->verticesCount;
|
||||
@ -179,7 +185,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
}
|
||||
case SP_ATTACHMENT_SKINNED_MESH: {
|
||||
spSkinnedMeshAttachment* attachment = (spSkinnedMeshAttachment*)slot->attachment;
|
||||
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot, worldVertices);
|
||||
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot, _worldVertices);
|
||||
texture = [self getTextureForSkinnedMesh:attachment];
|
||||
uvs = attachment->uvs;
|
||||
verticesCount = attachment->uvsCount;
|
||||
@ -194,9 +200,21 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
default: ;
|
||||
}
|
||||
if (texture) {
|
||||
if (slot->data->additiveBlending != additive) {
|
||||
[self setBlendMode:[CCBlendMode blendModeWithOptions:@{CCBlendFuncSrcColor: @(_blendFunc.src),CCBlendFuncDstColor: @(slot->data->additiveBlending ? GL_ONE : _blendFunc.dst)}]];
|
||||
additive = slot->data->additiveBlending;
|
||||
if (slot->data->blendMode != blendMode) {
|
||||
blendMode = slot->data->blendMode;
|
||||
switch (slot->data->blendMode) {
|
||||
case SP_BLEND_MODE_ADDITIVE:
|
||||
[self setBlendMode:[CCBlendMode addMode]];
|
||||
break;
|
||||
case SP_BLEND_MODE_MULTIPLY:
|
||||
[self setBlendMode:[CCBlendMode multiplyMode]];
|
||||
break;
|
||||
case SP_BLEND_MODE_SCREEN:
|
||||
[self setBlendMode:screenMode];
|
||||
break;
|
||||
default:
|
||||
[self setBlendMode:_premultipliedAlpha ? [CCBlendMode premultipliedAlphaMode] : [CCBlendMode alphaMode]];
|
||||
}
|
||||
}
|
||||
if (_premultipliedAlpha) {
|
||||
a *= _skeleton->a * slot->a;
|
||||
@ -217,7 +235,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
CCRenderBuffer buffer = [renderer enqueueTriangles:(trianglesCount / 3) andVertexes:verticesCount withState:self.renderState globalSortOrder:0];
|
||||
for (int i = 0; i * 2 < verticesCount; ++i) {
|
||||
CCVertex vertex;
|
||||
vertex.position = GLKVector4Make(worldVertices[i * 2], worldVertices[i * 2 + 1], 0.0, 1.0);
|
||||
vertex.position = GLKVector4Make(_worldVertices[i * 2], _worldVertices[i * 2 + 1], 0.0, 1.0);
|
||||
vertex.color = GLKVector4Make(r, g, b, a);
|
||||
vertex.texCoord1 = GLKVector2Make(uvs[i * 2], 1 - uvs[i * 2 + 1]);
|
||||
CCRenderBufferSetVertex(buffer, i, CCVertexApplyTransform(vertex, transform));
|
||||
@ -236,11 +254,11 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
spSlot* slot = _skeleton->drawOrder[i];
|
||||
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
|
||||
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
||||
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
|
||||
points[0] = ccp(worldVertices[0], worldVertices[1]);
|
||||
points[1] = ccp(worldVertices[2], worldVertices[3]);
|
||||
points[2] = ccp(worldVertices[4], worldVertices[5]);
|
||||
points[3] = ccp(worldVertices[6], worldVertices[7]);
|
||||
spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices);
|
||||
points[0] = ccp(_worldVertices[0], _worldVertices[1]);
|
||||
points[1] = ccp(_worldVertices[2], _worldVertices[3]);
|
||||
points[2] = ccp(_worldVertices[4], _worldVertices[5]);
|
||||
points[3] = ccp(_worldVertices[6], _worldVertices[7]);
|
||||
[_drawNode drawPolyWithVerts:points count:4 fillColor:[CCColor clearColor] borderWidth:1 borderColor:[CCColor blueColor]];
|
||||
}
|
||||
}
|
||||
@ -283,20 +301,20 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
||||
int verticesCount;
|
||||
if (slot->attachment->type == SP_ATTACHMENT_REGION) {
|
||||
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
||||
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
|
||||
spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices);
|
||||
verticesCount = 8;
|
||||
} else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
|
||||
spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
|
||||
spMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
|
||||
spMeshAttachment_computeWorldVertices(mesh, slot, _worldVertices);
|
||||
verticesCount = mesh->verticesCount;
|
||||
} else if (slot->attachment->type == SP_ATTACHMENT_SKINNED_MESH) {
|
||||
spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*)slot->attachment;
|
||||
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
|
||||
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot, _worldVertices);
|
||||
verticesCount = mesh->uvsCount;
|
||||
} else
|
||||
continue;
|
||||
for (int ii = 0; ii < verticesCount; ii += 2) {
|
||||
float x = worldVertices[ii] * scaleX, y = worldVertices[ii + 1] * scaleY;
|
||||
float x = _worldVertices[ii] * scaleX, y = _worldVertices[ii + 1] * scaleY;
|
||||
minX = fmin(minX, x);
|
||||
minY = fmin(minY, y);
|
||||
maxX = fmax(maxX, x);
|
||||
|
||||
@ -144,7 +144,7 @@ void SkeletonRenderer::draw () {
|
||||
skeleton->b = nodeColor.b / (float)255;
|
||||
skeleton->a = getDisplayedOpacity() / (float)255;
|
||||
|
||||
int additive = -1;
|
||||
int blendMode = -1;
|
||||
ccColor4B color;
|
||||
const float* uvs = nullptr;
|
||||
int verticesCount = 0;
|
||||
@ -200,10 +200,22 @@ void SkeletonRenderer::draw () {
|
||||
}
|
||||
}
|
||||
if (texture) {
|
||||
if (slot->data->additiveBlending != additive) {
|
||||
if (slot->data->blendMode != blendMode) {
|
||||
batch->flush();
|
||||
ccGLBlendFunc(blendFunc.src, slot->data->additiveBlending ? GL_ONE : blendFunc.dst);
|
||||
additive = slot->data->additiveBlending;
|
||||
blendMode = slot->data->blendMode;
|
||||
switch (slot->data->blendMode) {
|
||||
case SP_BLEND_MODE_ADDITIVE:
|
||||
ccGLBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE);
|
||||
break;
|
||||
case SP_BLEND_MODE_MULTIPLY:
|
||||
ccGLBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
|
||||
break;
|
||||
case SP_BLEND_MODE_SCREEN:
|
||||
ccGLBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
|
||||
break;
|
||||
default:
|
||||
ccGLBlendFunc(blendFunc.src, blendFunc.dst);
|
||||
}
|
||||
}
|
||||
color.a = skeleton->a * slot->a * a * 255;
|
||||
float multiplier = premultipliedAlpha ? color.a : 255;
|
||||
|
||||
@ -158,7 +158,7 @@ void SkeletonRenderer::drawSkeleton (const Mat4 &transform, uint32_t transformFl
|
||||
_skeleton->b = nodeColor.b / (float)255;
|
||||
_skeleton->a = getDisplayedOpacity() / (float)255;
|
||||
|
||||
int additive = -1;
|
||||
int blendMode = -1;
|
||||
Color4B color;
|
||||
const float* uvs = nullptr;
|
||||
int verticesCount = 0;
|
||||
@ -215,10 +215,22 @@ void SkeletonRenderer::drawSkeleton (const Mat4 &transform, uint32_t transformFl
|
||||
default: ;
|
||||
}
|
||||
if (texture) {
|
||||
if (slot->data->additiveBlending != additive) {
|
||||
if (slot->data->blendMode != blendMode) {
|
||||
_batch->flush();
|
||||
GL::blendFunc(_blendFunc.src, slot->data->additiveBlending ? GL_ONE : _blendFunc.dst);
|
||||
additive = slot->data->additiveBlending;
|
||||
blendMode = slot->data->blendMode;
|
||||
switch (slot->data->blendMode) {
|
||||
case SP_BLEND_MODE_ADDITIVE:
|
||||
GL::blendFunc(_premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE);
|
||||
break;
|
||||
case SP_BLEND_MODE_MULTIPLY:
|
||||
GL::blendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
|
||||
break;
|
||||
case SP_BLEND_MODE_SCREEN:
|
||||
GL::blendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
|
||||
break;
|
||||
default:
|
||||
GL::blendFunc(_blendFunc.src, _blendFunc.dst);
|
||||
}
|
||||
}
|
||||
color.a = _skeleton->a * slot->a * a * 255;
|
||||
float multiplier = _premultipliedAlpha ? color.a : 255;
|
||||
|
||||
@ -52,6 +52,7 @@ spine.AnimationState = require "spine-lua.AnimationState"
|
||||
spine.EventData = require "spine-lua.EventData"
|
||||
spine.Event = require "spine-lua.Event"
|
||||
spine.SkeletonBounds = require "spine-lua.SkeletonBounds"
|
||||
spine.BlendMode = require "spine-lua.BlendMode"
|
||||
|
||||
spine.utils.readFile = function (fileName, base)
|
||||
if not base then base = system.ResourceDirectory end
|
||||
@ -125,7 +126,15 @@ function spine.Skeleton.new (skeletonData, group)
|
||||
print("Error creating image: " .. attachment.name)
|
||||
image = spine.Skeleton.failed
|
||||
end
|
||||
if slot.data.additiveBlending then image.blendMode = "add" end
|
||||
if slot.data.blendMode == spine.BlendMode.normal then
|
||||
image.blendMode = "normal"
|
||||
elseif slot.data.blendMode == spine.BlendMode.additive then
|
||||
image.blendMode = "add"
|
||||
elseif slot.data.blendMode == spine.BlendMode.multiply then
|
||||
image.blendMode = "multiply"
|
||||
elseif slot.data.blendMode == spine.BlendMode.screen then
|
||||
image.blendMode = "screen"
|
||||
end
|
||||
images[slot] = image
|
||||
end
|
||||
-- Position image based on attachment and bone.
|
||||
|
||||
@ -64,6 +64,7 @@
|
||||
<Compile Include="src\Attachments\MeshAttachment.cs" />
|
||||
<Compile Include="src\Attachments\RegionAttachment.cs" />
|
||||
<Compile Include="src\Attachments\SkinnedMeshAttachment.cs" />
|
||||
<Compile Include="src\BlendMode.cs" />
|
||||
<Compile Include="src\Bone.cs" />
|
||||
<Compile Include="src\BoneData.cs" />
|
||||
<Compile Include="src\AnimationState.cs" />
|
||||
|
||||
@ -103,6 +103,7 @@
|
||||
<Compile Include="src\Attachments\AttachmentType.cs" />
|
||||
<Compile Include="src\Attachments\BoundingBoxAttachment.cs" />
|
||||
<Compile Include="src\Attachments\RegionAttachment.cs" />
|
||||
<Compile Include="src\BlendMode.cs" />
|
||||
<Compile Include="src\Bone.cs" />
|
||||
<Compile Include="src\BoneData.cs" />
|
||||
<Compile Include="src\IkConstraint.cs" />
|
||||
|
||||
35
spine-csharp/src/BlendMode.cs
Normal file
35
spine-csharp/src/BlendMode.cs
Normal file
@ -0,0 +1,35 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License
|
||||
* Version 2.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
* non-transferable license to install, execute and perform the Spine Runtimes
|
||||
* Software (the "Software") solely for internal use. Without the written
|
||||
* permission of Esoteric Software (typically granted by licensing Spine), you
|
||||
* may not (a) modify, translate, adapt or otherwise create derivative works,
|
||||
* improvements of the Software or develop new applications using the Software
|
||||
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
|
||||
* trademark, patent or other intellectual property or proprietary rights
|
||||
* notices on or in the Software, including any copy thereof. Redistributions
|
||||
* in binary or source form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
namespace Spine {
|
||||
public enum BlendMode {
|
||||
normal, additive, multiply, screen
|
||||
}
|
||||
}
|
||||
@ -156,7 +156,7 @@ namespace Spine {
|
||||
slotData.b = ((color & 0x0000ff00) >> 8) / 255f;
|
||||
slotData.a = ((color & 0x000000ff)) / 255f;
|
||||
slotData.attachmentName = ReadString(input);
|
||||
slotData.additiveBlending = ReadBoolean(input);
|
||||
slotData.blendMode = (BlendMode)ReadInt(input, true);
|
||||
skeletonData.slots.Add(slotData);
|
||||
}
|
||||
|
||||
|
||||
@ -163,8 +163,10 @@ namespace Spine {
|
||||
if (slotMap.ContainsKey("attachment"))
|
||||
slotData.attachmentName = (String)slotMap["attachment"];
|
||||
|
||||
if (slotMap.ContainsKey("additive"))
|
||||
slotData.additiveBlending = (bool)slotMap["additive"];
|
||||
if (slotMap.ContainsKey("blend"))
|
||||
slotData.blendMode = (BlendMode)Enum.Parse(typeof(BlendMode), (String)slotMap["blend"], false);
|
||||
else
|
||||
slotData.blendMode = BlendMode.normal;
|
||||
|
||||
skeletonData.slots.Add(slotData);
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ namespace Spine {
|
||||
internal BoneData boneData;
|
||||
internal float r = 1, g = 1, b = 1, a = 1;
|
||||
internal String attachmentName;
|
||||
internal bool additiveBlending;
|
||||
internal BlendMode blendMode;
|
||||
|
||||
public String Name { get { return name; } }
|
||||
public BoneData BoneData { get { return boneData; } }
|
||||
@ -46,7 +46,7 @@ namespace Spine {
|
||||
public float A { get { return a; } set { a = value; } }
|
||||
/// <summary>May be null.</summary>
|
||||
public String AttachmentName { get { return attachmentName; } set { attachmentName = value; } }
|
||||
public bool AdditiveBlending { get { return additiveBlending; } set { additiveBlending = value; } }
|
||||
public BlendMode BlendMode { get { return blendMode; } set { blendMode = value; } }
|
||||
|
||||
public SlotData (String name, BoneData boneData) {
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null.");
|
||||
|
||||
@ -50,6 +50,13 @@ spine.BoneData.prototype = {
|
||||
flipX: false, flipY: false
|
||||
};
|
||||
|
||||
spine.BlendMode = {
|
||||
normal: 0,
|
||||
additive: 1,
|
||||
multiply: 2,
|
||||
screen: 3
|
||||
};
|
||||
|
||||
spine.SlotData = function (name, boneData) {
|
||||
this.name = name;
|
||||
this.boneData = boneData;
|
||||
@ -57,7 +64,7 @@ spine.SlotData = function (name, boneData) {
|
||||
spine.SlotData.prototype = {
|
||||
r: 1, g: 1, b: 1, a: 1,
|
||||
attachmentName: null,
|
||||
additiveBlending: false
|
||||
blendMode: spine.BlendMode.normal
|
||||
};
|
||||
|
||||
spine.IkConstraintData = function (name) {
|
||||
@ -1766,7 +1773,7 @@ spine.SkeletonJson.prototype = {
|
||||
}
|
||||
|
||||
slotData.attachmentName = slotMap["attachment"];
|
||||
slotData.additiveBlending = slotMap["additive"] && slotMap["additive"] == "true";
|
||||
slotData.blendMode = spine.AttachmentType[slotMap["blend"] || "normal"];
|
||||
|
||||
skeletonData.slots.push(slotData);
|
||||
}
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
|
||||
package com.esotericsoftware.spine;
|
||||
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
|
||||
public enum BlendMode {
|
||||
normal(GL20.GL_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA), //
|
||||
additive(GL20.GL_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE), //
|
||||
multiply(GL20.GL_DST_COLOR, GL20.GL_DST_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA), //
|
||||
screen(GL20.GL_ONE, GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_COLOR), //
|
||||
;
|
||||
|
||||
int source, sourcePMA, dest;
|
||||
|
||||
BlendMode (int source, int sourcePremultipledAlpha, int dest) {
|
||||
this.source = source;
|
||||
this.sourcePMA = sourcePremultipledAlpha;
|
||||
this.dest = dest;
|
||||
}
|
||||
|
||||
public int getSource (boolean premultipliedAlpha) {
|
||||
return premultipliedAlpha ? sourcePMA : source;
|
||||
}
|
||||
|
||||
public int getDest () {
|
||||
return dest;
|
||||
}
|
||||
|
||||
static public BlendMode[] values = values();
|
||||
}
|
||||
@ -160,7 +160,7 @@ public class SkeletonBinary {
|
||||
SlotData slotData = new SlotData(slotName, boneData);
|
||||
Color.rgba8888ToColor(slotData.color, input.readInt());
|
||||
slotData.attachmentName = input.readString();
|
||||
slotData.additiveBlending = input.readBoolean();
|
||||
slotData.blendMode = BlendMode.values[input.readInt(true)];
|
||||
skeletonData.slots.add(slotData);
|
||||
}
|
||||
|
||||
@ -227,7 +227,7 @@ public class SkeletonBinary {
|
||||
String name = input.readString();
|
||||
if (name == null) name = attachmentName;
|
||||
|
||||
switch (AttachmentType.values()[input.readByte()]) {
|
||||
switch (AttachmentType.values[input.readByte()]) {
|
||||
case region: {
|
||||
String path = input.readString();
|
||||
if (path == null) path = name;
|
||||
|
||||
@ -161,9 +161,7 @@ public class SkeletonJson {
|
||||
if (color != null) slotData.getColor().set(Color.valueOf(color));
|
||||
|
||||
slotData.attachmentName = slotMap.getString("attachment", null);
|
||||
|
||||
slotData.additiveBlending = slotMap.getBoolean("additive", false);
|
||||
|
||||
slotData.blendMode = BlendMode.valueOf(slotMap.getString("blend", BlendMode.normal.name()));
|
||||
skeletonData.slots.add(slotData);
|
||||
}
|
||||
|
||||
|
||||
@ -30,18 +30,16 @@
|
||||
|
||||
package com.esotericsoftware.spine;
|
||||
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.esotericsoftware.spine.attachments.Attachment;
|
||||
import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||
import com.esotericsoftware.spine.attachments.SkeletonAttachment;
|
||||
import com.esotericsoftware.spine.attachments.SkinnedMeshAttachment;
|
||||
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
public class SkeletonRenderer {
|
||||
static private final short[] quadTriangles = {0, 1, 2, 2, 3, 0};
|
||||
|
||||
@ -50,10 +48,7 @@ public class SkeletonRenderer {
|
||||
@SuppressWarnings("null")
|
||||
public void draw (PolygonSpriteBatch batch, Skeleton skeleton) {
|
||||
boolean premultipliedAlpha = this.premultipliedAlpha;
|
||||
int srcFunc = premultipliedAlpha ? GL20.GL_ONE : GL20.GL_SRC_ALPHA;
|
||||
batch.setBlendFunction(srcFunc, GL20.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
boolean additive = false;
|
||||
BlendMode blendMode = null;
|
||||
|
||||
float[] vertices = null;
|
||||
short[] triangles = null;
|
||||
@ -106,12 +101,10 @@ public class SkeletonRenderer {
|
||||
}
|
||||
|
||||
if (texture != null) {
|
||||
if (slot.data.getAdditiveBlending() != additive) {
|
||||
additive = !additive;
|
||||
if (additive)
|
||||
batch.setBlendFunction(srcFunc, GL20.GL_ONE);
|
||||
else
|
||||
batch.setBlendFunction(srcFunc, GL20.GL_ONE_MINUS_SRC_ALPHA);
|
||||
BlendMode slotBlendMode = slot.data.getBlendMode();
|
||||
if (slotBlendMode != blendMode) {
|
||||
blendMode = slotBlendMode;
|
||||
batch.setBlendFunction(blendMode.getSource(premultipliedAlpha), blendMode.getDest());
|
||||
}
|
||||
batch.draw(texture, vertices, 0, vertices.length, triangles, 0, triangles.length);
|
||||
}
|
||||
@ -120,10 +113,7 @@ public class SkeletonRenderer {
|
||||
|
||||
public void draw (Batch batch, Skeleton skeleton) {
|
||||
boolean premultipliedAlpha = this.premultipliedAlpha;
|
||||
int srcFunc = premultipliedAlpha ? GL20.GL_ONE : GL20.GL_SRC_ALPHA;
|
||||
batch.setBlendFunction(srcFunc, GL20.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
boolean additive = false;
|
||||
BlendMode blendMode = null;
|
||||
|
||||
Array<Slot> drawOrder = skeleton.drawOrder;
|
||||
for (int i = 0, n = drawOrder.size; i < n; i++) {
|
||||
@ -133,12 +123,10 @@ public class SkeletonRenderer {
|
||||
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
||||
regionAttachment.updateWorldVertices(slot, premultipliedAlpha);
|
||||
float[] vertices = regionAttachment.getWorldVertices();
|
||||
if (slot.data.getAdditiveBlending() != additive) {
|
||||
additive = !additive;
|
||||
if (additive)
|
||||
batch.setBlendFunction(srcFunc, GL20.GL_ONE);
|
||||
else
|
||||
batch.setBlendFunction(srcFunc, GL20.GL_ONE_MINUS_SRC_ALPHA);
|
||||
BlendMode slotBlendMode = slot.data.getBlendMode();
|
||||
if (slotBlendMode != blendMode) {
|
||||
blendMode = slotBlendMode;
|
||||
batch.setBlendFunction(blendMode.getSource(premultipliedAlpha), blendMode.getDest());
|
||||
}
|
||||
batch.draw(regionAttachment.getRegion().getTexture(), vertices, 0, 20);
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ public class SlotData {
|
||||
final BoneData boneData;
|
||||
final Color color = new Color(1, 1, 1, 1);
|
||||
String attachmentName;
|
||||
boolean additiveBlending;
|
||||
BlendMode blendMode;
|
||||
|
||||
SlotData () {
|
||||
name = null;
|
||||
@ -73,12 +73,12 @@ public class SlotData {
|
||||
return attachmentName;
|
||||
}
|
||||
|
||||
public boolean getAdditiveBlending () {
|
||||
return additiveBlending;
|
||||
public BlendMode getBlendMode () {
|
||||
return blendMode;
|
||||
}
|
||||
|
||||
public void setAdditiveBlending (boolean additiveBlending) {
|
||||
this.additiveBlending = additiveBlending;
|
||||
public void setBlendMode (BlendMode blendMode) {
|
||||
this.blendMode = blendMode;
|
||||
}
|
||||
|
||||
public String toString () {
|
||||
|
||||
@ -31,5 +31,7 @@
|
||||
package com.esotericsoftware.spine.attachments;
|
||||
|
||||
public enum AttachmentType {
|
||||
region, boundingbox, mesh, skinnedmesh
|
||||
region, boundingbox, mesh, skinnedmesh;
|
||||
|
||||
static public AttachmentType[] values = values();
|
||||
}
|
||||
|
||||
@ -52,6 +52,7 @@ spine.AnimationState = require "spine-lua.AnimationState"
|
||||
spine.EventData = require "spine-lua.EventData"
|
||||
spine.Event = require "spine-lua.Event"
|
||||
spine.SkeletonBounds = require "spine-lua.SkeletonBounds"
|
||||
spine.BlendMode = require "spine-lua.BlendMode"
|
||||
|
||||
spine.utils.readFile = function (fileName, base)
|
||||
local path = fileName
|
||||
@ -139,10 +140,14 @@ function spine.Skeleton.new (skeletonData, group)
|
||||
rotation = -rotation
|
||||
end
|
||||
love.graphics.setColor(r * slot.r, g * slot.g, b * slot.b, a * slot.a)
|
||||
if slot.data.additiveBlending then
|
||||
love.graphics.setBlendMode("additive")
|
||||
else
|
||||
if slot.data.blendMode == spine.BlendMode.normal then
|
||||
love.graphics.setBlendMode("alpha")
|
||||
elseif slot.data.blendMode == spine.BlendMode.additive then
|
||||
love.graphics.setBlendMode("additive")
|
||||
elseif slot.data.blendMode == spine.BlendMode.multiply then
|
||||
love.graphics.setBlendMode("multiply")
|
||||
elseif slot.data.blendMode == spine.BlendMode.screen then
|
||||
love.graphics.setBlendMode("screen")
|
||||
end
|
||||
love.graphics.draw(image,
|
||||
self.x + x,
|
||||
|
||||
37
spine-lua/BlendMode.lua
Normal file
37
spine-lua/BlendMode.lua
Normal file
@ -0,0 +1,37 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- Spine Runtimes Software License
|
||||
-- Version 2.1
|
||||
--
|
||||
-- Copyright (c) 2013, Esoteric Software
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
-- non-transferable license to install, execute and perform the Spine Runtimes
|
||||
-- Software (the "Software") solely for internal use. Without the written
|
||||
-- permission of Esoteric Software (typically granted by licensing Spine), you
|
||||
-- may not (a) modify, translate, adapt or otherwise create derivative works,
|
||||
-- improvements of the Software or develop new applications using the Software
|
||||
-- or (b) remove, delete, alter or obscure any trademarks or any copyright,
|
||||
-- trademark, patent or other intellectual property or proprietary rights
|
||||
-- notices on or in the Software, including any copy thereof. Redistributions
|
||||
-- in binary or source form must include this license and terms.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
-- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
-- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
-- EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
-- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
-- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
-- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local BlendMode = {
|
||||
normal = 0,
|
||||
additive = 1,
|
||||
multiply = 2,
|
||||
screen = 3
|
||||
}
|
||||
return BlendMode
|
||||
@ -39,6 +39,7 @@ local IkConstraint = require "spine-lua.IkConstraint"
|
||||
local EventData = require "spine-lua.EventData"
|
||||
local Event = require "spine-lua.Event"
|
||||
local AttachmentType = require "spine-lua.AttachmentType"
|
||||
local BlendMode = require "spine-lua.BlendMode"
|
||||
|
||||
local SkeletonJson = {}
|
||||
function SkeletonJson.new (attachmentLoader)
|
||||
@ -154,7 +155,7 @@ function SkeletonJson.new (attachmentLoader)
|
||||
end
|
||||
|
||||
slotData.attachmentName = slotMap["attachment"]
|
||||
slotData.additiveBlending = slotMap["additive"]
|
||||
slotData.blendMode = BlendMode[slotMap["blend"] or "normal"]
|
||||
|
||||
table.insert(skeletonData.slots, slotData)
|
||||
skeletonData.slotNameIndices[slotData.name] = #skeletonData.slots
|
||||
|
||||
@ -28,6 +28,8 @@
|
||||
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local BlendMode = require "spine-lua.BlendMode"
|
||||
|
||||
local SlotData = {}
|
||||
function SlotData.new (name, boneData)
|
||||
if not name then error("name cannot be nil", 2) end
|
||||
@ -38,7 +40,7 @@ function SlotData.new (name, boneData)
|
||||
boneData = boneData,
|
||||
r = 1, g = 1, b = 1, a = 1,
|
||||
attachmentName = nil,
|
||||
additiveBlending = false
|
||||
blendMode = BlendMode.normal
|
||||
}
|
||||
|
||||
function self:setColor (r, g, b, a)
|
||||
|
||||
@ -95,7 +95,6 @@ void SkeletonDrawable::update (float deltaTime) {
|
||||
|
||||
void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
|
||||
vertexArray->clear();
|
||||
states.blendMode = BlendAlpha;
|
||||
|
||||
sf::Vertex vertices[4];
|
||||
sf::Vertex vertex;
|
||||
@ -103,6 +102,25 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
|
||||
Slot* slot = skeleton->drawOrder[i];
|
||||
Attachment* attachment = slot->attachment;
|
||||
if (!attachment) continue;
|
||||
|
||||
sf::BlendMode blend;
|
||||
switch (slot->data->blendMode) {
|
||||
case BLEND_MODE_ADDITIVE:
|
||||
blend = BlendAdd;
|
||||
break;
|
||||
case BLEND_MODE_MULTIPLY:
|
||||
blend = BlendMultiply;
|
||||
break;
|
||||
case BLEND_MODE_SCREEN: // Unsupported, fall through.
|
||||
default:
|
||||
blend = BlendAlpha;
|
||||
}
|
||||
if (states.blendMode != blend) {
|
||||
target.draw(*vertexArray, states);
|
||||
vertexArray->clear();
|
||||
states.blendMode = blend;
|
||||
}
|
||||
|
||||
Texture* texture = 0;
|
||||
if (attachment->type == ATTACHMENT_REGION) {
|
||||
RegionAttachment* regionAttachment = (RegionAttachment*)attachment;
|
||||
@ -212,13 +230,6 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
|
||||
if (texture) {
|
||||
// SMFL doesn't handle batching for us, so we'll just force a single texture per skeleton.
|
||||
states.texture = texture;
|
||||
|
||||
BlendMode blend = slot->data->additiveBlending ? BlendAdd : BlendAlpha;
|
||||
if (states.blendMode != blend) {
|
||||
target.draw(*vertexArray, states);
|
||||
vertexArray->clear();
|
||||
states.blendMode = blend;
|
||||
}
|
||||
}
|
||||
}
|
||||
target.draw(*vertexArray, states);
|
||||
|
||||
@ -41,6 +41,9 @@ import flash.geom.Matrix;
|
||||
import flash.geom.Point;
|
||||
import flash.utils.Dictionary;
|
||||
|
||||
import spine.BlendMode;
|
||||
import spine.flash.SkeletonSprite;
|
||||
|
||||
import starling.core.RenderSupport;
|
||||
import starling.core.Starling;
|
||||
import starling.display.BlendMode;
|
||||
@ -61,8 +64,8 @@ internal class PolygonBatch {
|
||||
private var _texture:Texture;
|
||||
private var _support:RenderSupport;
|
||||
private var _programBits:uint;
|
||||
private var _blendMode:String;
|
||||
private var _additive:Boolean;
|
||||
private var _blendModeNormal:String;
|
||||
private var _blendMode:spine.BlendMode;
|
||||
private var _alpha:Number;
|
||||
|
||||
private var _verticesCount:int;
|
||||
@ -88,11 +91,11 @@ internal class PolygonBatch {
|
||||
_support = support;
|
||||
_alpha = alpha;
|
||||
_programBits = 0xffffffff;
|
||||
_additive = false;
|
||||
_blendMode = null;
|
||||
|
||||
support.finishQuadBatch();
|
||||
support.blendMode = blendMode;
|
||||
_blendMode = support.blendMode;
|
||||
_blendModeNormal = support.blendMode;
|
||||
|
||||
var context:Context3D = Starling.context;
|
||||
context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 1, support.mvpMatrix3D, true);
|
||||
@ -115,11 +118,14 @@ internal class PolygonBatch {
|
||||
}
|
||||
|
||||
public function add (texture:Texture, vertices:Vector.<Number>, vl:int, uvs:Vector.<Number>, triangles:Vector.<uint>,
|
||||
r:Number, g:Number, b:Number, a:Number, additive:Boolean, matrix:Matrix) : void {
|
||||
if (additive != _additive) {
|
||||
_additive = additive;
|
||||
r:Number, g:Number, b:Number, a:Number, blendMode:spine.BlendMode, matrix:Matrix) : void {
|
||||
if (blendMode != _blendMode) {
|
||||
_blendMode = blendMode;
|
||||
flush();
|
||||
_support.blendMode = additive ? BlendMode.ADD : _blendMode;
|
||||
if (blendMode == spine.BlendMode.normal)
|
||||
_support.blendMode = _blendModeNormal;
|
||||
else
|
||||
_support.blendMode = spine.starling.SkeletonSprite.blendModes[blendMode.ordinal];
|
||||
_support.applyBlendMode(true);
|
||||
}
|
||||
|
||||
|
||||
@ -58,6 +58,8 @@ public class SkeletonSprite extends DisplayObject {
|
||||
static private var _tempMatrix:Matrix = new Matrix();
|
||||
static private var _tempVertices:Vector.<Number> = new Vector.<Number>(8);
|
||||
static private var _quadTriangles:Vector.<uint> = new <uint>[0, 1, 2, 2, 3, 0];
|
||||
static internal var blendModes:Vector.<String> = new <String>[
|
||||
BlendMode.NORMAL, BlendMode.ADD, BlendMode.MULTIPLY, BlendMode.SCREEN];
|
||||
|
||||
private var _skeleton:Skeleton;
|
||||
private var _polygonBatch:PolygonBatch;
|
||||
@ -165,7 +167,7 @@ public class SkeletonSprite extends DisplayObject {
|
||||
r *= skeletonR * slot.r * a;
|
||||
g *= skeletonG * slot.g * a;
|
||||
b *= skeletonB * slot.b * a;
|
||||
polygonBatch.add(image.texture, worldVertices, verticesLength, uvs, triangles, r, g, b, a, slot.data.additiveBlending, matrix);
|
||||
polygonBatch.add(image.texture, worldVertices, verticesLength, uvs, triangles, r, g, b, a, slot.data.blendMode, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -206,7 +208,7 @@ public class SkeletonSprite extends DisplayObject {
|
||||
vertexData.setColorAndAlpha(3, rgb, a);
|
||||
|
||||
image.updateVertices();
|
||||
support.blendMode = slot.data.additiveBlending ? BlendMode.ADD : blendMode;
|
||||
support.blendMode = blendModes[slot.data.blendMode.ordinal];
|
||||
support.batchQuad(image, alpha, image.texture, _smoothing);
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +191,7 @@ function drawSkeleton (batch, skeleton) {
|
||||
if (!(attachment instanceof spine.RegionAttachment)) continue;
|
||||
attachment.computeVertices(skeleton.x, skeleton.y, slot.bone, vertices);
|
||||
|
||||
var blendMode = slot.data.additiveBlending ? draw2D.blend.additive : draw2D.blend.alpha;
|
||||
var blendMode = slot.data.blendMode == spine.BlendMode.additive ? draw2D.blend.additive : draw2D.blend.alpha;
|
||||
if (batch.blendMode != blendMode) {
|
||||
batch.end();
|
||||
batch.begin(blendMode);
|
||||
|
||||
@ -283,8 +283,7 @@ public class SkeletonRenderer : MonoBehaviour {
|
||||
color.r = (byte)(r * slot.r * regionAttachment.r * color.a);
|
||||
color.g = (byte)(g * slot.g * regionAttachment.g * color.a);
|
||||
color.b = (byte)(b * slot.b * regionAttachment.b * color.a);
|
||||
if (slot.data.additiveBlending)
|
||||
color.a = 0;
|
||||
if (slot.data.blendMode == BlendMode.additive) color.a = 0;
|
||||
colors[vertexIndex] = color;
|
||||
colors[vertexIndex + 1] = color;
|
||||
colors[vertexIndex + 2] = color;
|
||||
@ -311,8 +310,7 @@ public class SkeletonRenderer : MonoBehaviour {
|
||||
color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
|
||||
color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
|
||||
color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
|
||||
if (slot.data.additiveBlending)
|
||||
color.a = 0;
|
||||
if (slot.data.blendMode == BlendMode.additive) color.a = 0;
|
||||
|
||||
float[] meshUVs = meshAttachment.uvs;
|
||||
float z = i * zSpacing;
|
||||
@ -332,8 +330,7 @@ public class SkeletonRenderer : MonoBehaviour {
|
||||
color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
|
||||
color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
|
||||
color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
|
||||
if (slot.data.additiveBlending)
|
||||
color.a = 0;
|
||||
if (slot.data.blendMode == BlendMode.additive) color.a = 0;
|
||||
|
||||
float[] meshUVs = meshAttachment.uvs;
|
||||
float z = i * zSpacing;
|
||||
|
||||
@ -96,7 +96,7 @@ namespace Spine {
|
||||
Attachment attachment = slot.Attachment;
|
||||
if (attachment is RegionAttachment) {
|
||||
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
||||
BlendState blend = slot.Data.AdditiveBlending ? BlendState.Additive : defaultBlendState;
|
||||
BlendState blend = slot.Data.BlendMode == BlendMode.additive ? BlendState.Additive : defaultBlendState;
|
||||
if (device.BlendState != blend) {
|
||||
End();
|
||||
device.BlendState = blend;
|
||||
|
||||
@ -88,7 +88,7 @@ namespace Spine {
|
||||
Slot slot = drawOrder[i];
|
||||
RegionAttachment regionAttachment = slot.Attachment as RegionAttachment;
|
||||
if (regionAttachment != null) {
|
||||
BlendState blend = slot.Data.AdditiveBlending ? BlendState.Additive : defaultBlendState;
|
||||
BlendState blend = slot.Data.BlendMode == BlendMode.additive ? BlendState.Additive : defaultBlendState;
|
||||
if (device.BlendState != blend) {
|
||||
End();
|
||||
device.BlendState = blend;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user