Compare commits

...

31 Commits

Author SHA1 Message Date
be41c95ab3 use texture map to create dotted plot lines 2020-07-07 11:19:37 -07:00
a6d16409b9 use physical coordinates for distance comparisons 2020-07-06 16:30:22 -07:00
d55466f2c9 Merge branch 'plots/customization' into plots/customization-line 2020-07-06 13:18:30 -07:00
0ef977ebee Merge branch 'master' into plots/customization 2020-07-06 12:46:10 -07:00
41141aa11c access correct file 2020-07-06 12:22:46 -07:00
9ceb3c5b1e Merge pull request #3130 from nasa/display-layout-fix-3128
[Display Layouts] Prevent duplicate from being added when composition 'add' is fired
2020-07-06 11:36:25 -07:00
5ca38c0f43 draw dotted lines using webGL 2020-07-02 16:14:32 -07:00
bee3a9eedf Merge branch 'master' into display-layout-fix-3128 2020-07-02 10:48:53 -07:00
e515d19acd Merge pull request #3144 from nasa/switching-type-error
Fix for non working switch from alpha to tables and plots
2020-07-02 10:38:01 -07:00
dd13efe065 Merge branch 'master' into switching-type-error 2020-07-02 10:26:13 -07:00
b5dfbe268c Merge pull request #3146 from nasa/new-folder-action-fix-07012020
Added unnamed folder and made it required
2020-07-01 16:48:10 -07:00
a9b9107cc3 change icon and action name 2020-07-01 16:30:03 -07:00
cfda4e4214 added unnamed folder and required 2020-07-01 16:20:33 -07:00
0a657de4b2 Fix for non working switch from alpha to tables 2020-07-01 16:09:05 -07:00
8153edb9cb Update any/all criterion when telemetry is removed (#3138)
Co-authored-by: Andrew Henry <akhenry@gmail.com>
2020-07-01 12:22:47 -07:00
246aee0029 add inspector display text helper functions 2020-06-30 22:22:59 -07:00
52c918455a Merge branch 'plots/customization' into plots/customization-line 2020-06-30 21:48:53 -07:00
f0cde1055d helper function for marker options display in inspector
refactor for clarity
2020-06-30 21:38:28 -07:00
07b2aeaae1 add missing semi-colon 2020-06-30 14:10:45 -07:00
c4736f3cac add canvas 2d draw line styles 2020-06-30 13:06:08 -07:00
0d91b88eb1 add select and display line style to inspector 2020-06-30 12:04:04 -07:00
ac1ff36c20 refactor shape to shape code 2020-06-29 13:29:53 -07:00
e01e263b37 Merge branch 'master' into plots/customization 2020-06-29 13:18:29 -07:00
b80373aee9 refactor for clarity 2020-06-29 12:18:12 -07:00
376ecf93a9 allow point shapes for webGL plots
add circle shape
2020-06-27 15:35:50 -07:00
774726af77 add canvas2d circle marker shape 2020-06-26 16:11:57 -07:00
101f3c022c change line style to line method in anticipation of adding true line style attribute 2020-06-26 15:37:52 -07:00
b4d4945057 allow marker shape selection in plot inspector
add shapes for canvas2d - point, cross, star
2020-06-26 15:32:39 -07:00
dadb6120c2 fix lint error 2020-06-26 14:00:39 -07:00
d9a94db59d prevent composition from adding a dupe into layout 2020-06-26 13:51:03 -07:00
c0780a62ae lineWidth is not supported in modern browsers 2020-06-24 13:29:08 -07:00
12 changed files with 387 additions and 71 deletions

View File

@ -103,6 +103,8 @@ export default class ConditionManager extends EventEmitter {
criterion.operation = ''; criterion.operation = '';
conditionChanged = true; conditionChanged = true;
} }
} else {
conditionChanged = true;
} }
}); });
if (conditionChanged) { if (conditionChanged) {

View File

@ -457,15 +457,43 @@ export default {
this.objectViewMap = {}; this.objectViewMap = {};
this.layoutItems.forEach(this.trackItem); this.layoutItems.forEach(this.trackItem);
}, },
isItemAlreadyTracked(child) {
let found = false,
keyString = this.openmct.objects.makeKeyString(child.identifier);
this.layoutItems.forEach(item => {
if (item.identifier) {
let itemKeyString = this.openmct.objects.makeKeyString(item.identifier);
if (itemKeyString === keyString) {
found = true;
return;
}
}
});
if (found) {
return true;
} else if (this.isTelemetry(child)) {
return this.telemetryViewMap[keyString] && this.objectViewMap[keyString];
} else {
return this.objectViewMap[keyString];
}
},
addChild(child) { addChild(child) {
let keyString = this.openmct.objects.makeKeyString(child.identifier); if (this.isItemAlreadyTracked(child)) {
return;
}
let type;
if (this.isTelemetry(child)) { if (this.isTelemetry(child)) {
if (!this.telemetryViewMap[keyString] && !this.objectViewMap[keyString]) { type = 'telemetry-view';
this.addItem('telemetry-view', child); } else {
} type = 'subobject-view';
} else if (!this.objectViewMap[keyString]) {
this.addItem('subobject-view', child);
} }
this.addItem(type, child);
}, },
removeChild(identifier) { removeChild(identifier) {
let keyString = this.openmct.objects.makeKeyString(identifier); let keyString = this.openmct.objects.makeKeyString(identifier);
@ -566,7 +594,7 @@ export default {
createNewDomainObject(domainObject, composition, viewType, nameExtension, model) { createNewDomainObject(domainObject, composition, viewType, nameExtension, model) {
let identifier = { let identifier = {
key: uuid(), key: uuid(),
namespace: domainObject.identifier.namespace namespace: this.internalDomainObject.identifier.namespace
}, },
type = this.openmct.types.get(viewType), type = this.openmct.types.get(viewType),
parentKeyString = this.openmct.objects.makeKeyString(this.internalDomainObject.identifier), parentKeyString = this.openmct.objects.makeKeyString(this.internalDomainObject.identifier),

View File

@ -24,14 +24,14 @@ import uuid from 'uuid';
export default class NewFolderAction { export default class NewFolderAction {
constructor(openmct) { constructor(openmct) {
this.name = 'New Folder'; this.name = 'Add New Folder';
this.key = 'newFolder'; this.key = 'newFolder';
this.description = 'Create a new folder'; this.description = 'Create a new folder';
this.cssClass = 'icon-folder'; this.cssClass = 'icon-folder-new';
this._openmct = openmct; this._openmct = openmct;
this._dialogForm = { this._dialogForm = {
name: "New Folder Name", name: "Add New Folder",
sections: [ sections: [
{ {
rows: [ rows: [
@ -39,7 +39,9 @@ export default class NewFolderAction {
key: "name", key: "name",
control: "textfield", control: "textfield",
name: "Folder Name", name: "Folder Name",
required: false pattern: "\\S+",
required: true,
cssClass: "l-input-lg"
} }
] ]
} }
@ -53,7 +55,7 @@ export default class NewFolderAction {
dialogService = this._openmct.$injector.get('dialogService'), dialogService = this._openmct.$injector.get('dialogService'),
folderType = this._openmct.types.get('folder'); folderType = this._openmct.types.get('folder');
dialogService.getUserInput(this._dialogForm, {}).then((userInput) => { dialogService.getUserInput(this._dialogForm, {name: 'Unnamed Folder'}).then((userInput) => {
let name = userInput.name, let name = userInput.name,
identifier = { identifier = {
key: uuid(), key: uuid(),

View File

@ -44,19 +44,16 @@
</li> </li>
<li class="grid-row"> <li class="grid-row">
<div class="grid-cell label" <div class="grid-cell label"
title="The line rendering style for this series.">Line Style</div> title="The line style and rendering method to join lines for this series.">Line Method and Style</div>
<div class="grid-cell value">{{ { <div class="grid-cell value">
'none': 'None', {{ series.lineOptionsDisplayText() }}
'linear': 'Linear interpolation',
'stepAfter': 'Step After'
}[series.get('interpolate')] }}
</div> </div>
</li> </li>
<li class="grid-row"> <li class="grid-row">
<div class="grid-cell label" <div class="grid-cell label"
title="Whether markers are displayed, and their size.">Markers</div> title="Whether markers are displayed, and their size.">Markers</div>
<div class="grid-cell value"> <div class="grid-cell value">
{{series.get('markers') ? "Enabled: " + series.get('markerSize') + "px" : "Disabled"}} {{ series.markerOptionsDisplayText() }}
</div> </div>
</li> </li>
<li class="grid-row"> <li class="grid-row">

View File

@ -52,7 +52,7 @@
</li> </li>
<li class="grid-row"> <li class="grid-row">
<div class="grid-cell label" <div class="grid-cell label"
title="The line rendering style for this series.">Line Style</div> title="The rendering method to join lines for this series.">Line Method</div>
<div class="grid-cell value"> <div class="grid-cell value">
<select ng-model="form.interpolate"> <select ng-model="form.interpolate">
<option value="none">None</option> <option value="none">None</option>
@ -61,15 +61,45 @@
</select> </select>
</div> </div>
</li> </li>
<li class="grid-row" ng-show="form.interpolate !== 'none'">
<div class="grid-cell label"
title="The line style for this series.">Line Style</div>
<div class="grid-cell value">
<select ng-model="form.lineStyle">
<option
ng-repeat="option in lineStyleOptions"
value="{{ option.value }}"
ng-selected="option.value === form.lineStyle"
>
{{ option.name }}
</option>
</select>
</div>
</li>
<li class="grid-row"> <li class="grid-row">
<div class="grid-cell label" <div class="grid-cell label"
title="Whether markers are displayed.">Markers</div> title="Whether markers are displayed.">Markers</div>
<div class="grid-cell value"><input type="checkbox" ng-model="form.markers"/></div> <div class="grid-cell value">
<input type="checkbox" ng-model="form.markers"/>
<select
ng-show="form.markers"
ng-model="form.markerShape">
<option
ng-repeat="option in markerShapeOptions"
value="{{ option.value }}"
ng-selected="option.value == form.markerShape"
>
{{ option.name }}
</option>
</select>
</div>
</li> </li>
<li class="grid-row"> <li class="grid-row">
<div class="grid-cell label" <div class="grid-cell label"
title="Display markers visually denoting points in alarm.">Alarm Markers</div> title="Display markers visually denoting points in alarm.">Alarm Markers</div>
<div class="grid-cell value"><input type="checkbox" ng-model="form.alarmMarkers"/></div> <div class="grid-cell value">
<input type="checkbox" ng-model="form.alarmMarkers"/>
</div>
</li> </li>
<li class="grid-row" ng-show="form.markers || form.alarmMarkers"> <li class="grid-row" ng-show="form.markers || form.alarmMarkers">
<div class="grid-cell label" <div class="grid-cell label"

View File

@ -371,7 +371,8 @@ function (
chartElement.getBuffer(), chartElement.getBuffer(),
chartElement.color().asRGBAArray(), chartElement.color().asRGBAArray(),
chartElement.count, chartElement.count,
chartElement.series.get('markerSize') chartElement.series.get('markerSize'),
chartElement.series.get('markerShape')
); );
}; };
@ -379,7 +380,8 @@ function (
this.drawAPI.drawLine( this.drawAPI.drawLine(
chartElement.getBuffer(), chartElement.getBuffer(),
chartElement.color().asRGBAArray(), chartElement.color().asRGBAArray(),
chartElement.count chartElement.count,
chartElement.series.get('lineStyle')
); );
}; };
@ -395,9 +397,10 @@ function (
this.offset.yVal(highlight.point, highlight.series) this.offset.yVal(highlight.point, highlight.series)
]), ]),
color = highlight.series.get('color').asRGBAArray(), color = highlight.series.get('color').asRGBAArray(),
pointCount = 1; pointCount = 1,
shape = highlight.series.get('markerShape');
this.drawAPI.drawPoints(points, color, pointCount, HIGHLIGHT_SIZE); this.drawAPI.drawPoints(points, color, pointCount, HIGHLIGHT_SIZE, shape);
}; };
MCTChartController.prototype.drawRectangles = function () { MCTChartController.prototype.drawRectangles = function () {

View File

@ -25,12 +25,16 @@ define([
'lodash', 'lodash',
'../configuration/Model', '../configuration/Model',
'../lib/extend', '../lib/extend',
'EventEmitter' 'EventEmitter',
'../draw/LineStyles',
'../draw/MarkerShapes'
], function ( ], function (
_, _,
Model, Model,
extend, extend,
EventEmitter EventEmitter,
LINE_STYLES,
MARKER_SHAPES
) { ) {
/** /**
@ -55,7 +59,9 @@ define([
* `interpolate`: interpolate method, either `undefined` (no interpolation), * `interpolate`: interpolate method, either `undefined` (no interpolation),
* `linear` (points are connected via straight lines), or * `linear` (points are connected via straight lines), or
* `stepAfter` (points are connected by steps). * `stepAfter` (points are connected by steps).
* `lineStyle`: string, style of line.
* `markers`: boolean, whether or not this series should render with markers. * `markers`: boolean, whether or not this series should render with markers.
* `markerShape`: string, shape of markers.
* `markerSize`: number, size in pixels of markers for this series. * `markerSize`: number, size in pixels of markers for this series.
* `alarmMarkers`: whether or not to display alarm markers for this series. * `alarmMarkers`: whether or not to display alarm markers for this series.
* `stats`: An object that tracks the min and max y values observed in this * `stats`: An object that tracks the min and max y values observed in this
@ -101,8 +107,10 @@ define([
xKey: options.collection.plot.xAxis.get('key'), xKey: options.collection.plot.xAxis.get('key'),
yKey: range.key, yKey: range.key,
markers: true, markers: true,
markerShape: 'point',
markerSize: 2.0, markerSize: 2.0,
alarmMarkers: true alarmMarkers: true,
lineStyle: 'solid'
}; };
}, },
@ -410,6 +418,36 @@ define([
} else { } else {
this.filters = deepCopiedFilters; this.filters = deepCopiedFilters;
} }
},
lineOptionsDisplayText: function () {
const lineMethods = {
'none': 'None',
'linear': 'Linear interpolation',
'stepAfter': 'Step After'
}
const lineMethodKey = this.get('interpolate');
const lineMethod = lineMethods[lineMethodKey];
if (lineMethod === 'None') {
return lineMethod;
}
const lineStyleKey = this.get('lineStyle');
const lineStyle = LINE_STYLES[lineStyleKey].label;
return `${lineMethod}: ${lineStyle}`;
},
markerOptionsDisplayText: function () {
const showMarkers = this.get('markers');
if (!showMarkers) {
return "Disabled";
}
const markerShapeKey = this.get('markerShape');
const markerShape = MARKER_SHAPES[markerShapeKey].label;
const markerSize = this.get('markerSize');
return `${markerShape}: ${markerSize}px`;
} }
}); });

View File

@ -23,10 +23,14 @@
define([ define([
'EventEmitter', 'EventEmitter',
'../lib/eventHelpers' '../lib/eventHelpers',
'./LineStyles',
'./MarkerShapes'
], function ( ], function (
EventEmitter, EventEmitter,
eventHelpers eventHelpers,
LINE_STYLES,
MARKER_SHAPES
) { ) {
/** /**
@ -84,9 +88,8 @@ define([
this.origin = newOrigin; this.origin = newOrigin;
}; };
Draw2D.prototype.drawLine = function (buf, color, points) { Draw2D.prototype.drawLine = function (buf, color, points, style) {
var i; const pattern = LINE_STYLES[style].pattern;
this.setColor(color); this.setColor(color);
// Configure context to draw two-pixel-thick lines // Configure context to draw two-pixel-thick lines
@ -95,11 +98,12 @@ define([
// Start a new path... // Start a new path...
if (buf.length > 1) { if (buf.length > 1) {
this.c2d.beginPath(); this.c2d.beginPath();
this.c2d.setLineDash(pattern);
this.c2d.moveTo(this.x(buf[0]), this.y(buf[1])); this.c2d.moveTo(this.x(buf[0]), this.y(buf[1]));
} }
// ...and add points to it... // ...and add points to it...
for (i = 2; i < points * 2; i = i + 2) { for (let i = 2; i < points * 2; i = i + 2) {
this.c2d.lineTo(this.x(buf[i]), this.y(buf[i + 1])); this.c2d.lineTo(this.x(buf[i]), this.y(buf[i + 1]));
} }
@ -121,18 +125,17 @@ define([
buf, buf,
color, color,
points, points,
pointSize pointSize,
shape
) { ) {
var i = 0, const drawC2DShape = MARKER_SHAPES[shape].drawC2D.bind(this);
offset = pointSize / 2;
this.setColor(color); this.setColor(color);
for (; i < points; i++) { for (let i = 0; i < points; i++) {
this.c2d.fillRect( drawC2DShape(
this.x(buf[i * 2]) - offset, this.x(buf[i * 2]),
this.y(buf[i * 2 + 1]) - offset, this.y(buf[i * 2 + 1]),
pointSize,
pointSize pointSize
); );
} }

View File

@ -23,30 +23,58 @@
define([ define([
'EventEmitter', 'EventEmitter',
'../lib/eventHelpers' '../lib/eventHelpers',
'./LineStyles',
'./MarkerShapes'
], function ( ], function (
EventEmitter, EventEmitter,
eventHelpers eventHelpers,
LINE_STYLES,
MARKER_SHAPES
) { ) {
// WebGL shader sources (for drawing plain colors) // WebGL shader sources (for drawing plain colors)
var FRAGMENT_SHADER = [ const FRAGMENT_SHADER = `
"precision mediump float;", precision mediump float;
"uniform vec4 uColor;", uniform vec4 uColor;
"void main(void) {", uniform int uLineStyle;
"gl_FragColor = uColor;", uniform int uMarkerShape;
"}" uniform sampler2D uPattern;
].join('\n'), uniform float uPointCount;
VERTEX_SHADER = [ varying float vLengthSoFar;
"attribute vec2 aVertexPosition;",
"uniform vec2 uDimensions;", void main(void) {
"uniform vec2 uOrigin;", if (uMarkerShape == 2) {
"uniform float uPointSize;", float distance = length(2.0 * gl_PointCoord - 1.0);
"void main(void) {", if (distance > 1.0) {
"gl_Position = vec4(2.0 * ((aVertexPosition - uOrigin) / uDimensions) - vec2(1,1), 0, 1);", discard;
"gl_PointSize = uPointSize;", }
"}" }
].join('\n'); gl_FragColor = uColor;
if (uLineStyle == 2) {
gl_FragColor = texture2D(
uPattern,
vec2(fract(vLengthSoFar * 10.0))
);
}
}
`;
const VERTEX_SHADER = `
attribute vec2 aVertexPosition;
attribute float aLengthSoFar;
uniform vec2 uDimensions;
uniform vec2 uOrigin;
uniform float uPointSize;
varying float vLengthSoFar;
void main(void) {
gl_Position = vec4(2.0 * ((aVertexPosition - uOrigin) / uDimensions) - vec2(1,1), 0, 1);
gl_PointSize = uPointSize;
vLengthSoFar = aLengthSoFar;
}
`;
/** /**
* Create a draw api utilizing WebGL. * Create a draw api utilizing WebGL.
@ -90,6 +118,7 @@ define([
this.vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER);
this.gl.shaderSource(this.vertexShader, VERTEX_SHADER); this.gl.shaderSource(this.vertexShader, VERTEX_SHADER);
this.gl.compileShader(this.vertexShader); this.gl.compileShader(this.vertexShader);
this.fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
this.gl.shaderSource(this.fragmentShader, FRAGMENT_SHADER); this.gl.shaderSource(this.fragmentShader, FRAGMENT_SHADER);
this.gl.compileShader(this.fragmentShader); this.gl.compileShader(this.fragmentShader);
@ -104,19 +133,21 @@ define([
// Get locations for attribs/uniforms from the // Get locations for attribs/uniforms from the
// shader programs (to pass values into shaders at draw-time) // shader programs (to pass values into shaders at draw-time)
this.aVertexPosition = this.gl.getAttribLocation(this.program, "aVertexPosition"); this.aVertexPosition = this.gl.getAttribLocation(this.program, "aVertexPosition");
this.aLengthSoFar = this.gl.getAttribLocation(this.program, "aLengthSoFar");
this.uColor = this.gl.getUniformLocation(this.program, "uColor"); this.uColor = this.gl.getUniformLocation(this.program, "uColor");
this.uLineStyle = this.gl.getUniformLocation(this.program, "uLineStyle");
this.uMarkerShape = this.gl.getUniformLocation(this.program, "uMarkerShape");
this.uDimensions = this.gl.getUniformLocation(this.program, "uDimensions"); this.uDimensions = this.gl.getUniformLocation(this.program, "uDimensions");
this.uOrigin = this.gl.getUniformLocation(this.program, "uOrigin"); this.uOrigin = this.gl.getUniformLocation(this.program, "uOrigin");
this.uPointSize = this.gl.getUniformLocation(this.program, "uPointSize"); this.uPointSize = this.gl.getUniformLocation(this.program, "uPointSize");
this.uPointCount = this.gl.getUniformLocation(this.program, "uPointCount");
this.gl.enableVertexAttribArray(this.aVertexPosition); this.gl.enableVertexAttribArray(this.aVertexPosition);
this.gl.enableVertexAttribArray(this.aLengthSoFar);
// Create a buffer to holds points which will be drawn // Create a buffer to holds points which will be drawn
this.buffer = this.gl.createBuffer(); this.buffer = this.gl.createBuffer();
// Use a line width of 2.0 for legibility
this.gl.lineWidth(2.0);
// Enable blending, for smoothness // Enable blending, for smoothness
this.gl.enable(this.gl.BLEND); this.gl.enable(this.gl.BLEND);
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
@ -138,14 +169,62 @@ define([
((v - this.origin[1]) / this.dimensions[1]) * this.height; ((v - this.origin[1]) / this.dimensions[1]) * this.height;
}; };
DrawWebGL.prototype.doDraw = function (drawType, buf, color, points) { DrawWebGL.prototype.doDraw = function (drawType, buf, color, points, shape) {
if (this.isContextLost) { if (this.isContextLost) {
return; return;
} }
const lineStyle = LINE_STYLES[shape] ? LINE_STYLES[shape].drawWebGL : 0;
const shapeCode = MARKER_SHAPES[shape] ? MARKER_SHAPES[shape].drawWebGL : 0;
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, buf, this.gl.DYNAMIC_DRAW); this.gl.bufferData(this.gl.ARRAY_BUFFER, buf, this.gl.DYNAMIC_DRAW);
this.gl.vertexAttribPointer(this.aVertexPosition, 2, this.gl.FLOAT, false, 0, 0); this.gl.vertexAttribPointer(this.aVertexPosition, 2, this.gl.FLOAT, false, 0, 0);
this.gl.uniform4fv(this.uColor, color); this.gl.uniform4fv(this.uColor, color);
this.gl.uniform1i(this.uLineStyle, lineStyle);
this.gl.uniform1i(this.uMarkerShape, shapeCode);
this.gl.uniform1f(this.uPointCount, points);
const lengthSoFar = [0];
for (let i = 1; i < points; i++) {
const lastX = (i - 1) * 2;
const currentX = i * 2;
const xDelta = this.x(buf[lastX]) - this.x(buf[currentX]);
const yDelta = this.y(buf[lastX + 1]) - this.y(buf[currentX + 1]);
const distance = Math.sqrt(
Math.pow(xDelta, 2)
+ Math.pow(yDelta, 2)
);
lengthSoFar.push(lengthSoFar[i - 1] + distance);
}
let lineBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, lineBuffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(lengthSoFar), this.gl.DYNAMIC_DRAW);
this.gl.vertexAttribPointer(this.aLengthSoFar, 1, this.gl.FLOAT, false, 0, 0);
const mappedColor = color.map(function (c, i) {
return Math.floor(c * 255);
});
const dots = [
...mappedColor,
0,0,0,0,
0,0,0,0,
0,0,0,0,
];
var texture = this.gl.createTexture();
this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
this.gl.texImage2D(
this.gl.TEXTURE_2D, 0, this.gl.RGBA, dots.length / 4, 1, 0,
this.gl.RGBA, this.gl.UNSIGNED_BYTE, new Uint8Array(dots));
this.gl.texParameteri(
this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
this.gl.texParameteri(
this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
this.gl.drawArrays(drawType, 0, points); this.gl.drawArrays(drawType, 0, points);
}; };
@ -198,24 +277,26 @@ define([
* the line, as an RGBA color where each element * the line, as an RGBA color where each element
* is in the range of 0.0-1.0 * is in the range of 0.0-1.0
* @param {number} points the number of points to draw * @param {number} points the number of points to draw
* @param {string} style the line style
*/ */
DrawWebGL.prototype.drawLine = function (buf, color, points) { DrawWebGL.prototype.drawLine = function (buf, color, points, style) {
if (this.isContextLost) { if (this.isContextLost) {
return; return;
} }
this.doDraw(this.gl.LINE_STRIP, buf, color, points);
this.doDraw(this.gl.LINE_STRIP, buf, color, points, style);
}; };
/** /**
* Draw the buffer as points. * Draw the buffer as points.
* *
*/ */
DrawWebGL.prototype.drawPoints = function (buf, color, points, pointSize) { DrawWebGL.prototype.drawPoints = function (buf, color, points, pointSize, shape) {
if (this.isContextLost) { if (this.isContextLost) {
return; return;
} }
this.gl.uniform1f(this.uPointSize, pointSize); this.gl.uniform1f(this.uPointSize, pointSize);
this.doDraw(this.gl.POINTS, buf, color, points); this.doDraw(this.gl.POINTS, buf, color, points, shape);
}; };
/** /**

View File

@ -0,0 +1,53 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2020, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([], function () {
/**
* @label string (required) display name of shape
* @drawWebGL integer (unique, required) index provided to WebGL Fragment Shader
* @pattern array
*/
const LINE_STYLES = {
solid: {
label: 'Solid',
drawWebGL: 1,
drawC2D: []
},
dot: {
label: 'Dot',
drawWebGL: 2,
drawC2D: [2, 2]
}
// dash: {
// label: 'Dash',
// drawWebGL: 3,
// drawC2D: [5, 2]
// }
// dotDashDot: {
// label: 'Dot Dash Dot',
// drawWebGL: 4,
// drawC2D: [5, 2, 2]
// }
};
return LINE_STYLES;
});

View File

@ -0,0 +1,53 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2020, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([], function () {
/**
* @label string (required) display name of shape
* @drawWebGL integer (unique, required) index provided to WebGL Fragment Shader
* @drawC2D function (required) canvas2d draw function
*/
const MARKER_SHAPES = {
point: {
label: 'Point',
drawWebGL: 1,
drawC2D: function (x, y, size) {
const offset = size / 2;
this.c2d.fillRect(x - offset, y - offset, size, size);
}
},
circle: {
label: 'Circle',
drawWebGL: 2,
drawC2D: function (x, y, size) {
const radius = size / 2;
this.c2d.beginPath();
this.c2d.arc(x, y, radius, 0, 2 * Math.PI, false);
this.c2d.closePath();
this.c2d.fill();
}
}
};
return MARKER_SHAPES;
});

View File

@ -22,9 +22,13 @@
define([ define([
'./PlotModelFormController', './PlotModelFormController',
'../draw/LineStyles',
'../draw/MarkerShapes',
'lodash' 'lodash'
], function ( ], function (
PlotModelFormController, PlotModelFormController,
LINE_STYLES,
MARKER_SHAPES,
_ _
) { ) {
@ -93,6 +97,20 @@ define([
value: o.key value: o.key
}; };
}); });
this.$scope.lineStyleOptions = Object.entries(LINE_STYLES)
.map(([key, obj]) => {
return {
name: obj.label,
value: key
};
});
this.$scope.markerShapeOptions = Object.entries(MARKER_SHAPES)
.map(([key, obj]) => {
return {
name: obj.label,
value: key
};
});
}, },
fields: [ fields: [
@ -104,10 +122,18 @@ define([
modelProp: 'interpolate', modelProp: 'interpolate',
objectPath: dynamicPathForKey('interpolate') objectPath: dynamicPathForKey('interpolate')
}, },
{
modelProp: 'lineStyle',
objectPath: dynamicPathForKey('lineStyle')
},
{ {
modelProp: 'markers', modelProp: 'markers',
objectPath: dynamicPathForKey('markers') objectPath: dynamicPathForKey('markers')
}, },
{
modelProp: 'markerShape',
objectPath: dynamicPathForKey('markerShape')
},
{ {
modelProp: 'markerSize', modelProp: 'markerSize',
coerce: Number, coerce: Number,