这是一个有点奇葩的项目需求,大概率没有人会这么玩。
需求布景
在spine中有一个插槽隐藏了,也就是下边的copy
导出的spine纹路中是带着这个copy纹路的
项目需求
希望动态的将copy纹路
替换原图对应的插槽纹路
这样也有好处,由于替换纹路都在一张图里面,drawcall不会发生变化
可是copy纹路发生了旋转,所以需要对SpriteFrame的极点uv数据处理下
换图后发现图的纹路旋转反常,图被旋转了180
由于frame如果是旋转的,究其原因,仍是由于旋转的界说不一样导致的
处理办法
我首要想到的是修正SpriteFrame的极点,仔细看了相关的引擎源码,发现从头核算SpriteFrame的极点没有用,由于spine的region在核算时,运用的是SpriteFrame.rect进行核算的
我想要复用之前的逻辑,运用SpriteFrame替换纹路,所以首要要处理的问题就是怎么拿到SpriteFrame的信息,js engine比较好处理,c++的解析atlas的逻辑导出给jsb就有点费事,想来想去,决定将解析atlas的逻辑参考spine,从头运用js完成下。
- spine解析atlas的逻辑
var TextureAtlas = (function () {
function TextureAtlas(atlasText, textureLoader) {
this.pages = new Array();
this.regions = new Array();
this.load(atlasText, textureLoader);
}
TextureAtlas.prototype.load = function (atlasText, textureLoader) {
if (textureLoader == null)
throw new Error("textureLoader cannot be null.");
var reader = new TextureAtlasReader(atlasText);
var tuple = new Array(4);
var page = null;
while (true) {
var line = reader.readLine();
if (line == null)
break;
line = line.trim();
if (line.length == 0)
page = null;
else if (!page) {
page = new TextureAtlasPage();
page.name = line;
if (reader.readTuple(tuple) == 2) {
page.width = parseInt(tuple[0]);
page.height = parseInt(tuple[1]);
reader.readTuple(tuple);
}
reader.readTuple(tuple);
page.minFilter = spine.Texture.filterFromString(tuple[0]);
page.magFilter = spine.Texture.filterFromString(tuple[1]);
var direction = reader.readValue();
page.uWrap = spine.TextureWrap.ClampToEdge;
page.vWrap = spine.TextureWrap.ClampToEdge;
if (direction == "x")
page.uWrap = spine.TextureWrap.Repeat;
else if (direction == "y")
page.vWrap = spine.TextureWrap.Repeat;
else if (direction == "xy")
page.uWrap = page.vWrap = spine.TextureWrap.Repeat;
page.texture = textureLoader(line);
page.texture.setFilters(page.minFilter, page.magFilter);
page.texture.setWraps(page.uWrap, page.vWrap);
page.width = page.texture.getImage().width;
page.height = page.texture.getImage().height;
this.pages.push(page);
}
else {
var region = new TextureAtlasRegion();
region.name = line;
region.page = page;
var rotateValue = reader.readValue();
if (rotateValue.toLocaleLowerCase() == "true") {
region.degrees = 90;
}
else if (rotateValue.toLocaleLowerCase() == "false") {
region.degrees = 0;
}
else {
region.degrees = parseFloat(rotateValue);
}
region.rotate = region.degrees == 90;
reader.readTuple(tuple);
var x = parseInt(tuple[0]);
var y = parseInt(tuple[1]);
reader.readTuple(tuple);
var width = parseInt(tuple[0]);
var height = parseInt(tuple[1]);
region.u = x / page.width;
region.v = y / page.height;
if (region.rotate) {
region.u2 = (x + height) / page.width;
region.v2 = (y + width) / page.height;
}
else {
region.u2 = (x + width) / page.width;
region.v2 = (y + height) / page.height;
}
region.x = x;
region.y = y;
region.width = Math.abs(width);
region.height = Math.abs(height);
if (reader.readTuple(tuple) == 4) {
if (reader.readTuple(tuple) == 4) {
reader.readTuple(tuple);
}
}
region.originalWidth = parseInt(tuple[0]);
region.originalHeight = parseInt(tuple[1]);
reader.readTuple(tuple);
region.offsetX = parseInt(tuple[0]);
region.offsetY = parseInt(tuple[1]);
region.index = parseInt(reader.readValue());
region.texture = page.texture;
this.regions.push(region);
}
}
};
TextureAtlas.prototype.findRegion = function (name) {
for (var i = 0; i < this.regions.length; i++) {
if (this.regions[i].name == name) {
return this.regions[i];
}
}
return null;
};
TextureAtlas.prototype.dispose = function () {
for (var i = 0; i < this.pages.length; i++) {
this.pages[i].texture.dispose();
}
};
return TextureAtlas;
}());
问题:c++运用spine图集换肤,极点超过了1,导致烘托反常
反常情况如下:
MeshAttachment
在处理degress的时候,c++和js的完成逻辑不一样
主要就是在设置宽高时的逻辑有出入,能够看到上图中textureWidth
的核算方法不一样,可是成果应该是一样的,我这儿出现了不一样,是由于c++的regionHeight
导致的问题,排查了很久,感觉处理degress的逻辑应该没问题,问题出在换肤的SpriteFrame
的rect.width
/rect.height
上。
由于运用的spine图集中的frame,发生逆时针旋转90度,所以这儿我主动传递了degress=90
来矫正(我感觉这样处理可能会不合理,可是目前我也没找到适宜的处理办法),此时我应该同步将宽高交换的。
目前是凭直觉这样处理了,没发现问题,详细逻辑还需要后续深究,这块有点绕。
成果