从命令行工具生成(* .tps)?

时间:2013-11-13 15:09:28

标签: batch-file command-line texturepacker

我正在编写一个批处理脚本,使用TexturePacker的命令行工具生成精灵表。

for /f "delims=" %%i in ('dir /b sprites') do (
    TexturePacker --format "json" --data "sheets/%%i.json" --sheet "sheets/%%i.png" "sprites/%%i"
)

到目前为止非常简单,但我想知道是否有可能从该工具生成[* .tps]文件。因此,如果有人想要检查导出的属性,他们可以通过TexturePackerGUI来完成。

2 个答案:

答案 0 :(得分:1)

这是我用来在文件夹中构建所有.tps文件的bash脚本:

#!/bin/bash
for i in *.tps; do TexturePacker assets/texture_packer/$i; done

答案 1 :(得分:0)

此批处理脚本在文件夹中生成所有* .tps:

const topZero = 0;
const parent = i => ((i + 1) >>> 1) - 1;
const left = i => (i << 1) + 1;
const right = i => (i + 1) << 1;

class PriorityQueue {

  constructor(comparator = (a, b) => a > b) {
    this._heap = [];
    this._comparator = comparator;
  }

  size() {
    return this._heap.length;
  }

  isEmpty() {
    return this.size() == 0;
  }

  peek() {
    return this._heap[topZero];
  }

  push(...values) {
    values.forEach(value => {
      this._heap.push(value);
      this._siftUp();
    });
    return this.size();
  }

  pop() {
    const poppedValue = this.peek();
    const bottom = this.size() - 1;
    if (bottom > topZero) {
      this._swap(topZero, bottom);
    }
    this._heap.pop();
    this._siftDown();
    return poppedValue;
  }

  replace(value) {
    const replacedValue = this.peek();
    this._heap[topZero] = value;
    this._siftDown();
    return replacedValue;
  }

  _greater(i, j) {
    return this._comparator(this._heap[i], this._heap[j]);
  }

  _swap(i, j) {
    [this._heap[i], this._heap[j]] = [this._heap[j], this._heap[i]];
  }

  _siftUp() {
    let node = this.size() - 1;
    while (node > topZero && this._greater(node, parent(node))) {
      this._swap(node, parent(node));
      node = parent(node);
    }
  }

  _siftDown() {
    let node = topZero;
    while (
      (left(node) < this.size() && this._greater(left(node), node)) ||
      (right(node) < this.size() && this._greater(right(node), node))
      ) {
      let maxChild = (right(node) < this.size() && this._greater(right(node), left(node))) ? right(node) : left(node);
      this._swap(node, maxChild);
      node = maxChild;
    }
  }
}

const rectangles = [{
  rectID: "b22d",
  "yTop": 0,
  "yBottom": 60,
  "leftX": -1,
  "rightX": -1
},
  {
    rectID: "8938",
    "yTop": 60,
    "yBottom": 120,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e78a",
    "yTop": 60,
    "yBottom": 120,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "81ed",
    "yTop": 207,
    "yBottom": 222,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "b446",
    "yTop": 207,
    "yBottom": 222,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "ebd3",
    "yTop": 207,
    "yBottom": 222,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "2caf",
    "yTop": 208,
    "yBottom": 223,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e623",
    "yTop": 227,
    "yBottom": 242,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e6a3",
    "yTop": 270,
    "yBottom": 320,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e613",
    "yTop": 272,
    "yBottom": 460,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "c2d1",
    "yTop": 272,
    "yBottom": 290,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e64d",
    "yTop": 274,
    "yBottom": 300,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "b653",
    "yTop": 276,
    "yBottom": 310,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "e323",
    "yTop": 276,
    "yBottom": 310,
    "leftX": -1,
    "rightX": -1
  },
  {
    rectID: "fca3",
    "yTop": 300,
    "yBottom": 315,
    "leftX": -1,
    "rightX": -1
  }
];

