Photoshop: How to handle numbering a large amount of disorganized items? - text

Suppose I have a large campsite like "seating" chart with several hundred lots sectioned off and outlined in photoshop. (each lot is roughly a square) Every lot needs to be numbered in photoshop and also editable in the future in case of changes. The lots are scattered and curve around the landscape so entering text in one layer seems out since for example lot 27 with be on the right and rotate 20 degrees to match the lot and yet lot 185 might be way over on the left at a far different angle.
Is there an elegant way to do this or at least quickly import a large number sequence that places one number per layer so I can grab them and orient them to their corresponding lot quickly instead of typing out and then positioning ever number individually? I'm having trouble thinking up an elegant/fast way to handle this in Photoshop...
Edit 1 - picture: http://i.imgur.com/UT3DRBi.jpg

You can do it with Extendscript. I am not the best of Extendscript programmers, but the following script will ask you for the number of text labels you want and add that many numbers on sepearate layers. Of course, you can diddle around with the font, colour, position, size etc. but it should get you started.
Here is an example - I turned off layers 4 and 5 so you can see each number is on a new layer.
Here it asks how many numbers you want:
// Setchell - AddNumbers - Adobe Photoshop Script
// Description: Asks user for number of numbers to add, each in own layer
// Version: 0.1
// Author: Mark Setchell (mark#thesetchells.com)
// Web: http://www.thesetchells.com
// ============================================================================
// Installation:
// 1. Place script in 'C:\Program Files\Adobe\Adobe Photoshop CS#\Presets\Scripts\'
// 2. Restart Photoshop
// 3. Choose File > Scripts > AddNumbers
// ============================================================================
// enable double-clicking from Mac Finder or Windows Explorer
// this command only works in Photoshop CS2 and higher
#target photoshop
// bring application forward for double-click events
app.bringToFront();
///////////////////////////////////////////////////////////////////////////////
// AddNumbers
///////////////////////////////////////////////////////////////////////////////
function AddNumbers() {
// Change Debug=1 for extra debugging messages
var Debug=1;
// Get user to enter common stem for JPEG names
var dialog = new Window('dialog', 'Setchell - AddNumbers');
dialog.size = {width:500, height:100};
dialog.stem = dialog.add('edittext',undefined, '<Enter ending number>');
dialog.stem.size = {width:400,height:25};
dialog.stem.value = true;
dialog.stem.buildBtn = dialog.add('button', undefined,'OK', {name:'ok'});
dialog.show();
// Pick up what user entered - just digits
var limit=dialog.stem.text.match(/\d+/);
// Debug
if(Debug)alert(limit);
var cnt;
var n=0;
var nPer=10;
var deltaX=app.activeDocument.width/nPer;
var deltaY=app.activeDocument.height/nPer;
var tX=0;
var tY=deltaY;
app.preferences.typeUnits = TypeUnits.POINTS;
for(cnt=1;cnt<=limit;cnt++){
// Adds a new layer to the active document and stores it in a variable named “myTextLayer”.
var myTextLayer = app.activeDocument.artLayers.add();
// Changes myTextLayer from normal to a text layer.
myTextLayer.kind = LayerKind.TEXT;
// Gets a reference to the textItem property of myTextLayer.
var myText = myTextLayer.textItem;
// sets the font size of the text to 16.
myText.size = 16;
// Sets the contents of the textItem.
myText.contents = cnt;
// Position the label - could be improved :-)
tX=n*deltaX;
myText.position = new Array(tX, tY);
n++;
if(n==nPer){
tY+=deltaY;
n=0;
}
}
return;
}
///////////////////////////////////////////////////////////////////////////////
// isCorrectVersion - check for Adobe Photoshop CS2 (v9) or higher
///////////////////////////////////////////////////////////////////////////////
function isCorrectVersion() {
if (parseInt(version, 10) >= 9) {
return true;
}
else {
alert('This script requires Adobe Photoshop CS2 or higher.', 'Wrong Version', false);
return false;
}
}
///////////////////////////////////////////////////////////////////////////////
// showError - display error message if something goes wrong
///////////////////////////////////////////////////////////////////////////////
function showError(err) {
if (confirm('An unknown error has occurred.\n' +
'Would you like to see more information?', true, 'Unknown Error')) {
alert(err + ': on line ' + err.line, 'Script Error', true);
}
}
// test initial conditions prior to running main function
if (isCorrectVersion()) {
// Save current RulerUnits to restore when we have finished
var savedRulerUnits = app.preferences.rulerUnits;
// Set RulerUnits to PIXELS
app.preferences.rulerUnits = Units.PIXELS;
try {
AddNumbers();
}
catch(e) {
// don't report error on user cancel
if (e.number != 8007) {
showError(e);
}
}
// Restore RulerUnits to whatever they were when we started
app.preferences.rulerUnits = savedRulerUnits;
}

Related

PDFKit split text into two equal columns while using for loop

