Expressions / adds color and array conversion operators
Also fixes existing error throwingtests which were essentially doing nothing.
This commit is contained in:
@@ -50,6 +50,13 @@ import {asArray, isStringColor} from '../color.js';
|
||||
* * `['between', value1, value2, value3]` returns `1` if `value1` is contained between `value2` and `value3`
|
||||
* (inclusively), or `0` otherwise.
|
||||
*
|
||||
* * Conversion operators:
|
||||
* * `['array', value1, ...valueN]` creates a numerical array from `number` values; please note that the amount of
|
||||
* values can currently only be 2, 3 or 4.
|
||||
* * `['color', red, green, blue, alpha]` creates a `color` value from `number` values; the `alpha` parameter is
|
||||
* optional; if not specified, it will be set to 1.
|
||||
* Note: `red`, `green` and `blue` components must be values between 0 and 255; `alpha` between 0 and 1.
|
||||
*
|
||||
* Values can either be literals or another operator, as they will be evaluated recursively.
|
||||
* Literal values can be of the following types:
|
||||
* * `number`
|
||||
@@ -265,6 +272,11 @@ function assertArgsMinCount(args, count) {
|
||||
throw new Error(`At least ${count} arguments were expected, got ${args.length} instead`);
|
||||
}
|
||||
}
|
||||
function assertArgsMaxCount(args, count) {
|
||||
if (args.length > count) {
|
||||
throw new Error(`At most ${count} arguments were expected, got ${args.length} instead`);
|
||||
}
|
||||
}
|
||||
function assertArgsEven(args) {
|
||||
if (args.length % 2 !== 0) {
|
||||
throw new Error(`An even amount of arguments was expected, got ${args} instead`);
|
||||
@@ -492,6 +504,42 @@ Operators['between'] = {
|
||||
return `(${value} >= ${min} && ${value} <= ${max})`;
|
||||
}
|
||||
};
|
||||
Operators['array'] = {
|
||||
getReturnType: function(args) {
|
||||
return ValueTypes.NUMBER_ARRAY;
|
||||
},
|
||||
toGlsl: function(context, args) {
|
||||
assertArgsMinCount(args, 2);
|
||||
assertArgsMaxCount(args, 4);
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
assertNumber(args[i]);
|
||||
}
|
||||
const parsedArgs = args.map(function(val) {
|
||||
return expressionToGlsl(context, val, ValueTypes.NUMBER);
|
||||
});
|
||||
return `vec${args.length}(${parsedArgs.join(', ')})`;
|
||||
}
|
||||
};
|
||||
Operators['color'] = {
|
||||
getReturnType: function(args) {
|
||||
return ValueTypes.COLOR;
|
||||
},
|
||||
toGlsl: function(context, args) {
|
||||
assertArgsMinCount(args, 3);
|
||||
assertArgsMaxCount(args, 4);
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
assertNumber(args[i]);
|
||||
}
|
||||
const array = /** @type {number[]} */(args);
|
||||
if (args.length === 3) {
|
||||
array.push(1);
|
||||
}
|
||||
const parsedArgs = args.map(function(val, i) {
|
||||
return expressionToGlsl(context, val, ValueTypes.NUMBER) + (i < 3 ? ' / 255.0' : '');
|
||||
});
|
||||
return `vec${args.length}(${parsedArgs.join(', ')})`;
|
||||
}
|
||||
};
|
||||
Operators['interpolate'] = {
|
||||
getReturnType: function(args) {
|
||||
let type = ValueTypes.COLOR | ValueTypes.NUMBER;
|
||||
|
||||
@@ -138,7 +138,8 @@ describe('ol.style.expressions', function() {
|
||||
expect(getValueType(['==', 10, ['get', 'attr4']])).to.eql(ValueTypes.BOOLEAN);
|
||||
expect(getValueType(['between', ['get', 'attr4'], -4.0, 5.0])).to.eql(ValueTypes.BOOLEAN);
|
||||
expect(getValueType(['!', ['get', 'attr4']])).to.eql(ValueTypes.BOOLEAN);
|
||||
expect(getValueType(['interpolate', ['get', 'attr4'], [255, 255, 255, 1], 'transparent'])).to.eql(ValueTypes.COLOR);
|
||||
expect(getValueType(['array', ['get', 'attr4'], 1, 2, 3])).to.eql(ValueTypes.NUMBER_ARRAY);
|
||||
expect(getValueType(['color', ['get', 'attr4'], 1, 2])).to.eql(ValueTypes.COLOR);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -171,6 +172,8 @@ describe('ol.style.expressions', function() {
|
||||
expect(expressionToGlsl(context, ['==', 10, ['get', 'attr4']])).to.eql('(10.0 == a_attr4)');
|
||||
expect(expressionToGlsl(context, ['between', ['get', 'attr4'], -4.0, 5.0])).to.eql('(a_attr4 >= -4.0 && a_attr4 <= 5.0)');
|
||||
expect(expressionToGlsl(context, ['!', ['get', 'attr4']])).to.eql('(!a_attr4)');
|
||||
expect(expressionToGlsl(context, ['array', ['get', 'attr4'], 1, 2, 3])).to.eql('vec4(a_attr4, 1.0, 2.0, 3.0)');
|
||||
expect(expressionToGlsl(context, ['color', ['get', 'attr4'], 1, 2, 0.5])).to.eql('vec4(a_attr4 / 255.0, 1.0 / 255.0, 2.0 / 255.0, 0.5)');
|
||||
});
|
||||
|
||||
it('correctly adapts output for fragment shaders', function() {
|
||||
@@ -201,17 +204,39 @@ describe('ol.style.expressions', function() {
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).to.be(true);
|
||||
|
||||
thrown = false;
|
||||
try {
|
||||
expressionToGlsl(context, ['<', 0, 'aa']);
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).to.be(true);
|
||||
|
||||
thrown = false;
|
||||
try {
|
||||
expressionToGlsl(context, ['+', true, ['get', 'attr']]);
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).to.be(true);
|
||||
|
||||
thrown = false;
|
||||
try {
|
||||
expressionToGlsl(context, ['color', 1, 2, 'red']);
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).to.be(true);
|
||||
|
||||
thrown = false;
|
||||
try {
|
||||
expressionToGlsl(context, ['array', 1, '2', 3]);
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).to.be(true);
|
||||
});
|
||||
|
||||
it('throws with the wrong number of arguments', function() {
|
||||
@@ -221,31 +246,43 @@ describe('ol.style.expressions', function() {
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).to.be(true);
|
||||
|
||||
thrown = false;
|
||||
try {
|
||||
expressionToGlsl(context, ['<', 4]);
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).to.be(true);
|
||||
|
||||
thrown = false;
|
||||
try {
|
||||
expressionToGlsl(context, ['+']);
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).to.be(true);
|
||||
|
||||
thrown = false;
|
||||
try {
|
||||
expressionToGlsl(context, ['array', 1]);
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).to.be(true);
|
||||
|
||||
thrown = false;
|
||||
try {
|
||||
expressionToGlsl(context, ['color', 1, 2, 3, 4, 5]);
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
expect(thrown).to.be(true);
|
||||
});
|
||||
|
||||
it('throws on invalid expressions', function() {
|
||||
let thrown = false;
|
||||
try {
|
||||
expressionToGlsl(context, true);
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
try {
|
||||
expressionToGlsl(context, [123, 456]);
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
try {
|
||||
expressionToGlsl(context, null);
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user