let eventQueue = new PriorityQueue((a, b) => {
  if (a.y !== b.y) return a.y < b.y;
  if (a.type !== b.type) return a.type > b.type;
  return a.rectID > b.rectID;
})
let regionQueue = []; // FIFO
const EVENT_START = 0;
const EVENT_STOP = 1;

const queueAdd = (queue, toAdd, type, priority) => {

  return queue.push(toAdd);
}


const queuePop = (queue) => {
  return queue.pop();
}

const queueDestroy = (queue) => {
  return queue = [];
}

const optimizeLeftAndRightXStartPointsForNormalizedRectangleAreaWithoutOverlapping = (rectArray, length, overlapLimit, containerWidth) => {
  // fill the event queue with START and STOP events for each rectangle
  for (let i = 0; i < length; i++) {
    let startEvent = {
      y: rectArray[i].yTop,
      type: EVENT_START,
      index: i
    };
    eventQueue.push(startEvent);
    let stopEvent = {
      y: rectArray[i].yBottom,
      type: EVENT_STOP,
      index: i
    };
    eventQueue.push(stopEvent);
  }
  while (eventQueue.size()) { // queueIsNotEmpty(eventQueue)
    // search for the end of a region, while keeping track of the overlap in that region
    let overlap = 0;
    let maxOverlap = 0;
    let event;
    while (event = eventQueue.pop()) { // take from the event queue
      queueAdd(regionQueue, event); // save in the region queue
      if (event.type === 0) {
        overlap++;
      } else {
        overlap--;
      }
      if (overlap === 0) { // reached the end of a region
        break;
      }
      // if we have a new maximum for the overlap, update 'maxOverlap'
      if (overlap > maxOverlap) {
        maxOverlap = overlap;
      }
    }
    // limit the overlap as specified by the function parameter
    if (maxOverlap > overlapLimit) {
      maxOverlap = overlapLimit;
    }

    // compute the width to be used for rectangles in this region
    const width = parseInt(containerWidth / maxOverlap);

    // create and initialize an array to keep track of which columns are in use
    let usedColumns = new Array(maxOverlap);
    for (let i = 0; i < maxOverlap; i++) {
      if (usedColumns[i] == event.rectID) {
        usedColumns[i] = -1;
        break;
      }
    }
    // process the region, computing left and right X values for each rectangle
    while (event = queuePop(regionQueue)) {
      if (event.type == 0) {
        // find an available column for this rectangle, and assign the X values
        for (let column = 0; column < maxOverlap; column++) {
          if (usedColumns[column] < 0) {
            usedColumns[column] = event.rectID;
            rectArray[event.index].leftX = column * width;
            rectArray[event.index].rightX = (column + 1) * width;
            break;
          }

        }
      } else {
        // free the column that's being used for this rectangle
        for (let i = 0; i < maxOverlap; i++)
          if (usedColumns[i] == event.rectID) {
            usedColumns[i] = -1;
            break;
          }
      }
    }

  }
  return rectArray;
}


const displayResults = (completedRectangleList) => {
  const rectangleColors = ['cyan', 'magenta', 'green', 'yellow', 'orange']
  completedRectangleList.forEach((rectangle, index) => {
    if (rectangle.leftX > -1 && rectangle.rightX > -1) {
      let newRectangle = document.createElement('div');
      newRectangle.style.position = 'absolute';
      newRectangle.style.height = rectangle.yBottom - rectangle.yTop + 'px';
      newRectangle.style.top = rectangle.yTop + 'px';
      newRectangle.style.left = parseInt(rectangle.leftX) + '%';
      newRectangle.style.width = rectangle.rightX - rectangle.leftX + "%";
      newRectangle.style.backgroundColor = rectangleColors[index % rectangleColors.length];
      newRectangle.innerHTML = rectangle.rectID;
      if (rectangle.isMax) {
        newRectangle.innerHTML += '- more hidden';
      }
      document.body.appendChild(newRectangle);
    }

  })
}
let results = optimizeLeftAndRightXStartPointsForNormalizedRectangleAreaWithoutOverlapping(rectangles, (rectangles.length), 3, 100);
console.log('results ' + JSON.stringify(results));
displayResults(results);