Im trying to use PDFKit to generate a simple pdf, for the most part the pdf works but albeit in a very non useful way, what i have is a deck building API that takes in a number of cards, each of these objects i want to export to a pdf, its as simple as displaying their name, but as it is, the pdf only renders one card at a time, and only on one line, what id like to happen is to get it to split the text into columns so itd look similar to this.
column 1 | column 2
c1 c8
c2 c9
c3 c10
c4 c(n)
here is my code so far,
module.exports = asyncHandler(async (req, res, next) => {
try {
// find the deck
const deck = await Deck.findById(req.params.deckId);
// need to sort cards by name
await deck.cards.sort((a, b) => {
if (a.name < b.name) {
return -1;
} else if (a.name > b.name) {
return 1;
} else {
return 0;
}
});
// Create a new PDF document
const doc = new PDFDocument();
// Pipe its output somewhere, like to a file or HTTP response
doc.pipe(
fs.createWriteStream(
`${__dirname}/../../public/pdf/${deck.deck_name}.pdf`
)
);
// Embed a font, set the font size, and render some text
doc.fontSize(25).text(`${deck.deck_name} Deck List`, {
align: "center",
underline: true,
underlineColor: "#000000",
underlineThickness: 2,
});
// We need to create two columns for the cards
// The first column will be the card name
// The second column will continue the cards listed
const section = doc.struct("P");
doc.addStructure(section);
for (const card of deck.cards) {
doc.text(`${card.name}`, {
color: "#000000",
fontSize: 10,
columns: 2,
columnGap: 10,
continued: true,
});
}
section.end();
// finalize the PDF and end the response
doc.end();
res.status(200).json({ message: "PDF generated successfully" });
} catch (error) {
console.error(error);
res.status(500).json({
success: false,
message: `Server Error - ${error.message}`,
});
}
});
At Present this does generate a column order like i want, however theres and extreme caveat to this solution and that is, if the card text isnt very long, the next card will start on that same line, it'd be useful if i could find a way to make the text take up the full width of that row, but i havent seen anything to do that with.
I think the problem is that you're relying on PDFKit's text "flow" API/logic, and you're having problems when two cards are not big enough to flow across your columns and you get two cards in one column.
I'd say that what you really want is to create a table—based on your initial text sample.
PDFKit doesn't have a table API (yet), so you'll have to make one up for yourself.
Here's an approach where you figure out the dimensions of things:
the page size
the size of your cells of text (either manually choose for yourself, or use PDFKit to tell you how big some piece of text is)
margins
Then you use those sizes to calculate how many rows and columns of your text can fit on your page.
Finally you iterate of over columns then rows for each page, writing text into those column-by-row "coordinates" (which I track through "offsets" and use to calculate the final "position").
const PDFDocument = require('pdfkit');
const fs = require('fs');
// Create mock-up Cards for OP
const cards = [];
for (let i = 0; i < 100; i++) {
cards.push(`Card ${i + 1}`);
}
// Set a sensible starting point for each page
const originX = 50;
const originY = 50;
const doc = new PDFDocument({ size: 'LETTER' });
// Define row height and column widths, based on font size; either manually,
// or use commented-out heightOf and widthOf methods to dynamically pick sizes
doc.fontSize(24);
const rowH = 50; // doc.heightOfString(cards[cards.length - 1]);
const colW = 150; // doc.widthOfString(cards[cards.length - 1]); // because the last card is the "longest" piece of text
// Margins aren't really discussed in the documentation; I can ignore the top and left margin by
// placing the text at (0,0), but I cannot write below the bottom margin
const pageH = doc.page.height;
const rowsPerPage = parseInt((pageH - originY - doc.page.margins.bottom) / rowH);
const colsPerPage = 2;
var cardIdx = 0;
while (cardIdx < cards.length) {
var colOffset = 0;
while (colOffset < colsPerPage) {
const posX = originX + (colOffset * colW);
var rowOffset = 0;
while (rowOffset < rowsPerPage) {
const posY = originY + (rowOffset * rowH);
doc.text(cards[cardIdx], posX, posY);
cardIdx += 1;
rowOffset += 1;
}
colOffset += 1;
}
// This is hacky, but PDFKit adds a page by default so the loop doesn't 100% control when a page is added;
// this prevents an empty trailing page from being added
if (cardIdx < cards.length) {
doc.addPage();
}
}
// Finalize PDF file
doc.pipe(fs.createWriteStream('output.pdf'));
doc.end();
When I run that I get a PDF with 4 pages that looks like this:
Changing colW = 250 and colsPerPage = 3:

Phaser: show text when sprites overlap

