Pure javascript pixel manipulation with processing.js - processing.js

I would like to manipulate pixels with processing.js. I would like to do this in pure javascript but am having difficulties. The following simple case fails
<canvas id="canvas1"></canvas>
<script type="text/javascript">
function sketchProc(p){
// Configure page and init variables
function setup() {
p.size(300, 300);
console.log(p.pixels)
p.background(100,200,100)
}
function draw() {
p.loadPixels();
for (var i = 0; i < 3000 ; i++) {
p.pixels[i] = p.color(0,0,0)
}
p.updatePixels();
}
// Attach functions to processing object
p.setup = setup;
p.draw = draw;
}
var canvas = document.getElementById("canvas1")
var processingInstance = new Processing(canvas, sketchProc)
</script>
which (I believe) should convert the first 3000 pixels to black. Looking at the console.log for p.pixels I am wondering if this type of array access fails in pure javascript? Any suggestions welcome and thanks in advance.

That is because you must Attach the functions directly to p:
function sketchProc(p){
// Attach functions to processing object
p.setup = function setup() {
p.size(300, 300);
console.log(p.pixels);
p.background(100,200,100);
};
p.draw = function draw() {
p.loadPixels();
for (var i = 0; i < 3000 ; i++) {
p.pixels[i] = p.color(0,0,0);
}
p.updatePixels();
};
}
var canvas = document.getElementById("canvas1");
var processingInstance = new Processing(canvas, sketchProc);

Related

Photoshop Scripting: Relink Smart Object

I'm working on a script that should go through a photoshop document and relink all visible linked objects to a new specified file. I've gotten the loop working so that it cycles through every layer and collects only the visible layers, but for the life of me I can't find if there's a method available to relink a smart object. The closest I've found is this script:
https://gist.github.com/laryn/0a1f6bf0dab5b713395a835f9bfa805c
but when it gets to desc3.putPath(idnull, new File(newFile));, it spits out an error indicating that the functionality may not be present in the current Photoshop version. The script itself is 4 years old so it may be out of date.
Any help would be appreciated!
MY script as it stands is below:
// SELECT FILE //
var files = File.openDialog("Please select new linked file");
var selectedFile = files[0];
// GET ALL LAYERS //
var doc = app.activeDocument;
var allLayers = [];
var allLayers = collectAllLayers(doc, allLayers);
function collectAllLayers (doc, allLayers)
{
for (var m = 0; m < doc.layers.length; m++)
{
var theLayer = doc.layers[m];
if (theLayer.typename === "ArtLayer")
{
allLayers.push(theLayer);
}
else
{
collectAllLayers(theLayer, allLayers);
}
}
return allLayers;
}
// GET VISIBLE LAYERS //
var visibleLayers = [];
for (i = 0; i < allLayers.length; i++)
{
var layer = allLayers[i];
if (layer.visible && layer.kind == LayerKind.SMARTOBJECT)
{
visibleLayers.push(layer);
}
}
// REPLACE LAYERS
for (i = 0; i < visibleLayers.length; i++)
{
var layer = visibleLayers[i];
//--> REPLACE THE FILE HERE
}
Note: I am aware that this script currently may be error-prone if you don't know exactly how it works; I'm not intending to publish it at this time so I'm not super concerned with that at the moment. Mostly I just need the core functionality to work.
I used an AM function for getting visible smart objects — it works much faster. But if you want you can use yours. The important bit is relinkSO(path);: it'll also work in your script (just don't forget to select a layer: activeDocument.activeLayer = visibleLayers[i];)
Note that it works similar to Photoshop Relink to File command — if used on one instance of Smart Object all the instances are going to be relinked. If you want to relink only specific layers you'll have to break instancing first (probably using the New Smart Object via Copy command)
function main() {
var myFile = Folder.myDocuments.openDlg('Load file', undefined, false);
if (myFile == null) return false;
// gets IDs of all smart objects
var lyrs = getLyrs();
for (var i = 0; i < lyrs.length; i++) {
// for each SO id...
// select it
selectById(lyrs[i]);
// relink SO to file
relinkSO(myFile);
// embed linked if you want
embedLinked()
}
function getLyrs() {
var ids = [];
var layers, desc, vis, type, id;
try
{
activeDocument.backgroundLayer;
layers = 0;
}
catch (e)
{
layers = 1;
}
while (true)
{
ref = new ActionReference();
ref.putIndex(charIDToTypeID('Lyr '), layers);
try
{
desc = executeActionGet(ref);
}
catch (err)
{
break;
}
vis = desc.getBoolean(charIDToTypeID("Vsbl"));
type = desc.getInteger(stringIDToTypeID("layerKind"));
id = desc.getInteger(stringIDToTypeID("layerID"));
if (type == 5 && vis) ids.push(id);
layers++;
}
return ids;
} // end of getLyrs()
function selectById(id) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID('Lyr '), id);
desc.putReference(charIDToTypeID('null'), ref);
executeAction(charIDToTypeID('slct'), desc, DialogModes.NO);
} // end of selectById()
function relinkSO(path) {
var desc = new ActionDescriptor();
desc.putPath( charIDToTypeID('null'), new File( path ) );
executeAction( stringIDToTypeID('placedLayerRelinkToFile'), desc, DialogModes.NO );
} // end of relinkSO()
function embedLinked() {
executeAction( stringIDToTypeID('placedLayerConvertToEmbedded'), undefined, DialogModes.NO );
} // end of embedLinked()
}
app.activeDocument.suspendHistory("relink SOs", "main()");

