Merge pull request #116 from Microsoft/revert_screenopt
Use game loop instead of animation queue
This commit is contained in:
commit
1765ca2d35
@ -24,7 +24,7 @@ namespace music {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//% color="#48150C"
|
//% color="#5F3109"
|
||||||
namespace control {
|
namespace control {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -132,10 +132,10 @@
|
|||||||
"logic": "#1E5AA8",
|
"logic": "#1E5AA8",
|
||||||
"math": "#9DC3F7",
|
"math": "#9DC3F7",
|
||||||
"variables": "#B40000",
|
"variables": "#B40000",
|
||||||
"text": "#F0890A",
|
"text": "#FCAC00",
|
||||||
"advanced": "#969696",
|
"advanced": "#969696",
|
||||||
"functions": "#064597",
|
"functions": "#19325A",
|
||||||
"arrays": "#890058"
|
"arrays": "#901F76"
|
||||||
},
|
},
|
||||||
"monacoColors": {
|
"monacoColors": {
|
||||||
"editor.background": "#ecf6ff"
|
"editor.background": "#ecf6ff"
|
||||||
|
@ -34,9 +34,6 @@ namespace pxsim {
|
|||||||
this.color = color;
|
this.color = color;
|
||||||
this.changed = true;
|
this.changed = true;
|
||||||
this.valueChanged = true;
|
this.valueChanged = true;
|
||||||
|
|
||||||
runtime.queueDisplayUpdate();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue() {
|
getValue() {
|
||||||
|
@ -22,20 +22,14 @@ namespace pxsim {
|
|||||||
setAngle(angle: number) {
|
setAngle(angle: number) {
|
||||||
if (this.angle != angle) {
|
if (this.angle != angle) {
|
||||||
this.angle = angle;
|
this.angle = angle;
|
||||||
this.changed = true;
|
this.setChangedState();
|
||||||
this.valueChanged = true;
|
|
||||||
|
|
||||||
runtime.queueDisplayUpdate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setRate(rate: number) {
|
setRate(rate: number) {
|
||||||
if (this.rate != rate) {
|
if (this.rate != rate) {
|
||||||
this.rate = rate;
|
this.rate = rate;
|
||||||
this.changed = true;
|
this.setChangedState();
|
||||||
this.valueChanged = true;
|
|
||||||
|
|
||||||
runtime.queueDisplayUpdate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,11 @@ namespace pxsim {
|
|||||||
namespace pxsim.output {
|
namespace pxsim.output {
|
||||||
|
|
||||||
export function setLights(pattern: number) {
|
export function setLights(pattern: number) {
|
||||||
const lightState = ev3board().getBrickNode().lightState;
|
const brickState = ev3board().getBrickNode();
|
||||||
lightState.lightPattern = pattern;
|
const lightState = brickState.lightState;
|
||||||
runtime.queueDisplayUpdate();
|
if (lightState.lightPattern != pattern) {
|
||||||
|
lightState.lightPattern = pattern;
|
||||||
|
brickState.setChangedState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
namespace pxsim {
|
namespace pxsim {
|
||||||
|
|
||||||
export class MotorNode extends BaseNode {
|
export abstract class MotorNode extends BaseNode {
|
||||||
isOutput = true;
|
isOutput = true;
|
||||||
|
|
||||||
public angle: number = 0;
|
protected angle: number = 0;
|
||||||
|
|
||||||
private speed: number;
|
private speed: number;
|
||||||
private large: boolean;
|
private large: boolean;
|
||||||
@ -18,7 +18,8 @@ namespace pxsim {
|
|||||||
if (this.speed != speed) {
|
if (this.speed != speed) {
|
||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
this.changed = true;
|
this.changed = true;
|
||||||
runtime.queueDisplayUpdate();
|
this.setChangedState();
|
||||||
|
this.playMotorAnimation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +51,14 @@ namespace pxsim {
|
|||||||
|
|
||||||
start() {
|
start() {
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
runtime.queueDisplayUpdate();
|
this.setChangedState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getAngle() {
|
||||||
|
return this.angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract playMotorAnimation(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MediumMotorNode extends MotorNode {
|
export class MediumMotorNode extends MotorNode {
|
||||||
@ -60,6 +67,32 @@ namespace pxsim {
|
|||||||
constructor(port: number) {
|
constructor(port: number) {
|
||||||
super(port);
|
super(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected lastMotorAnimationId: number;
|
||||||
|
protected playMotorAnimation() {
|
||||||
|
// Max medium motor RPM is 250 according to http://www.cs.scranton.edu/~bi/2015s-html/cs358/EV3-Motor-Guide.docx
|
||||||
|
const rotationsPerMinute = 250; // 250 rpm at speed 100
|
||||||
|
const rotationsPerSecond = rotationsPerMinute / 60;
|
||||||
|
const fps = GAME_LOOP_FPS;
|
||||||
|
const rotationsPerFrame = rotationsPerSecond / fps;
|
||||||
|
let now;
|
||||||
|
let then = Date.now();
|
||||||
|
let interval = 1000 / fps;
|
||||||
|
let delta;
|
||||||
|
let that = this;
|
||||||
|
function draw() {
|
||||||
|
that.lastMotorAnimationId = requestAnimationFrame(draw);
|
||||||
|
now = Date.now();
|
||||||
|
delta = now - then;
|
||||||
|
if (delta > interval) {
|
||||||
|
then = now - (delta % interval);
|
||||||
|
const rotations = that.getSpeed() / 100 * rotationsPerFrame;
|
||||||
|
const angle = rotations * 360;
|
||||||
|
that.angle += angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LargeMotorNode extends MotorNode {
|
export class LargeMotorNode extends MotorNode {
|
||||||
@ -69,5 +102,30 @@ namespace pxsim {
|
|||||||
super(port);
|
super(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected lastMotorAnimationId: number;
|
||||||
|
protected playMotorAnimation() {
|
||||||
|
// Max medium motor RPM is 170 according to http://www.cs.scranton.edu/~bi/2015s-html/cs358/EV3-Motor-Guide.docx
|
||||||
|
const rotationsPerMinute = 170; // 170 rpm at speed 100
|
||||||
|
const rotationsPerSecond = rotationsPerMinute / 60;
|
||||||
|
const fps = GAME_LOOP_FPS;
|
||||||
|
const rotationsPerFrame = rotationsPerSecond / fps;
|
||||||
|
let now;
|
||||||
|
let then = Date.now();
|
||||||
|
let interval = 1000 / fps;
|
||||||
|
let delta;
|
||||||
|
let that = this;
|
||||||
|
function draw() {
|
||||||
|
that.lastMotorAnimationId = requestAnimationFrame(draw);
|
||||||
|
now = Date.now();
|
||||||
|
delta = now - then;
|
||||||
|
if (delta > interval) {
|
||||||
|
then = now - (delta % interval);
|
||||||
|
const rotations = that.getSpeed() / 100 * rotationsPerFrame;
|
||||||
|
const angle = rotations * 360;
|
||||||
|
that.angle += angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,5 +32,9 @@ namespace pxsim {
|
|||||||
this.changed = false;
|
this.changed = false;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setChangedState() {
|
||||||
|
this.changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,6 +7,7 @@ namespace pxsim {
|
|||||||
|
|
||||||
|
|
||||||
export class EV3ScreenState {
|
export class EV3ScreenState {
|
||||||
|
changed: boolean = true;
|
||||||
points: Uint8Array;
|
points: Uint8Array;
|
||||||
constructor() {
|
constructor() {
|
||||||
this.points = new Uint8Array(visuals.SCREEN_WIDTH * visuals.SCREEN_HEIGHT)
|
this.points = new Uint8Array(visuals.SCREEN_WIDTH * visuals.SCREEN_HEIGHT)
|
||||||
@ -23,13 +24,13 @@ namespace pxsim {
|
|||||||
|
|
||||||
setPixel(x: number, y: number, v: number) {
|
setPixel(x: number, y: number, v: number) {
|
||||||
this.applyMode(OFF(x, y), v)
|
this.applyMode(OFF(x, y), v)
|
||||||
runtime.queueDisplayUpdate();
|
this.changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
for (let i = 0; i < this.points.length; ++i)
|
for (let i = 0; i < this.points.length; ++i)
|
||||||
this.points[i] = 0;
|
this.points[i] = 0;
|
||||||
runtime.queueDisplayUpdate();
|
this.changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
blitLineCore(x: number, y: number, w: number, buf: RefBuffer, mode: Draw, offset = 0) {
|
blitLineCore(x: number, y: number, w: number, buf: RefBuffer, mode: Draw, offset = 0) {
|
||||||
@ -58,7 +59,7 @@ namespace pxsim {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.queueDisplayUpdate();
|
this.changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearLine(x: number, y: number, w: number) {
|
clearLine(x: number, y: number, w: number) {
|
||||||
@ -72,6 +73,12 @@ namespace pxsim {
|
|||||||
off++
|
off++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
didChange() {
|
||||||
|
const res = this.changed;
|
||||||
|
this.changed = false;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,11 @@ namespace pxsim {
|
|||||||
this.valueChanged = false;
|
this.valueChanged = false;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setChangedState() {
|
||||||
|
this.changed = true;
|
||||||
|
this.valueChanged = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AnalogSensorNode extends SensorNode {
|
export class AnalogSensorNode extends SensorNode {
|
||||||
|
@ -17,10 +17,7 @@ namespace pxsim {
|
|||||||
setDistance(distance: number) {
|
setDistance(distance: number) {
|
||||||
if (this.distance != distance) {
|
if (this.distance != distance) {
|
||||||
this.distance = distance;
|
this.distance = distance;
|
||||||
this.changed = true;
|
this.setChangedState();
|
||||||
this.valueChanged = true;
|
|
||||||
|
|
||||||
runtime.queueDisplayUpdate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
/// <reference path="./layoutView.ts" />
|
/// <reference path="./layoutView.ts" />
|
||||||
|
|
||||||
|
namespace pxsim {
|
||||||
|
export const GAME_LOOP_FPS = 32;
|
||||||
|
}
|
||||||
|
|
||||||
namespace pxsim.visuals {
|
namespace pxsim.visuals {
|
||||||
|
|
||||||
const EV3_STYLE = `
|
const EV3_STYLE = `
|
||||||
@ -136,6 +140,12 @@ namespace pxsim.visuals {
|
|||||||
this.board.updateSubscribers.push(() => this.updateState());
|
this.board.updateSubscribers.push(() => this.updateState());
|
||||||
this.updateState();
|
this.updateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Runtime.messagePosted = (msg) => {
|
||||||
|
switch (msg.type || "") {
|
||||||
|
case "status": if ((msg as pxsim.SimulatorStateMessage).state == "killed") this.kill(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getView(): SVGAndSize<SVGSVGElement> {
|
public getView(): SVGAndSize<SVGSVGElement> {
|
||||||
@ -167,54 +177,6 @@ namespace pxsim.visuals {
|
|||||||
this.layoutView.updateTheme(theme);
|
this.layoutView.updateTheme(theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateState() {
|
|
||||||
this.updateVisibleNodes();
|
|
||||||
this.updateScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateVisibleNodes() {
|
|
||||||
const inputNodes = ev3board().getInputNodes();
|
|
||||||
inputNodes.forEach((node, index) => {
|
|
||||||
const view = this.getDisplayViewForNode(node.id, index);
|
|
||||||
if (view) {
|
|
||||||
this.layoutView.setInput(index, view);
|
|
||||||
view.updateState();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.getDisplayViewForNode(ev3board().getBrickNode().id, -1).updateState();
|
|
||||||
|
|
||||||
const outputNodes = ev3board().getMotors();
|
|
||||||
outputNodes.forEach((node, index) => {
|
|
||||||
const view = this.getDisplayViewForNode(node.id, index);
|
|
||||||
if (view) {
|
|
||||||
this.layoutView.setOutput(index, view);
|
|
||||||
view.updateState();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const selected = this.layoutView.getSelected();
|
|
||||||
if (selected && (selected.getId() !== this.selectedNode || selected.getPort() !== this.selectedPort)) {
|
|
||||||
this.selectedNode = selected.getId();
|
|
||||||
this.selectedPort = selected.getPort();
|
|
||||||
this.controlGroup.clear();
|
|
||||||
const control = this.getControlForNode(this.selectedNode, selected.getPort());
|
|
||||||
if (control) {
|
|
||||||
this.controlView = control;
|
|
||||||
this.controlGroup.addView(control);
|
|
||||||
}
|
|
||||||
this.closeIconView.setVisible(true);
|
|
||||||
} else if (!selected) {
|
|
||||||
this.controlGroup.clear();
|
|
||||||
this.controlView = undefined;
|
|
||||||
this.selectedNode = undefined;
|
|
||||||
this.selectedPort = undefined;
|
|
||||||
this.closeIconView.setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.resize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public resize() {
|
public resize() {
|
||||||
const bounds = this.element.getBoundingClientRect();
|
const bounds = this.element.getBoundingClientRect();
|
||||||
this.width = bounds.width;
|
this.width = bounds.width;
|
||||||
@ -242,7 +204,7 @@ namespace pxsim.visuals {
|
|||||||
this.controlView.translate(controlCoords.x, controlCoords.y);
|
this.controlView.translate(controlCoords.x, controlCoords.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateScreen();
|
//this.updateScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getControlForNode(id: NodeType, port: number) {
|
private getControlForNode(id: NodeType, port: number) {
|
||||||
@ -355,7 +317,7 @@ namespace pxsim.visuals {
|
|||||||
this.closeIconView.setVisible(false);
|
this.closeIconView.setVisible(false);
|
||||||
|
|
||||||
this.resize();
|
this.resize();
|
||||||
this.updateState();
|
//this.updateState();
|
||||||
|
|
||||||
// Add Screen canvas to board
|
// Add Screen canvas to board
|
||||||
this.buildScreenCanvas();
|
this.buildScreenCanvas();
|
||||||
@ -394,8 +356,84 @@ namespace pxsim.visuals {
|
|||||||
this.screenCanvasTemp.style.display = 'none';
|
this.screenCanvasTemp.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateScreen() {
|
private kill() {
|
||||||
|
if (this.lastAnimationId) cancelAnimationFrame(this.lastAnimationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private lastAnimationId: number;
|
||||||
|
public updateState() {
|
||||||
|
if (this.lastAnimationId) cancelAnimationFrame(this.lastAnimationId);
|
||||||
|
const fps = GAME_LOOP_FPS;
|
||||||
|
let now;
|
||||||
|
let then = Date.now();
|
||||||
|
let interval = 1000 / fps;
|
||||||
|
let delta;
|
||||||
|
let that = this;
|
||||||
|
function loop() {
|
||||||
|
that.lastAnimationId = requestAnimationFrame(loop);
|
||||||
|
now = Date.now();
|
||||||
|
delta = now - then;
|
||||||
|
if (delta > interval) {
|
||||||
|
then = now - (delta % interval);
|
||||||
|
that.updateStateStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateStateStep() {
|
||||||
|
const selected = this.layoutView.getSelected();
|
||||||
|
const inputNodes = ev3board().getInputNodes();
|
||||||
|
inputNodes.forEach((node, index) => {
|
||||||
|
if (!node.didChange()) return;
|
||||||
|
const view = this.getDisplayViewForNode(node.id, index);
|
||||||
|
if (view) {
|
||||||
|
this.layoutView.setInput(index, view);
|
||||||
|
view.updateState();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const brickNode = ev3board().getBrickNode();
|
||||||
|
if (brickNode.didChange()) {
|
||||||
|
this.getDisplayViewForNode(ev3board().getBrickNode().id, -1).updateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
const outputNodes = ev3board().getMotors();
|
||||||
|
outputNodes.forEach((node, index) => {
|
||||||
|
if (!node.didChange()) return;
|
||||||
|
const view = this.getDisplayViewForNode(node.id, index);
|
||||||
|
if (view) {
|
||||||
|
this.layoutView.setOutput(index, view);
|
||||||
|
view.updateState();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (selected && (selected.getId() !== this.selectedNode || selected.getPort() !== this.selectedPort)) {
|
||||||
|
this.selectedNode = selected.getId();
|
||||||
|
this.selectedPort = selected.getPort();
|
||||||
|
this.controlGroup.clear();
|
||||||
|
const control = this.getControlForNode(this.selectedNode, selected.getPort());
|
||||||
|
if (control) {
|
||||||
|
this.controlView = control;
|
||||||
|
this.controlGroup.addView(control);
|
||||||
|
}
|
||||||
|
this.closeIconView.setVisible(true);
|
||||||
|
this.resize();
|
||||||
|
} else if (!selected) {
|
||||||
|
this.controlGroup.clear();
|
||||||
|
this.controlView = undefined;
|
||||||
|
this.selectedNode = undefined;
|
||||||
|
this.selectedPort = undefined;
|
||||||
|
this.closeIconView.setVisible(false);
|
||||||
|
this.resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateScreenStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateScreenStep() {
|
||||||
let state = ev3board().screenState;
|
let state = ev3board().screenState;
|
||||||
|
if (!state.didChange()) return;
|
||||||
|
|
||||||
const bBox = this.layoutView.getBrick().getScreenBBox();
|
const bBox = this.layoutView.getBrick().getScreenBBox();
|
||||||
if (!bBox || bBox.width == 0) return;
|
if (!bBox || bBox.width == 0) return;
|
||||||
|
@ -78,7 +78,7 @@ namespace pxsim.visuals {
|
|||||||
return this.getInnerHeight() * 0.6;
|
return this.getInnerHeight() * 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
onBoardStateChanged() {
|
updateState() {
|
||||||
if (!this.isVisible) {
|
if (!this.isVisible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -91,7 +91,6 @@ namespace pxsim.visuals {
|
|||||||
onComponentVisible() {
|
onComponentVisible() {
|
||||||
super.onComponentVisible();
|
super.onComponentVisible();
|
||||||
this.isVisible = true;
|
this.isVisible = true;
|
||||||
this.onBoardStateChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onComponentHidden() {
|
onComponentHidden() {
|
||||||
|
@ -60,7 +60,7 @@ namespace pxsim.visuals {
|
|||||||
return this.getInnerHeight() / 4;
|
return this.getInnerHeight() / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
onBoardStateChanged() {
|
updateState() {
|
||||||
if (!this.isVisible) {
|
if (!this.isVisible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -74,7 +74,6 @@ namespace pxsim.visuals {
|
|||||||
onComponentVisible() {
|
onComponentVisible() {
|
||||||
super.onComponentVisible();
|
super.onComponentVisible();
|
||||||
this.isVisible = true;
|
this.isVisible = true;
|
||||||
this.onBoardStateChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onComponentHidden() {
|
onComponentHidden() {
|
||||||
|
@ -35,10 +35,6 @@ namespace pxsim.visuals {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public shouldUpdateState() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public updateState() {
|
public updateState() {
|
||||||
this.updateLight();
|
this.updateLight();
|
||||||
}
|
}
|
||||||
|
@ -18,36 +18,10 @@ namespace pxsim.visuals {
|
|||||||
if (this.lastMotorAnimationId) cancelAnimationFrame(this.lastMotorAnimationId);
|
if (this.lastMotorAnimationId) cancelAnimationFrame(this.lastMotorAnimationId);
|
||||||
|
|
||||||
if (!speed) return;
|
if (!speed) return;
|
||||||
this.playMotorAnimation(motorState);
|
this.setMotorAngle(motorState.getAngle());
|
||||||
}
|
}
|
||||||
|
|
||||||
private playMotorAnimation(state: MotorNode) {
|
private setMotorAngle(angle: number) {
|
||||||
// Max medium motor RPM is 170 according to http://www.cs.scranton.edu/~bi/2015s-html/cs358/EV3-Motor-Guide.docx
|
|
||||||
const rotationsPerMinute = 170; // 170 rpm at speed 100
|
|
||||||
const rotationsPerSecond = rotationsPerMinute / 60;
|
|
||||||
const fps = MOTOR_ROTATION_FPS;
|
|
||||||
const rotationsPerFrame = rotationsPerSecond / fps;
|
|
||||||
let now;
|
|
||||||
let then = Date.now();
|
|
||||||
let interval = 1000 / fps;
|
|
||||||
let delta;
|
|
||||||
let that = this;
|
|
||||||
function draw() {
|
|
||||||
that.lastMotorAnimationId = requestAnimationFrame(draw);
|
|
||||||
now = Date.now();
|
|
||||||
delta = now - then;
|
|
||||||
if (delta > interval) {
|
|
||||||
then = now - (delta % interval);
|
|
||||||
that.playMotorAnimationStep(state.angle);
|
|
||||||
const rotations = state.getSpeed() / 100 * rotationsPerFrame;
|
|
||||||
const angle = rotations * 360;
|
|
||||||
state.angle += angle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
private playMotorAnimationStep(angle: number) {
|
|
||||||
const holeEl = this.content.getElementById(this.normalizeId(LargeMotorView.ROTATING_ECLIPSE_ID))
|
const holeEl = this.content.getElementById(this.normalizeId(LargeMotorView.ROTATING_ECLIPSE_ID))
|
||||||
const width = 34;
|
const width = 34;
|
||||||
const height = 34;
|
const height = 34;
|
||||||
|
@ -28,36 +28,10 @@ namespace pxsim.visuals {
|
|||||||
if (this.lastMotorAnimationId) cancelAnimationFrame(this.lastMotorAnimationId);
|
if (this.lastMotorAnimationId) cancelAnimationFrame(this.lastMotorAnimationId);
|
||||||
|
|
||||||
if (!speed) return;
|
if (!speed) return;
|
||||||
this.playMotorAnimation(motorState);
|
this.setMotorAngle(motorState.getAngle());
|
||||||
}
|
}
|
||||||
|
|
||||||
private playMotorAnimation(state: MotorNode) {
|
private setMotorAngle(angle: number) {
|
||||||
// Max medium motor RPM is 250 according to http://www.cs.scranton.edu/~bi/2015s-html/cs358/EV3-Motor-Guide.docx
|
|
||||||
const rotationsPerMinute = 250; // 250 rpm at speed 100
|
|
||||||
const rotationsPerSecond = rotationsPerMinute / 60;
|
|
||||||
const fps = MOTOR_ROTATION_FPS;
|
|
||||||
const rotationsPerFrame = rotationsPerSecond / fps;
|
|
||||||
let now;
|
|
||||||
let then = Date.now();
|
|
||||||
let interval = 1000 / fps;
|
|
||||||
let delta;
|
|
||||||
let that = this;
|
|
||||||
function draw() {
|
|
||||||
that.lastMotorAnimationId = requestAnimationFrame(draw);
|
|
||||||
now = Date.now();
|
|
||||||
delta = now - then;
|
|
||||||
if (delta > interval) {
|
|
||||||
then = now - (delta % interval);
|
|
||||||
that.playMotorAnimationStep(state.angle);
|
|
||||||
const rotations = state.getSpeed() / 100 * rotationsPerFrame;
|
|
||||||
const angle = rotations * 360;
|
|
||||||
state.angle += angle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
private playMotorAnimationStep(angle: number) {
|
|
||||||
const holeEl = this.content.getElementById(this.normalizeId(MediumMotorView.ROTATING_ECLIPSE_ID))
|
const holeEl = this.content.getElementById(this.normalizeId(MediumMotorView.ROTATING_ECLIPSE_ID))
|
||||||
const width = 47.9;
|
const width = 47.9;
|
||||||
const height = 47.2;
|
const height = 47.2;
|
||||||
|
@ -61,10 +61,6 @@ namespace pxsim.visuals {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public shouldUpdateState() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public updateState() {
|
public updateState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,23 +175,8 @@ namespace pxsim.visuals {
|
|||||||
public setSelected(selected: boolean) { }
|
public setSelected(selected: boolean) { }
|
||||||
|
|
||||||
protected getView() {
|
protected getView() {
|
||||||
if (!this.rendered) {
|
|
||||||
this.subscribe();
|
|
||||||
}
|
|
||||||
return super.getView();
|
return super.getView();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onBoardStateChanged() {
|
|
||||||
// To be implemented by sub class
|
|
||||||
}
|
|
||||||
|
|
||||||
protected subscribe() {
|
|
||||||
board().updateSubscribers.push(() => {
|
|
||||||
if (this.state.didChange()) {
|
|
||||||
this.onBoardStateChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ViewContainer extends View {
|
export class ViewContainer extends View {
|
||||||
|
@ -28,9 +28,14 @@
|
|||||||
|
|
||||||
div.blocklyTreeRow {
|
div.blocklyTreeRow {
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
-webkit-box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.2);
|
margin-bottom: 7px;
|
||||||
|
/*-webkit-box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.2);
|
||||||
-moz-box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.2);
|
-moz-box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.2);
|
||||||
box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.2);
|
box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.2);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
div.blocklyTreeSeparator {
|
||||||
|
border-bottom: solid #CEA403 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove shadow around blockly blocks */
|
/* Remove shadow around blockly blocks */
|
||||||
@ -51,6 +56,7 @@ span.blocklyTreeLabel {
|
|||||||
margin: 0.5rem;
|
margin: 0.5rem;
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
|
margin-bottom: 0.8rem;
|
||||||
}
|
}
|
||||||
.blocklySearchInputField {
|
.blocklySearchInputField {
|
||||||
border-radius: 1rem !important;
|
border-radius: 1rem !important;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
@emSize : 14px;
|
@emSize : 14px;
|
||||||
@fontSize : 13px;
|
@fontSize : 13px;
|
||||||
|
|
||||||
@primaryColor: @red;
|
@primaryColor: @blue;
|
||||||
@secondaryColor: @yellow;
|
@secondaryColor: @yellow;
|
||||||
|
|
||||||
@teal:#08415C;
|
@teal:#08415C;
|
||||||
@ -88,6 +88,8 @@
|
|||||||
|
|
||||||
@pageBackground: #fff;
|
@pageBackground: #fff;
|
||||||
|
|
||||||
|
@positiveColor: @blue;
|
||||||
|
@defaultBorderRadius: 0px;
|
||||||
|
|
||||||
@inputPlaceholderColor: lighten(@inputColor, 80);
|
@inputPlaceholderColor: lighten(@inputColor, 80);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user