diff --git a/libs/infrared-sensor/ir.ts b/libs/infrared-sensor/ir.ts
index 208e61c0..cb477745 100644
--- a/libs/infrared-sensor/ir.ts
+++ b/libs/infrared-sensor/ir.ts
@@ -23,7 +23,7 @@ const enum IrRemoteButton {
const enum InfraredSensorEvent {
//% block="object near"
- ObjectNear = 1,
+ ObjectNear = 3,
//% block="object detected"
ObjectDetected = 2
}
@@ -60,11 +60,12 @@ namespace sensors {
buttons.push(new RemoteInfraredBeaconButton(new brick.Button()))
}
+ // this defeats our static allocation system
// make sure sensors are up
- create(infraredSensor1)
- create(infraredSensor2)
- create(infraredSensor3)
- create(infraredSensor4)
+ //create(infraredSensor1)
+ //create(infraredSensor2)
+ //create(infraredSensor3)
+ //create(infraredSensor4)
}
let num = -1
@@ -196,6 +197,7 @@ namespace sensors {
//% weight=100 blockGap=8
//% group="Infrared Sensor"
onEvent(event: InfraredSensorEvent, handler: () => void) {
+ this._setMode(IrSensorMode.Proximity)
control.onEvent(this._id, event, handler);
}
@@ -210,6 +212,7 @@ namespace sensors {
//% weight=99 blockGap=8
//% group="Infrared Sensor"
pauseUntil(event: InfraredSensorEvent) {
+ this._setMode(IrSensorMode.Proximity)
control.waitForEvent(this._id, event);
}
@@ -222,7 +225,7 @@ namespace sensors {
//% blockId=infraredGetProximity
//% parts="infrared"
//% blockNamespace=sensors
- //% weight=65 blockGap=8
+ //% weight=98 blockGap=8
//% group="Infrared Sensor"
proximity(): number {
this._setMode(IrSensorMode.Proximity)
diff --git a/sim/dalboard.ts b/sim/dalboard.ts
index 5cda54b6..e430087f 100644
--- a/sim/dalboard.ts
+++ b/sim/dalboard.ts
@@ -143,6 +143,7 @@ namespace pxsim {
case DAL.DEVICE_TYPE_COLOR: this.inputNodes[port] = new ColorSensorNode(port); break;
case DAL.DEVICE_TYPE_TOUCH: this.inputNodes[port] = new TouchSensorNode(port); break;
case DAL.DEVICE_TYPE_ULTRASONIC: this.inputNodes[port] = new UltrasonicSensorNode(port); break;
+ case DAL.DEVICE_TYPE_IR: this.inputNodes[port] = new InfraredSensorNode(port); break;
}
}
return this.inputNodes[port];
diff --git a/sim/state/infrared.ts b/sim/state/infrared.ts
new file mode 100644
index 00000000..38af0128
--- /dev/null
+++ b/sim/state/infrared.ts
@@ -0,0 +1,35 @@
+///
+
+namespace pxsim {
+ export enum InfraredSensorMode {
+ None = -1,
+ Proximity = 0,
+ Seek = 1,
+ RemoteControl = 2
+ }
+
+ export class InfraredSensorNode extends UartSensorNode {
+ id = NodeType.InfraredSensor;
+
+ private proximity: number = 50; // [0..100]
+
+ constructor(port: number) {
+ super(port);
+ }
+
+ getDeviceType() {
+ return DAL.DEVICE_TYPE_IR;
+ }
+
+ setPromixity(proximity: number) {
+ if (this.proximity != proximity) {
+ this.proximity = proximity;
+ this.setChangedState();
+ }
+ }
+
+ getValue() {
+ return this.proximity;
+ }
+ }
+}
\ No newline at end of file
diff --git a/sim/state/nodeTypes.ts b/sim/state/nodeTypes.ts
index aa9b9f06..53d4c9c7 100644
--- a/sim/state/nodeTypes.ts
+++ b/sim/state/nodeTypes.ts
@@ -7,7 +7,8 @@ namespace pxsim {
LargeMotor = 4,
GyroSensor = 5,
ColorSensor = 6,
- UltrasonicSensor = 7
+ UltrasonicSensor = 7,
+ InfraredSensor = 8
}
export interface Node {
diff --git a/sim/visuals/assets/infraredsvg.ts b/sim/visuals/assets/infraredsvg.ts
new file mode 100644
index 00000000..00768506
--- /dev/null
+++ b/sim/visuals/assets/infraredsvg.ts
@@ -0,0 +1,79 @@
+namespace pxsim {
+ export const INFRARED_SVG = ``;
+}
\ No newline at end of file
diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts
index f471db28..9cbeca1a 100644
--- a/sim/visuals/board.ts
+++ b/sim/visuals/board.ts
@@ -230,6 +230,12 @@ namespace pxsim.visuals {
view = new DistanceSliderControl(this.element, this.defs, state, port);
break;
}
+ case NodeType.InfraredSensor: {
+ const state = ev3board().getInputNodes()[0] as InfraredSensorNode;
+ if (state.getMode() == InfraredSensorMode.Proximity)
+ view = new ProximitySliderControl(this.element, this.defs, state, port);
+ break;
+ }
case NodeType.GyroSensor: {
const state = ev3board().getInputNodes()[port] as GyroSensorNode;
view = new RotationSliderControl(this.element, this.defs, state, port);
@@ -271,6 +277,8 @@ namespace pxsim.visuals {
view = new ColorSensorView(port); break;
case NodeType.UltrasonicSensor:
view = new UltrasonicSensorView(port); break;
+ case NodeType.InfraredSensor:
+ view = new InfraredView(port); break;
case NodeType.Brick:
//return new BrickView(0);
view = this.layoutView.getBrick(); break;
@@ -305,11 +313,11 @@ namespace pxsim.visuals {
// Add EV3 module element
const brickCloseIcon = this.getCloseIconView();
- brickCloseIcon.registerClick(ev => {
- this.layoutView.unselectBrick();
+ brickCloseIcon.registerClick(ev => {
+ this.layoutView.unselectBrick();
this.resize();
});
- const brick =new BrickView(-1);
+ const brick = new BrickView(-1);
brick.setSelected(EV3View.isPreviousBrickSelected());
this.layoutView.setBrick(brick, brickCloseIcon);
diff --git a/sim/visuals/controls/proximitySlider.ts b/sim/visuals/controls/proximitySlider.ts
new file mode 100644
index 00000000..19afa077
--- /dev/null
+++ b/sim/visuals/controls/proximitySlider.ts
@@ -0,0 +1,138 @@
+
+
+namespace pxsim.visuals {
+
+ export class ProximitySliderControl extends ControlView {
+ private group: SVGGElement;
+ private gradient: SVGLinearGradientElement;
+ private slider: SVGGElement;
+
+ private reporter: SVGTextElement;
+
+ private static SLIDER_HANDLE_HEIGHT = 26;
+ private static SLIDER_SIDE_PADDING = 6;
+
+ getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {
+ let gid = "gradient-slider-" + this.getId();
+ this.group = svg.elt("g") as SVGGElement;
+ this.gradient = createGradient(gid, this.getGradientDefinition());
+ this.gradient.setAttribute('x1', '0%');
+ this.gradient.setAttribute('y1', '0%');
+ this.gradient.setAttribute('x2', '0%');
+ this.gradient.setAttribute('y2', '100%');
+ // this.gradient.setAttribute('gradientTransform', 'matrix(50, 0, 0, -110, 21949.45, 46137.67)');
+ // this.gradient.setAttribute('gradientUnits', 'userSpaceOnUse');
+ globalDefs.appendChild(this.gradient);
+
+ this.group = svg.elt("g") as SVGGElement;
+
+ const reporterGroup = pxsim.svg.child(this.group, "g");
+ reporterGroup.setAttribute("transform", `translate(${this.getWidth() / 2}, 42)`);
+ this.reporter = pxsim.svg.child(reporterGroup, "text", { 'text-anchor': 'middle', 'x': 0, 'y': '0', 'class': 'sim-text number large inverted' }) as SVGTextElement;
+
+ const sliderGroup = pxsim.svg.child(this.group, "g");
+ sliderGroup.setAttribute("transform", `translate(${this.getWidth() / 2 - this.getSliderWidth() / 2}, ${this.getReporterHeight()})`)
+
+ const rect = pxsim.svg.child(sliderGroup, "rect", { 'x': ProximitySliderControl.SLIDER_SIDE_PADDING, 'y': 2, 'width': this.getSliderWidth() - ProximitySliderControl.SLIDER_SIDE_PADDING * 2, 'height': this.getSliderHeight(), 'style': `fill: url(#${gid})` });
+
+ this.slider = pxsim.svg.child(sliderGroup, "g", { "transform": "translate(0,0)" }) as SVGGElement;
+ const sliderInner = pxsim.svg.child(this.slider, "g");
+ pxsim.svg.child(sliderInner, "rect", { 'width': this.getSliderWidth(), 'height': ProximitySliderControl.SLIDER_HANDLE_HEIGHT, 'rx': '2', 'ry': '2', 'style': 'fill: #f12a21' });
+ pxsim.svg.child(sliderInner, "rect", { 'x': '0.5', 'y': '0.5', 'width': this.getSliderWidth() - 1, 'height': ProximitySliderControl.SLIDER_HANDLE_HEIGHT - 1, 'rx': '1.5', 'ry': '1.5', 'style': 'fill: none;stroke: #b32e29' });
+
+ const dragSurface = svg.child(this.group, "rect", {
+ x: 0,
+ y: 0,
+ width: this.getInnerWidth(),
+ height: this.getInnerHeight(),
+ opacity: 0,
+ cursor: '-webkit-grab'
+ })
+
+ let pt = parent.createSVGPoint();
+ let captured = false;
+
+ touchEvents(dragSurface, ev => {
+ if (captured && (ev as MouseEvent).clientY != undefined) {
+ ev.preventDefault();
+ this.updateSliderValue(pt, parent, ev as MouseEvent);
+ }
+ }, ev => {
+ captured = true;
+ if ((ev as MouseEvent).clientY != undefined) {
+ dragSurface.setAttribute('cursor', '-webkit-grabbing');
+ this.updateSliderValue(pt, parent, ev as MouseEvent);
+ }
+ }, () => {
+ captured = false;
+ dragSurface.setAttribute('cursor', '-webkit-grab');
+ }, () => {
+ captured = false;
+ dragSurface.setAttribute('cursor', '-webkit-grab');
+ })
+
+ return this.group;
+ }
+
+ getInnerHeight() {
+ return 192;
+ }
+
+ getInnerWidth() {
+ return 111;
+ }
+
+ private getReporterHeight() {
+ return 50;
+ }
+
+ private getSliderHeight() {
+ return 110;
+ }
+
+ private getSliderWidth() {
+ return 62;
+ }
+
+ updateState() {
+ if (!this.visible) {
+ return;
+ }
+ const node = this.state;
+ const percentage = node.getValue();
+ const y = this.getSliderHeight() * percentage / this.getMax();
+ this.slider.setAttribute("transform", `translate(0, ${y - ProximitySliderControl.SLIDER_HANDLE_HEIGHT / 2})`);
+ // Update reporter text
+ this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}`;
+ }
+
+ private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
+ let cur = svg.cursorPoint(pt, parent, ev);
+ const height = this.getSliderHeight();
+ const bBox = this.content.getBoundingClientRect();
+ let t = Math.max(0, Math.min(1, (ProximitySliderControl.SLIDER_HANDLE_HEIGHT + height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height))
+
+ const state = this.state;
+ const v = Math.floor((1 - t) * (this.getMax()));
+ state.setPromixity(v);
+ }
+
+ private getMin() {
+ return 0;
+ }
+
+ private getMax() {
+ return 100;
+ }
+
+ private getGradientDefinition(): LinearGradientDefinition {
+ return {
+ stops: [
+ { offset: 0, color: '#626262' },
+ { offset: 100, color: "#ddd" }
+ ]
+ };
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/sim/visuals/nodes/infraredview.ts b/sim/visuals/nodes/infraredview.ts
new file mode 100644
index 00000000..c32a838b
--- /dev/null
+++ b/sim/visuals/nodes/infraredview.ts
@@ -0,0 +1,10 @@
+///
+
+namespace pxsim.visuals {
+ export class InfraredView extends ModuleView implements LayoutElement {
+
+ constructor(port: number) {
+ super(INFRARED_SVG, "infrared", NodeType.InfraredSensor, port);
+ }
+ }
+}
\ No newline at end of file