How to curve the navtitle along the path using wheelnav js

How can I make the navtitle curve along the path of the slice and wrap the text if it's long.
Image of the wheel above
In long text, use '\n' in the title for wrap.
wheel.createWheel(["Long\ntext"]);
Currently, the navtitle curve along the path is an RC feature, so please use the source code instead of the last release.
You can find the new properties in this CodePen: https://codepen.io/softwaretailoring/pen/RQYzWm
var piemenu = new wheelnav("wheelDiv");
// New properties in wheelnav.js v1.8.0
piemenu.titleCurved = true;
piemenu.titleCurvedClockwise = false;
piemenu.titleCurvedByRotateAngle = false;
Unfortunately, the two above properties don't work together. :(
UPDATE: There is a way to achieve your needs. You can use two wheels on each other.
var piemenu = new wheelnav("wheelDiv");
setMenu(piemenu); // Set common properties
piemenu.titleRadiusPercent = 0.65; // Positioning first title
piemenu.markerEnable = true;
piemenu.slicePathFunction = slicePath().DonutSlice;
piemenu.sliceClickablePathFunction = slicePath().DonutSlice;
piemenu.titleHoverAttr = { fill: "#333" };
piemenu.createWheel(["Hello", "world!", "-------"]);
var piemenu2 = new wheelnav("wheelDiv2", piemenu.raphael);
setMenu(piemenu2); // Set common properties
piemenu2.wheelRadius = 520; // Positioning second title
piemenu2.slicePathFunction = slicePath().NullSlice; // There is no slice, only title
piemenu2.createWheel(["Bello", "space!", "*******"]);
// Link navigateFunctions to each other
for (var i = 0; i < piemenu.navItems.length; i++) {
piemenu.navItems[i].navigateFunction = function () {
piemenu2.navigateWheel(Math.abs(this.itemIndex));
}
}
for (var i = 0; i < piemenu2.navItems.length; i++) {
piemenu2.navItems[i].navigateFunction = function () {
piemenu.navigateWheel(Math.abs(this.itemIndex));
}
}
Here is a new CodePen for wrapped and curved text: https://codepen.io/softwaretailoring/pen/eLNBYz

remove ticker for individual object in createjs

