Auto-generate LESS styles for sprite icons - less

I have icon sprites image with each icon in a 20 by 20 pixel area. Each icon has several variants (black, colour, white small etc.). And have a significant amount of them. Instead of writing styles for each individual icon I'd rather just provide their names in my LESS file and let the processor generate styles for them.
This is what I came up with but it doesn't seem to work.
#icons: upvote,downvote,comment,new,notify,search,popup,eye,cross;
#array: ~`(function(i){ return (i + "").replace(/[\[\] ]/gi, "").split(","); })("#{icons}")`;
#count: ~`(function(i){ return i.split(",").length; })("#{icons}")`;
.iconize (#c) when (#c < #count) {
#val: ~`(function(a){ return a.replace(" ","").split(",")[0]; })("#{array}")`;
#array: ~`(function(a){ a = a.replace(" ","").split(","); a.splice(0, 1); return a; })("#{array}")`;
&.#{val} { background-position: (-20px * #c) 0; }
&.color.#{val} { background-position: (-20px * #c) -20px; }
&.white.#{val} { background-position: (-20px * #c) -40px; }
.iconize(#c + 1);
}
.iconize(#c) when (#c = #count) {}
.iconize(0);
The only thing I'd like to edit is the #icons variable where I just enter their names. And I'm using Web Essentials addin for Visual Studio 2013 to automatically process my LESS file on file save.
What am I doing wrong?

Pure LESS (assuming you're using Web Essentials 2013 which uses LESS 1.5.x):
#icons: upvote, downvote, comment, new, notify, search, popup, eye, cross;
.iconize();
.iconize(#i: length(#icons)) when (#i > 0) {
.iconize((#i - 1));
#value: extract(#icons, #i); // LESS arrays are 1-based
.#{value} {background-position: (-20px * (#i - 1)) 0}
.color.#{value} {background-position: (-20px * (#i - 1)) -20px}
.white.#{value} {background-position: (-20px * (#i - 1)) -40px}
}
I removed & from selector names since it has no effect when you generate these classes in the global scope (but put it back if you actually need .iconize to be nested in another ruleset). It is also possible to calculate array length in earlier LESS versions (that have no length function) w/o any javascript, but I don't list this method here since it's quite scary (and you don't need it anyway).
Your javascript based loop is in fact less or more correct but the problem is all values returned by LESS inline javascript are of so-called "anonymous value" type and not a numbers so that when (#c < #count) condition is always true and the loop becomes infinite. (basically the condition is expanded exactly as when (0 < ~'9') ... when (9 < ~'9') = true etc.)

I think it depends on the version of LESS you use. Different versions of LESS handle array like structures and their length different.
Since LESS 1.5 you can define an array with quotes, like:
#array: "value1","value2"; and calculate its length with length(#array).
For example see also:
Sprites LESS CSS Variable increment issue
With LESS 1.5 your code ends in an endless loop: "SyntaxError: Maximum call stack size exceeded in"

Related

LESS conditional variable change inside mixin

I need to achieve such effect, but even when #padding actually < #height it still use multiplier value 2, which is non-sense...Is there any limitation i don't know about?
.btn-svg-offset(#height, #padding) {
#paddings-n: floor(#height / #padding);
#multiplier: 2;
& when (#padding < #height) {
#multiplier: 1;
}
#btn-svg-offset: #padding + ((#height / #multiplier) * #paddings-n);
};
Any workarounds are welcome)
& when is not if (they usually say so just for short). & {...} is still a regular ruleset with its own scope, and variables defined inside a ruleset are not visible in outer scopes.
To achieve what you need, rewrite this using conditional mixins (mixin's internals (incl. variables) are actually expanded into the caller scope):
.btn-svg-offset(#height, #padding) {
#paddings-n: floor(#height / #padding);
.-() {#multiplier: 2} .-;
.-() when (#padding < #height) {
#multiplier: 1;
}
#btn-svg-offset: #padding + ((#height / #multiplier) * #paddings-n);
}
Note that you can put the same condition onto the .btn-svg-offset mixin itself (so in real code it does not have to be that verbose as in my example... Exact code may vary though depending on the mixin usage and its other internals).
(Upd.) For example the following code (certain variations are possible too) would be an equivalent:
.btn-svg-offset(#height, #padding, #multiplier: 2) {
#paddings-n: floor(#height / #padding);
#btn-svg-offset: #padding + #height / #multiplier * #paddings-n;
}
.btn-svg-offset(#height, #padding) when (#padding < #height) {
.btn-svg-offset(#height, #padding, 1);
}

Looping with iterator vs temp object gives different result graphically (Libgdx/Java)

I've got a particle "engine" whom I've implementing a Pool system to and I've tested two different ways of rendering every Particle in a list. Please note that the Pooling really doesn't have anything with the problem to do. I just followed a tutorial and tried to use the second method when I noticed that they behaved differently.
The first way:
for (int i = 0; i < particleList.size(); i++) {
Iterator<Particle> it = particleList.iterator();
while (it.hasNext()) {
Particle p = it.next();
if (p.isDead()){
it.remove();
}
p.render(batch, delta);
}
}
Which works just fine. My particles are sharp and they move with the correct speed.
The second way:
Particle p;
for (int i = 0; i < particleList.size(); i++) {
p = particleList.get(i);
p.render(batch, delta);
if (p.isDead()) {
particleList.remove(i);
bulletPool.free(p);
}
}
Which makes all my particles blurry and moving really slow!
The render method for my particles look like this:
public void render(SpriteBatch batch, float delta) {
sprite.setX(sprite.getX() + (dx * speed) * delta * Assets.FPS);
sprite.setY(sprite.getY() + (dy * speed) * delta * Assets.FPS);
ttl--;
sprite.setScale(sprite.getScaleX() - 0.002f);
if (ttl <= 0 || sprite.getScaleX() <= 0)
isDead = true;
sprite.draw(batch);
}
Why do the different rendering methods provide different results?
Thanks in advance
You are mutating (removing elements from) a list while iterating over it. This is a classic way to make a mess.
The Iterator must have code to handle the delete case correctly. But your index-based for loop does not. Specifically when you call particleList.remove(i) the i is now "out of sync" with the content of the list. Consider what happens when you remove the element at index 3: 'i' will increment to 4, but the old element 4 got shuffled down into index 3, so it will get skipped.
I assume you're avoiding the Iterator to avoid memory allocations. So, one way to side-step this issue is to reverse the loop (go from particleList.size() down to 0). Alternatively, you can only increment i for non-dead particles.

wxGrid shows large empty border on right

By default, wxGrid shows a small ( 10 pixels? ) blank border on the right hand side, after the last column. Calling SetMargins() has no effect on it.
It is irritating, but I can live with it.
However, if I set the the row label width to zero then the blank border grows much larger. If I have just one column, the effect is horrible. It looks like wxGrid is leaving room for the non-existent label.
myPatGrid = new wxGrid(panel,IDC_PatGrid,wxPoint(10,10),wxSize(150,300) );
myPatGrid->SetRowLabelSize(0);
myPatGrid->CreateGrid(200,1);
myPatGrid->SetColLabelValue(0,L"Patient IDs");
Is there a way to remove this border?
Note that if I set the size of the wxgrid window to narrower in the wxGrid constructor, hoping to hide the border, I now get a horizontal scroll bar which is horrible too.
myPatGrid = new wxGrid(panel,IDC_PatGrid,wxPoint(10,10),wxSize(100,300) );
myPatGrid->SetRowLabelSize(0);
myPatGrid->CreateGrid(200,1);
myPatGrid->SetColLabelValue(0,L"Patient IDs");
Gives me
I just upgraded to wxWidgets v2.8.12 - problem still exists.
I didn't find an "autosize" function to fit columns in the grid space.
As a workaround, if you have only one column set its width to
myPatGrid->SetColMinimalWidth(0, grid_width - wxSYS_VSCROLL_X - 10)
otherwise, sum other column's width and adapt the last one to fit the remaining space (minus scrollbar width, minus 10).
EDIT: I have a working example, which produces this:
int gridSize = 150;
int minSize = gridSize - wxSYS_VSCROLL_X - 2; // scrollbar appear if higher
grid->SetRowLabelSize(0);
grid->SetColMinimalWidth(0, minSize);
grid->SetColSize(0, minSize); // needed, otherwise column will not resize
grid->ForceRefresh();
grid->SetColLabelValue(0, "COORD");
EDIT2: I succeded to remove the remaining margin with this:
int gridSize = 150;
int minSize = gridSize - 16; // trial & error
grid->SetMargins(0 - wxSYS_VSCROLL_X, 0);
Solving something similar yesterday I would like to contribute with following what does the job for me. Perhaps this is going to help someone else:
void RecalculateGridSize(wxGrid *grid, int cols) {
if (grid == NULL)
return;
grid->AutoSizeColumns();
float cumulative = 0, param = 0;
for (int i = 0; i < cols; ++i)
cumulative += grid->GetColSize(i);
//not stretching when client size lower then calculated
if(grid->GetClientSize().x < cumulative)
return;
param = (float) grid->GetClientSize().x / cumulative;
for (int i = 0; i < cols; ++i) {
if (i != cols - 1)
grid->SetColSize(i, int(grid->GetColSize(i)*param) - 2); //-2 for each line per column
else
grid->SetColSize(i, int(grid->GetColSize(i)*param)); //leaving last column full to fill properly
}
}
Note: This is doing particularly well when linked with OnSize() event.

Optimising loops for pixel processing

I'm implementing an algorithm (in OpenCV) that iterates over every pixel in an image, and for each pixel calculates block matches with pixels in the neighbourhood in order to evalaute the similarity of these neighbouring pixels. A "naive" implementation with very deep loops is very slow, so I was wondering how I might try to improve the performance. The following is an extract of my current code:
for(nCh=1;nCh<=channels;nCh++) { // Loop over three channels
for(i=0;i<h;i++) { // "vertical" loop
for(j=0;j<w;j++) { // "horizontal" loop
for (si=-sw_height; si<sw_height; si++){ // vertical search window loop
for (sj=-sw_width; sj<sw_width; sj++){ // horizontal search window loop
dist = 0;
for (blki=0; blki<blk_height; blki++){ // block match loop
for (blkj=0; blkj<blk_width; blkj++){ // block match loop
current_pxl = data[(i+blki)*step+(j+blkj)*channels+nCh];
search_pxl = data[(i+blki+si)*step+(j+blkj+sj)*channels+nCh];
dist += pow((current_pxl - search_pxl),2);
}
}
// ... further processing
}
}
}
}
}
You're calling pow in the innermost loop. Don't.
Also you're doing a lot of index calculation in there.
I bet you can move some out that out of the inner loop.
You should be able to get it so your inner loop looks more like this:
for (blkj = 0; blkj < blk_width; blkj++, pc += channels, ps += channels){
int diff = (*pc - *ps);
dist += (diff * diff);
}
And then, you might even want to unroll it a bit.
BTW, a little more whitespace might help :-)

Create a padded box mixin with Compass and Blueprint

The interface should look like this
+box(optional_padding_value_in_columns)
It shouldn't break the grid. (If placed in column that spans 7 units, then the box should stay within the 7 units.)
Compass _scaffolding.sass actually includes this little number:
// Mixin +box to create a padded box inside a column.
=box
:padding 1.5em
:margin-bottom 1.5em
:background #E5ECF9
But the padding blows up the grid.
The +box mixin is meant for a block element used inside a column. The 1.5em padding is not proportional to the blueprint column width so putting it on a column element will break the layout.
Try this:
// You can supply one padding value or all 4
=padded_column(!n, !p1, !p2=!p1, !p3=!p1, !p4=!p1)
+column(!n)
:padding= !p1 !p2 !p3 !p4
!width = !blueprint_grid_width * !n + (!blueprint_grid_margin * (!n - 1)) - !p2 - !p4
.padded_box
+padded_column(!two_columns_secondary, 10px, 0, 5px, 15px)
:background #f0f0f0