mirror of
https://github.com/nasa/openmct.git
synced 2025-06-26 19:12:02 +00:00
Compare commits
31 Commits
plotly-tes
...
plots/cust
Author | SHA1 | Date | |
---|---|---|---|
be41c95ab3 | |||
a6d16409b9 | |||
d55466f2c9 | |||
0ef977ebee | |||
41141aa11c | |||
9ceb3c5b1e | |||
5ca38c0f43 | |||
bee3a9eedf | |||
e515d19acd | |||
dd13efe065 | |||
b5dfbe268c | |||
a9b9107cc3 | |||
cfda4e4214 | |||
0a657de4b2 | |||
8153edb9cb | |||
246aee0029 | |||
52c918455a | |||
f0cde1055d | |||
07b2aeaae1 | |||
c4736f3cac | |||
0d91b88eb1 | |||
ac1ff36c20 | |||
e01e263b37 | |||
b80373aee9 | |||
376ecf93a9 | |||
774726af77 | |||
101f3c022c | |||
b4d4945057 | |||
dadb6120c2 | |||
d9a94db59d | |||
c0780a62ae |
@ -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) {
|
||||||
|
@ -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),
|
||||||
|
@ -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(),
|
||||||
|
@ -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">
|
||||||
|
@ -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"
|
||||||
|
@ -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 () {
|
||||||
|
@ -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`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
53
src/plugins/plot/src/draw/LineStyles.js
Normal file
53
src/plugins/plot/src/draw/LineStyles.js
Normal 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;
|
||||||
|
});
|
53
src/plugins/plot/src/draw/MarkerShapes.js
Normal file
53
src/plugins/plot/src/draw/MarkerShapes.js
Normal 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;
|
||||||
|
});
|
@ -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,
|
||||||
|
Reference in New Issue
Block a user