I want to remove the listener for individual objects that are animating. I want to remove the ticker for individual objects because they will stop at different times when they reach 200px in y. This code is one frame in Adobe Animate. So this code is not working:
this.stop();
that= this;
var aParticle;
var mySpeed = 12;
var myRotation = 4;
var totalParticles = 5;
var stopParticles = false;
var particleHolder = new createjs.Container();
var count = 0;
var collission_ar = [this.parent.mc_coll0, this.parent.mc_coll1, `this.parent.mc_coll2, this.parent.mc_coll3, this.parent.mc_coll4, this.parent.mc_coll5, this.parent.mc_coll6, this.parent.mc_coll7, this.parent.mc_coll8, this.parent.mc_coll9, this.parent.mc_coll10, this.parent.mc_coll11, this.parent.mc_coll12, this.parent.mc_coll13, this.parent.mc_coll14];`
var totalCollisions = collission_ar.length;
this.addChild(particleHolder);
//stage.update();
var xRange = width;
var yRange = height;
var scaleNum = 1;
//var collisionMethod = ndgmr.checkPixelCollision;
this.scaleX = 1;
this.scaleY = 1;
createParticles()
setTimeout(function(){
removeTimer();
}, 5000)
function createParticles(){
var particle_ar = [];
var randNum = Math.ceil(Math.random() * totalParticles);
aParticle = new lib['MC_leaf'+randNum]();
aParticle.name = 'MC_leaf'+count;
aParticle.x = Math.random() * xRange;
aParticle.y = -Math.random() * 15;
theNum = Math.random() * scaleNum;
aParticle.scaleX = theNum
aParticle.scaleY = theNum
aParticle.alpha = 1;
aParticle.collision = Math.floor(Math.random() * 2);
particleHolder.addChild(aParticle);
aParticle.addEventListener("tick", animateParticle.bind(that));
if(!stopParticles){
timer = setTimeout(function() { createParticles() }, 100);
}
count++;
}
function animateParticle (event){
var part = event.currentTarget;
event.currentTarget.y += mySpeed
event.currentTarget.x += Math.random()/10
event.currentTarget.rotation += myRotation;
if (part.y > 200) {
if(part.name == 'MC_leaf0') console.log('part0 y '+part.y);
part.removeEventListener("tick", animateParticle.bind(that));
}
}
function removeTimer() {
stopParticles = true;
timer = clearInterval();
}
var timer = setTimeout(function() { createParticles() }, 100, that);
So this code is just ignored:
part.removeEventListener("tick", animateParticle.bind(that));
You must pass a reference to the same method in removeEventListener that you used with addEventListener. When you use bind, it generates a wrapper function each time.
// This won't work.
part.removeEventListener("tick", animateParticle.bind(that));
A simple workaround is to store a reference to the bound function, and use that.
aParticle.tickHandler = animateParticle.bind(that);
aParticle.addEventListener("tick", aParticle.tickHandler);
Then use it when removing the listener
part.removeEventListener("tick", part.tickHandler);
There is a better way to handle this though. If you use the utility on() method instead of addEventListener, you can easily remove the method inside the handler.
aParticle.on("tick", animateParticle, that);
// Then when removing:
function animateParticle(event) {
if (conditions) {
event.remove();
}
}
The on() method also has a scope parameter, so you can skip the function binding. It is important to note though that the on() method does its own internal binding, so to remove a listener the usual way, you have to store a reference to it as well.
var listener = target.on("tick", handler, this);
listener.off("tick", listener);
Hope that helps!

Background Over-riding MousePressed() Ellipse in Draw Function

I've made a particle system in P5.js that explodes particles on mousepressed(). However, I'd also like expanding circles to output on mousepressed(). I was able to draw a circle on mousepressed(), however it seems to be under the background. I am having a brain fart on this. Why isn't the circle appearing along with the particles, above the black background? Thanks for help!
var lifeConstant = 50000;
var startVelMin = -10;
var startVelMax = 7;
var drag = -50;
var planetArray = [];
var planet;
var planet0;
var planet1;
var planet3;
//var planets = ['planet1.gif', 'planet2.gif', 'planet3.gif', 'planet4.gif']// for loop to loop through image files
//for (var i = 0; i < planets.length; i++) { //
function preload(){
//for (var i = 0; i < planetArray.length; i++) {
planet = loadImage('Assets/planet2.gif');
append(planetArray, planet);
planet3 = loadImage('Assets/planet3.gif');
append(planetArray, planet3);
planet0 = loadImage('Assets/planet4.gif');
append(planetArray, planet0);
planet1 = loadImage('Assets/planet1.gif');
append(planetArray, planet1);
}
//planetArray.add(planet);
function setup() {
createCanvas(windowWidth, windowHeight);
systems = [];
background(51);
}
function draw() {
background(0)
for (i = 0; i < systems.length; i++) {
systems[i].run();
systems[i].addParticle();
}
if (systems.length==0) {
fill(255);
textAlign(CENTER);
textSize(42);
text("Click mouse to create Big Bangs", width/2, height/2);
}
}
function mousePressed() {
this.p = new ParticleSystem(createVector(mouseX, mouseY));
systems.push(p);
fill(230,120, 0);
ellipse(mouseX, mouseY, 100, 100);
}
// A simple Particle class
var Particle = function(position) {
this.acceleration = createVector(0, .1);
this.velocity = createVector(random(startVelMin,startVelMax), random(startVelMin,startVelMax));
this.position = position.copy();
this.lifespan = lifeConstant;
};
Particle.prototype.run = function() {
this.update();
this.display();
};
// Method to update position
Particle.prototype.update = function(){
this.velocity.add(drag*this.acceleration);
this.position.add(this.velocity);
this.lifespan -= 150;
};
// Method to display
Particle.prototype.display = function () {
//fill(random(255), random(255), random(200));
//stroke(20, this.lifespan);
//strokeWeight(1);
//fill(random(255),this.lifespan);
//ellipse(this.position.x, this.position.y, 15, 15);
image(planetArray[floor(random(4))], this.position.x, this.position.y, 15, 15);
};
// Is the particle still useful?
Particle.prototype.isDead = function () {
if (this.lifespan < 0) {
return true;
} else {
return false;
}
};
var ParticleSystem = function (position) {
this.origin = position.copy();
this.particles = [];
};
ParticleSystem.prototype.addParticle = function () {
// Add either a Particle or CrazyParticle to the system
if (int(random(0, 2)) == 0) {
p = new Particle(this.origin);
}
else {
p = new
CrazyParticle(this.origin);
}
this.particles.push(p);
};
ParticleSystem.prototype.run = function () {
for (var i = this.particles.length - 1; i >= 0; i--) {
var p = this.particles[i];
p.run();
if (p.isDead()) {
this.particles.splice(i, 1);
}
}
};
// A subclass of Particle
function CrazyParticle(origin) {
// Call the parent constructor, making sure (using Function#call)
// that "this" is set correctly during the call
Particle.call(this, origin);
// Initialize our added properties
this.theta = 0.0;
};
// Create a Crazy.prototype object that inherits from Particle.prototype.
// Note: A common error here is to use "new Particle()" to create the
// Crazy.prototype. That's incorrect for several reasons, not least
// that we don't have anything to give Particle for the "origin"
// argument. The correct place to call Particle is above, where we call
// it from Crazy.
CrazyParticle.prototype = Object.create(Particle.prototype); // See note below
// Set the "constructor" property to refer to CrazyParticle
CrazyParticle.prototype.constructor = CrazyParticle;
// Notice we don't have the method run() here; it is inherited from Particle
// This update() method overrides the parent class update() method
CrazyParticle.prototype.update=function() {
Particle.prototype.update.call(this);
// Increment rotation based on horizontal velocity
this.theta += (this.velocity.x * this.velocity.mag()) / 10.0;
}
// This display() method overrides the parent class display() method
CrazyParticle.prototype.display=function() {
// Render the ellipse just like in a regular particle
// Particle.prototype.display.call(this);
}
The mousePressed() function is called whenever the mouse button is pressed down. The draw() function is called 60 times per second. So anything you draw in the mousePressed() function will almost immediately be drawn over with whatever you draw in the draw() function.
You need to have all of your drawing code called from your draw() function. You could do this by using a variable that keeps track of whether the mouse is pressed. Luckily, p5.js already has a variable that does exactly that: mouseIsPressed

JScript.NET private variables

I'm wondering about JScript.NET private variables. Please take a look on the following code:
import System;
import System.Windows.Forms;
import System.Drawing;
var jsPDF = function(){
var state = 0;
var beginPage = function(){
state = 2;
out('beginPage');
}
var out = function(text){
if(state == 2){
var st = 3;
}
MessageBox.Show(text + ' ' + state);
}
var addHeader = function(){
out('header');
}
return {
endDocument: function(){
state = 1;
addHeader();
out('endDocument');
},
beginDocument: function(){
beginPage();
}
}
}
var j = new jsPDF();
j.beginDocument();
j.endDocument();
Output:
beginPage 2
header 2
endDocument 2
if I run the same script in any browser, the output is:
beginPage 2
header 1
endDocument 1
Why it is so??
Thanks,
Paul.
Just a guess, but it appears that JScript.NET doesn't support closures the same way as EMCAScript, so the state variable in endDocument() isn't referencing the private member of the outer function, but rather an local variable (undeclared). Odd.
You don't have to use new when calling jsPDF here since you're using a singleton pattern. jsPDF is returning an object literal so even without new you'll have access to the beginPage and endDocument methods. To be perfectly honest I don't know what the specifications call for when using new on a function that returns an object literal so I'm not sure if JScript.NET is getting it wrong or the browser. But for now try either getting rid of the new before jsPDF() or change your function to this:
var jsPDF = function(){
var state = 0;
var beginPage = function(){
state = 2;
out('beginPage');
};
var out = function(text){
if(state == 2){
var st = 3;
}
MessageBox.Show(text + ' ' + state);
};
var addHeader = function(){
out('header');
};
this.endDocument = function(){
state = 1;
addHeader();
out('endDocument');
};
this.beginDocument: function(){
beginPage();
};
}
That will allow you to use the new keyword and create more than one jsPDF object.
I've come across the same problem. In the following code, the closure bound to fun should contain only one variable called result. As the code stands, the variable result in the function with one parameter seems to be different to the result variable in the closure.
If in this function the line
result = [];
is removed, then the result in the line
return result;
refers to the result in the closure.
var fun = function() {
var result = [];
// recursive descent, collects property names of obj
// dummy parameter does nothing
var funAux = function(obj, pathToObj, dummy) {
if (typeof obj === "object") {
for (var propName in obj) {
if (obj.hasOwnProperty(propName)) {
funAux(obj[propName], pathToObj.concat(propName), dummy);
}
}
}
else {
// at leaf property, save path to leaf
result.push(pathToObj);
}
}
return function(obj) {
// remove line below and `result' 3 lines below is `result' in closure
result = []; // does not appear to be bound to `result' above
funAux(obj, [], "dummy");
return result; // if result 2 lines above is set, result is closure is a different variable
};
}();