I am a Photoshop beginner and currently use version Photoshop CS3. I use keyboard shortcut all the time to speed up the design process such as creation of new layers etc.
However, one command I feel Photoshop must have is to create a new layer below the current working layer and therefore I cannot assign it via a shortcut.
I have to create a new layer above the current layer and then manually drag it below the current layer which I feel can be automated using action or scripting, both of which are difficult for me being a beginner.
Can anybody help me in this regard.
Thanks
dkj
It can be scripted with the following:
I've simplified my answer - you don't need to find the index, you can use the active layer instead.
create_new_layer("Gwen!");
// function CREATE NEW LAYER (layername)
// --------------------------------------------------------
function create_new_layer(layername)
{
if (layername == undefined) layername = "Layer";
// create new layer at top of layers
var originalLayer = app.activeDocument.activeLayer;
var layerRef = app.activeDocument.artLayers.add();
// name it & set blend mode to normal
layerRef.name = layername;
layerRef.blendMode = BlendMode.NORMAL;
// Move the layer below
layerRef.moveAfter(originalLayer);
// Move the layer above if you desire
// layerRef.moveBefore(originalLayer);
}
You can then record this script as an action and put on a keyboard short cut.
Few years ago i thought that native PS API working with DOM is cool and should work faster, but actually under the hood it's callstack often even bigger than same commands performed via actions. + Also sometimes DOM functions consist of multiple underlying calls, like artLayers.add() for example which is actually make layer + move it to top of the document. So here's action version of that functionality from my PS scripting library:
// get current layer number
function curLyrN(){
if(app.activeDocument.artLayers.length<2) return 1;
var idLyr = charIDToTypeID("Lyr ");
var idItmI = charIDToTypeID("ItmI");
var aref = new ActionReference();
aref.putEnumerated(idLyr, charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var id = executeActionGet(aref).getInteger(charIDToTypeID("LyrI"));
aref = new ActionReference();
aref.putProperty(charIDToTypeID("Prpr"), idItmI);
aref.putIdentifier(idLyr, id);
id = executeActionGet(aref).getInteger(idItmI);
if(id) return id;
return 0;
}
// select [LayerNum], optionally [add] to selection (if add=2: with inclusion)
function selLyr(LyrN,add){
var adesc = new ActionDescriptor();
var aref = new ActionReference();
aref.putIndex(charIDToTypeID("Lyr "), LyrN);
adesc.putReference(charIDToTypeID("null"), aref);
if(add){
add = (add==2) ? stringIDToTypeID("addToSelectionContinuous") : stringIDToTypeID("addToSelection");
adesc.putEnumerated(stringIDToTypeID("selectionModifier"),stringIDToTypeID("selectionModifierType"),add);
}
adesc.putBoolean(charIDToTypeID("MkVs"), false);
return executeAction(charIDToTypeID("slct"), adesc, DialogModes.NO);
}
// move current layer to [LayerNum]
function movLyr(LyrN){
var idLyr = charIDToTypeID("Lyr ");
var adesc = new ActionDescriptor();
var aref = new ActionReference();
aref.putEnumerated(idLyr, charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
adesc.putReference(charIDToTypeID("null"), aref);
aref = new ActionReference();
aref.putIndex(idLyr, LyrN);
adesc.putReference(charIDToTypeID("T "), aref);
adesc.putBoolean(charIDToTypeID("Adjs"), false);
return executeAction(charIDToTypeID("move"), adesc, DialogModes.NO);
}
// create new empty layer
function mkLyr(){
var aref = new ActionReference();
aref.putClass(charIDToTypeID("Lyr "));
var adesc = new ActionDescriptor();
adesc.putReference(charIDToTypeID("null"), aref);
return executeAction(charIDToTypeID("Mk "), adesc, DialogModes.NO);
}
// count all inner layers from layer-set (group)
function cntLyrS(lyrs,c){
if(!c){
if(lyrs.typename!='LayerSet') return 0;
c = 0;
}
var ls = lyrs.layers.length;
var i = 0;
while(i<ls){
c++;
if(lyrs.layers[i].typename=='LayerSet') c=cntLyrS(lyrs.layers[i],c);
i++;
}
return c+1;
}
// make new layer below current or [LayerNum], optionally [ignoreGroups]
function mkLyrBelow(LyrN,noGr){
var doc = app.activeDocument;
if(!doc) return false;
if(LyrN){
selLyr(LyrN);
}else{
LyrN = curLyrN();
if(!LyrN) return false;
}
var actv = doc.activeLayer;
if(actv.isBackgroundLayer) actv.isBackgroundLayer=false;
mkLyr();
if(curLyrN()==LyrN) return true;
if(!noGr){
var lc = cntLyrS(actv);
if(lc && lc<LyrN-1) LyrN -= lc;
}
return movLyr(LyrN-1);
}
And even tho it looks pretty cumbersome and scary - i doubt that it will perform much slower. And as a bonus it will create minimal amount of actions in the history (no unnecessary layer moves) + it will correctly work with background layer + it will work properly with the groups (layer-sets): if group is opened - it will create new layer inside of it, and if group is closed it will correctly move layer under the whole group-structure including other possible groups inside the selected one.
Use it like that: mkLyrBelow(); to create new layer under selected one, or mkLyrBelow(LayerNumber); to create layer under another one via it's number, also u can optionally add 2d parameter to ignore groups (it will move new layer inside the group even if it's closed): mkLyrBelow(LayerNumber,true); or mkLyrBelow(0,1);...
P.S. don't get me wrong about ActionRefs - they're not the silver bullet, just oftenly have some more convenience in the end, but ofc best results obtained when u combine ARef's with native API. Just believe me on that, i've coded my first PS script like 8 years ago, so i've tried pretty much everything =)
If I understand your question correctly, Photoshop already has these shortcuts
Ctrl+Shift+N (Creating New Layer)
Ctrl+] (To move the layer up)
Ctrl+[ (To move the layer down)
Related
Not sure if I'm doing this right. I'm trying to locate a layer. I can normally do that by group name & layer name. However that does present problems if there are duplicate names. So instead I'll try and find their unique layer ID.
I think this is correct:
var srcDoc = app.activeDocument;
var numOfLayers = srcDoc.layers.length;
// main loop
for (var i = numOfLayers -1; i >= 0 ; i--)
{
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), i);
var layerDesc = executeActionGet(ref);
var layerID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var currentLayer = srcDoc.layers[i].name;
alert(layerID + " " + currentLayer);
}
... Only I expected the ID to be a larger random string, not a int. Firstly, have I got this right? And secondly is there a way to get the layer ID from the activeLayer?
IDs are interegers in PS and they are unique for a document only: they always start at 1 and then new layers and layer operations change ID counter by +1 so it's normal to have IDs in hundreds after a while.
To get an id of the active layer, change the reference to target:
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt')); // reference is active layer
var layerDesc = executeActionGet(ref);
var layerID = layerDesc.getInteger(stringIDToTypeID('layerID'));
alert(layerID);
P.S. this will work only with one active layer. For multiple layers you'll have you use a function I posted here: Get selected layers
P.P.S. note that your original code won't work with groups: indices of DOM and indices of AM aren't the same. You need to traverse layers in AM list to get proper indices.
_context.Update(v) ;
_context.SaveChanges();
When I use this code then SQL Server adds a new record instead of updating the
current context
[HttpPost]
public IActionResult PageVote(List<string> Sar)
{
string name_voter = ViewBag.getValue = TempData["Namevalue"];
int count = 0;
foreach (var item in Sar)
{
count = count + 1;
}
if (count == 6)
{
Vote v = new Vote()
{
VoteSarparast1 = Sar[0],
VoteSarparast2 = Sar[1],
VoteSarparast3 = Sar[2],
VoteSarparast4 = Sar[3],
VoteSarparast5 = Sar[4],
VoteSarparast6 = Sar[5],
};
var voter = _context.Votes.FirstOrDefault(u => u.Voter == name_voter && u.IsVoted == true);
if (voter == null)
{
v.IsVoted = true;
v.Voter = name_voter;
_context.Add(v);
_context.SaveChanges();
ViewBag.Greeting = "رای شما با موفقیت ثبت شد";
return RedirectToAction(nameof(end));
}
v.IsVoted = true;
v.Voter = name_voter;
_context.Update(v);
_context.SaveChanges();
return RedirectToAction(nameof(end));
}
else
{
return View(_context.Applicants.ToList());
}
}
You need to tell the DbContext about your entity. If you do var vote = new Vote() vote has no Id. The DbContext see this and thinks you want to Add a new entity, so it simply does that. The DbContext tracks all the entities that you load from it, but since this is just a new instance, it has no idea about it.
To actually perform an update, you have two options:
1 - Load the Vote from the database in some way; If you get an Id, use that to find it.
// Loads the current vote by its id (or whatever other field..)
var existingVote = context.Votes.Single(p => p.Id == id_from_param);
// Perform the changes you want..
existingVote.SomeField = "NewValue";
// Then call save normally.
context.SaveChanges();
2 - Or if you don't want to load it from Db, you have to manually tell the DbContext what to do:
// create a new "vote"...
var vote = new Vote
{
// Since it's an update, you must have the Id somehow.. so you must set it manually
Id = id_from_param,
// do the changes you want. Be careful, because this can cause data loss!
SomeField = "NewValue"
};
// This is you telling the DbContext: Hey, I control this entity.
// I know it exists in the DB and it's modified
context.Entry(vote).State = EntityState.Modified;
// Then call save normally.
context.SaveChanges();
Either of those two approaches should fix your issue, but I suggest you read a little bit more about how Entity Framework works. This is crucial for the success (and performance) of your apps. Especially option 2 above can cause many many issues. There's a reason why the DbContext keep track of entities, so you don't have to. It's very complicated and things can go south fast.
Some links for you:
ChangeTracker in Entity Framework Core
Working with Disconnected Entity Graph in Entity Framework Core
I'm trying to create a purely JXA-ObjC approach to getting pixel colors from image paths. Here's what I have currently:
ObjC.import('Foundation')
ObjC.import('AppKit')
var c_filePath = $(picturePath)
var c_img = $.NSImage.alloc.initWithContentsOfFile(c_filePath)
if(c_img==$()){
return []
}
var c_point = $.NSMakePoint(x,y)
c_img.lockFocus() //Error - Undefined is not a function...?
var c_color = NSReadPixel(c_point)
c_img.unlockFocus() //Error - Undefined is not a function...?
c_img.release()
var r; var g; var b; var a
c_img.getRegGreenBlueAlpha($(r),$(g),$(b),$(a))
r = ObjC.unwrap(r)
g = ObjC.unwrap(g)
b = ObjC.unwrap(b)
a = ObjC.unwrap(a)
This code is heavily based off of the code found here.
However, as shown above c_img.lockFocus() is undefined according to JXA. Oddly I can get access to c_img.lockFocusFlipped(), however I'm not sure how to use this and/or if it can be used for the same purpose as lockFocus().
Is there an obvious problem here? Or is there a better way to get the pixel colour of an image?
Any help would be grateful.
It looks like I am too used to methods requiring parenthesis. TylerGaw however told me that this is not necessarily the case.
ObjC.import('Foundation')
ObjC.import('AppKit')
var c_filePath = $(picturePath)
var c_img = $.NSImage.alloc.initWithContentsOfFile(c_filePath)
if(c_img==$()){
return []
}
var c_point = $.NSMakePoint(x,y)
c_img.lockFocus
var c_color = NSReadPixel(c_point)
c_img.unlockFocus
c_img.release
appears to work as expected.
I'm trying to get similar Document of another one . I'm using the Lucene.Net MoreLikeThis-Class to achieve this. For this i seperate my Documents in multiple Fields - Title and Content. Now creating the actual query results in an empty query without interesting Terms.
My could looks like this:
var queries = new List<Query>();
foreach(var docField in docFields)
var similarSearch = new MoreLikeThis(indexReader);
similarSearch.SetFieldNames(docField.fieldName);
similarSearch.Analyzer = new GermanAnalyzer(Version.LUCENE_30, new HashSet<string>(StopWords));
similarSearch.MinDocFreq = 1;
similarSearch.MinTermFreq = 1;
similarSearch.MinWordLen = 1;
similarSearch.Boost = true;
similarSearch.BoostFactor = boostFactor;
using(var reader = new StringReader(docField.Content)){
var searchQuery = similarSearch.Like(reader);
// debugging purpose
var queryString = searchQuery.ToString(); // empty
var terms = similarSearch.RetrieveInterestingTerms(reader); // also empty
queries.Add(searchQuery);
}
var booleanQuery = new BooleanQuery();
foreach(var moreLikeThisQuery in queries)
{
booleanQuery.Add(moreLikeThisQuery, Occur.SHOULD);
}
var topDocs = indexSearcher.Search(booleanQuery, maxNumberOfResults); // and of course no results obtained
So the question is:
Why there are no Terms / why there is no query generated?
I hope important thing's be seen, if not please help me to make my first question better :)
I got it to work.
The problem was, that i worked on the false directory.
I have different Solutions for creating the index and creating the queries and had a missmatch with the index-location.
So the generall solution would be:
Is your Querygenerating-Class fully initialized? (MinDocFreq, MinTermFreq, MinWordLen, has a Analyzer, set the fieldNames)
Is your used IndexReader correctly initialized?
I have a special case when I want to do something like
let predicate = NSPredicate(format:"
DISTANCE(\(UserLocation),photoLocation) <= visibleRadius AND
DISTANCE(\(UserLocation),photoLocation" <= 10)"
var query = PFQuery(className:"Photo", predicate:predicate)
Basically, I want to get all photos that are taken within 10km around my current location if my current location is also within the photo's visible radius
Also, photoLocation and visibleRadius are two columns in the database, I will supply UserLocation as a PFGeoPoint.
Is it possible to achieve this? In my opinion, I don't think that I may call, for example, photoLocation.latitude to get a specific coordinate value. May I?
I'll appreciate you a lot if this can be achieved!!
I found this at the pares.com docs here is the link
let swOfSF = PFGeoPoint(latitude:37.708813, longitude:-122.526398)
let neOfSF = PFGeoPoint(latitude:37.822802, longitude:-122.373962)
var query = PFQuery(className:"PizzaPlaceObject")
query.whereKey("location", withinGeoBoxFromSouthwest:swOfSF, toNortheast:neOfSF)
var pizzaPlacesInSF = query.findObjects()
This code fetch you all the objects that are in a rectangle area defined by the swOfSF & neOfSF objectc, where seOfSF is in the south-west corner and neOfSF is in the north-east corner.
You can make some alterations to the code and get all the objects in rectangle area that your object is in middle
i would recommend that you don't use a radius, because it will take a lot of calculations. Instead use a rectangle area (like in the code i gave you).
just calculate what is the max/min longitude & max/min latitude from your position and fetch all the objects that are in between. you can read about how to fine the min/max longitude & latitude here Link
I managed to solve it using Parse Cloud Code, here is the quick tutorial
Parse.Cloud.define("latestPosts", function(request, response) {
var limit = 20;
var query = new Parse.Query("Post");
var userLocation = request.params.userLocation;
var searchScope = request.params.searchScope;
var afterDate = request.params.afterDate;
var senderUserName = request.params.senderUserName;
query.withinKilometers("Location", userLocation, searchScope);
query.greaterThan("createdAt", afterDate);
query.notEqualTo("senderUserName",senderUserName);
query.ascending("createdAt");
query.find({
success: function(results) {
var finalResults = results.filter(function(el) {
var visibleRadius = el.get("VisibleRadius");
var postLocation = el.get("Location");
return postLocation.kilometersTo(userLocation) <= visibleRadius;
});
if (finalResults.length > limit) {
var slicedFinalResults = results.slice(0, 20);
response.success(slicedFinalResults);
} else {
response.success(finalResults);
}
},
error: function() {
response.error("no new post");
}
});
});
The code above illustrate a basic example of how to use Cloud Code. Except, I have to make sure that all the returned image are in the union of user's search scope and photo's visible circle. There are more techniques such as Promises. But for my purpose, the code above should just suffice.