I am trying to work out a way to add a text to the top left corner of the viewport when two of my sprites overlap. One of them is an item and the other is my character. I can already detect for overlap and even "pick" the item (kill the sprite) when I click a key. However I would like that a text saying something like "Click "E" to pick the sword!" appeared while the collision function is active and when I kill the sprite by picking it up the text would vanish.
I tried including the text in the collision function itself but I suppose this way I am rendering the text multiple times (the fps drops a lot) and I just want to create it once and remove it according to my purposes. My code:
function collisionHandler(dude,the_sword) {
pickObject.onDown.add(function () {
the_sword.kill();
}, this);
}
game.physics.isoArcade.overlap(dude, the_sword, collisionHandler, null, this);
// message saying to pick // Where to put this?
var style = { font: "30px Arial", fill: "#ff0044"};
var pick_message = this.game.add.text(0,20,"Click 'E' to pick up the sword!",style);
pick_message.fixedToCamera = true;
Any idea on how to do this?
In your 'create' function:
var style = { font: "30px Arial", fill: "#ff0044"};
var pick_message = this.game.add.text(0,20,"Click 'E' to pick up the sword!",style);
pick_message.fixedToCamera = true;
pick_message.visible = false;
Then:
function collisionHandler(dude,the_sword) {
pick_message.visible = true;
pickObject.onDown.add(function () {
the_sword.kill();
pick_message.visible = false;
}, this);
}
game.physics.isoArcade.overlap(dude, the_sword, collisionHandler, null, this);
Something like that should work. If you want to perform other action, like opening the door, you can use:
pick_message.setText("Click 'Q' to open the door!");
You don't have to create new text evertime, you can use one for different purposes.

background image repeat effect in cocos creater

How can background image be set in repeat effect in cocos creater ?
If character runs, back image should be flow backwards, but I want to background repeatedly continuously repeated by using one device size image file.
I think you can do this by using two background images, placed one after the other, with anchors 0,0, size assumed to be same as canvas size (Images not placed inside the canvas). This script applied to both images can achieve that effect, in simplest form.
cc.Class({
extends: cc.Component,
properties: {
// speed of scrolling
speed: 0,
// reset to position
bgwidth: 0
},
// use this for initialization
onLoad: function () {
},
// called every frame, uncomment this function to activate update callback
update: function (dt) {
var x = this.node.x;
x -= this.speed * dt;
if (x <= -this.bgwidth) {
x += this.bgwidth*2;
}
this.node.x = x;
},
});

(After Effects) Change text content over the time

I would like to put the title + artist name when the song is playing, but I don't know how to achieve this, because with almost 30-35 songs, it would be long and boring to create a specific text layer for each song.
If there is a trick to achieve this quickly.
You can achieve this via scripting.
I have these two scripts that should do what you want. I wrote them some time ago. Maybe you need to do some adjustments.
This one adds several text layers from a csv file.
https://github.com/fabiantheblind/after-effects-script-snippets/blob/master/comp_with_text.jsx
This one should add one text layer with the source text set to the content of a csv.
https://github.com/fabiantheblind/after-effects-script-snippets/blob/master/text_to_comp.jsx
This is a minimal example to add a text layer with sourceText
/**
* main function
*/
var main = function() {
var txt = ['Hello - World', 'dog -cat', 'foo - bah']; // the text to add
app.beginUndoGroup('add source text'); // open a undo group
var curComp = app.project.activeItem; // get the current comp
// check if the curent active item is a comp
if (!curComp || !(curComp instanceof CompItem)) {
alert('noComp');
return;
// end if no comp is active
}
var txtLayer = curComp.layers.addText('titles'); // add a text layer
var counter = 0; // the time to add a keyframe to (in seconds)
// loop the text
for (var i = 0; i < txt.length; i++) {
var curFrame = (counter / curComp.frameRate); // calc time for each frame
$.writeln(curFrame);
// add a keyframe with the text as value every frame
txtLayer.text.sourceText.setValueAtTime(curFrame, txt[i]);
counter++; // increase the time by one
}
app.endUndoGroup();
};
main();

When I close a window and then open a different one, the selected tab is recreated by Chrome

I am writing a Chrome extension that saves/restores your browsers window state - So, I save the state of a given window:
var properties = [ "top",
"left",
"width",
"height",
"incognito",
"focused",
"type"
];
var json = {};
var cache = chrome_window_object;
// copy only the keys we care about:
_.each(properties,function(key,value) {
json[key] = cache[key];
});
// then copy the URLs of the tabs, if they exist:
if(cache.tabs) {
json.url = [];
_.each(cache.tabs,function(tab) {
json.url.push(tab.url);
});
}
return json;
At some point in the future, I remove all windows:
closeAllWindows: function(done_callback) {
function got_all(windows) {
var index = 0;
// use a closure to only close one window at a time:
function close_next() {
if(windows.length <= index) return;
var window = windows[index++];
chrome.windows.remove(window,close_next);
}
// start closing windows:
close_next();
}
chrome.windows.getAll(got_all);
}
and then I restore the window using:
chrome.windows.create(json_from_before);
The window that is created has an extra tab in it, whatever was in the window that I just closed... I am completely floored, and I assume the problem is something that I am doing in the code that I haven't posted (it's a big extension). I've spent a few hours checking code line by line and making sure I'm not explicitly asking for this tab to be created. So - has anybody seen anything like this before?

Resources