Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Select Polygons/Lines by color?

Question:  Is is possible, using the API, to select every drawn object on a map by color? Details:  I use different colors on the dynamic lighting layer for different purposes.  I'd like to be able to select all of the Red lines using the API and move them to another region and then back to the original position again (or I might just move them to the GM layer for a bit, but I might find that annoying since I would constantly see them). I'll try to code it myself if it's possible.  But I don't want to waste time trying if it's not.  At the moment, I have no clue how I'd do it, but I don't mind doing research.  Any tips would be welcome.  :)
1453768976
The Aaron
Pro
API Scripter
You can definitely filter your lines based on a given color.  Here's some sample code that will print out a breakdown of the number of lines of each color in all the pages in a game: on('ready',function(){   'use strict';   sendChat('Colors',   _.chain(findObjs({type: 'path'}))     .reduce(function(m,path){       var color = path.get('stroke') || 'missing';       m[color]=(m[color] ? m[color]+1 : 1);       return m;     },{})     .map(function(number,color){       return 'There are '+number+' lines with the color '+color+'.';     })     .tap(log)     .value()     .join('<br>')   ); });
1453769044
The Aaron
Pro
API Scripter
Note, you cannot affect the selection in the client, but you could operate on all those lines, moving them off screen or putting them on the GM layer or some such.
1453770654

Edited 1453772384
Lithl
Pro
Sheet Author
API Scripter
function selectLinesByColor(color, options) { options = options || {}; if (color !== 'transparent') { if (_.isString(color) && color.indexOf('#') !== 0) color = '#' + color; if (_.isString(color) && !parseInt(color.substring(1), 16)) { log(color + ' is not a valid color'); return []; } else if (!_.isNumber(color)) { log (color + ' is not a number'); return []; } } return filterObjs(function(obj) { var colorMatch, hue, hueMatch; if (obj.get('type') !== 'path') return false; if (options.layer && obj.get('layer') !== options.layer) return false; if (options.pages && options.pages.length > 0 && !_.contains(options.pages, obj.get('pageid'))) return false; colorMatch = options.matchFill ? obj.get('fill') : obj.get('stroke'); if (options.epsilon && color !== 'transparent') { if (colorMatch === 'transparent') return false; hue = rgbToHsv(parseInt(color.substring(1), 16)).hue; hueMatch = rgbToHsv(parseInt(colorMatch.substring(1), 16)).hue; return Math.abs(hue - hueMatch) <= options.epsilon; } else { return colorMatch === color; } }); } function rgbToHsv(rgb) { var r = (rgb >> 16) / 255, g = ((rgb >> 8) & 255) / 255, b = (rgb & 255) / 255, max = Math.max(r, g, b), min = Math.min(r, g, b), h, s, l = (max + min) / 2, d; if (max === min) { h = s = 0; } else { d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { hue: h, saturation: s, value: v }; } The selectLinesByColor function will return a list of Path objects which you can manipulate with more API code, such as setting their top and left properties to move them, or setting their layer property to switch their layer. There is no means in the API to actually select  an object such that you can then manipulate the group of selected objects with your cursor. The above code accepts a color , which may be the string "transparent", a string hex value with or without a leading hash (#), or an integer. It also accepts an optional options object, which can let you specify a specific layer to search (with the string options.layer ; if omitted, all layers will be searched), specific pages to search (with the array of strings options.pages ; if omitted or an empty array, all pages will be searched), whether to match the fill color instead of the stroke color (with the boolean options.matchFill ; if false or omitted, the stroke color will be matched against), and whether to match paths that are close  in color (with the number options.epsilon ; if given a value, the difference in the hues of the colors will be compared. The hue values will be in the [0..1] range, so any epsilon value at 1 or greater would match all paths, regardless of the supplied color , and any epsilon value less than 0 will match no paths. An epsilon of exactly zero will match paths with identical hues only, but they may have different saturations or values.) Disclaimer: The above code has not been tested.
Thank you!  That should give me enough information for what I want to do. As usual, the Scriptomancer is here to assist us lesser mortals.
Wow, Brian, ty!  Unfortunately something just came up and I won't be able to test your script tonight.  But tomorrow I should get time and I'll let you know how it works.
Brian said: The above code accepts a color , which may be the string "transparent", a string hex value with or without a leading hash (#), or an integer.  I tried debugging it myself, but I'm not having much luck.  It works if I send an integer, or use "transparent" but if I send the color code for red "#ff0000", with or without the hash, it tells me that "#ff0000 is not a number".
Update:  If I ignore the portion of the code that tries to determine if the value I send is valid, I can use your code to select the paths by color just fine. I am currently able to send paths from the walls layer to the gm layer.  And that's all that I needed.  If I decide I need to move them, I'm sure it'll work just as well. So thank you very much!