Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
a7d002d949 | |||
93fd8c8c78 | |||
1765ca2d35 | |||
1ab7ae6cfa | |||
3acf4e9ac5 | |||
ef5fa9ae82 | |||
e1f7a5b8cf | |||
2c73bfc813 | |||
d78d9c8686 | |||
2157af3e63 | |||
eac3e183c3 | |||
785ddff706 | |||
e07d6e3a31 |
@ -68,6 +68,13 @@ namespace sensors {
|
||||
}
|
||||
|
||||
setMode(m: ColorSensorMode) {
|
||||
if (m == ColorSensorMode.AmbientLightIntensity) {
|
||||
this.thresholdDetector.setLowThreshold(5);
|
||||
this.thresholdDetector.setHighThreshold(20);
|
||||
} else {
|
||||
this.thresholdDetector.setLowThreshold(20);
|
||||
this.thresholdDetector.setHighThreshold(80);
|
||||
}
|
||||
this._setMode(m)
|
||||
}
|
||||
|
||||
|
@ -32,15 +32,16 @@
|
||||
"brick.lightPattern": "Pattern block.",
|
||||
"brick.lightPattern|param|pattern": "the lights pattern to use. eg: LightsPattern.Green",
|
||||
"brick.print": "Show text on the screen.",
|
||||
"brick.printPorts": "Prints the port states on the screen",
|
||||
"brick.print|param|text": "the text to print on the screen, eg: \"Hello world\"",
|
||||
"brick.print|param|x": "the starting position's x coordinate, eg: 0",
|
||||
"brick.print|param|y": "the starting position's x coordinate, eg: 0",
|
||||
"brick.setLight": "Set lights.",
|
||||
"brick.setLight|param|pattern": "the lights pattern to use.",
|
||||
"brick.setPixel": "Sets a pixel on or off",
|
||||
"brick.setPixel|param|on": "a value indicating if the pixel should be on or off",
|
||||
"brick.setPixel|param|x": "the starting position's x coordinate, eg: 0",
|
||||
"brick.setPixel|param|y": "the starting position's x coordinate, eg: 0",
|
||||
"brick.setStatusLight": "Set lights.",
|
||||
"brick.setStatusLight|param|pattern": "the lights pattern to use.",
|
||||
"brick.showImage": "Shows an image on screen",
|
||||
"brick.showImage|param|image": "image to draw",
|
||||
"console": "Reading and writing data to the console output.\n\nReading and writing data to the console output.",
|
||||
|
@ -24,22 +24,23 @@
|
||||
"Output.CD|block": "C+D",
|
||||
"Output.C|block": "C",
|
||||
"Output.D|block": "D",
|
||||
"brick.Button.isPressed|block": "`icons.brickButtons` %button|is pressed",
|
||||
"brick.Button.onEvent|block": "on `icons.brickButtons` %button|%event",
|
||||
"brick.Button.pauseUntil|block": "pause until `icons.brickButtons` %button|%event",
|
||||
"brick.Button.wasPressed|block": "`icons.brickButtons` %button|was pressed",
|
||||
"brick.Button.isPressed|block": "%button|is pressed",
|
||||
"brick.Button.onEvent|block": "on %button|%event",
|
||||
"brick.Button.pauseUntil|block": "pause until %button|%event",
|
||||
"brick.Button.wasPressed|block": "%button|was pressed",
|
||||
"brick._imagePicker|block": "%image",
|
||||
"brick.buttonDown|block": "down",
|
||||
"brick.buttonEnter|block": "enter",
|
||||
"brick.buttonLeft|block": "left",
|
||||
"brick.buttonRight|block": "right",
|
||||
"brick.buttonUp|block": "up",
|
||||
"brick.clearScreen|block": "`icons.brickDisplay` clear screen",
|
||||
"brick.clearScreen|block": "clear screen",
|
||||
"brick.lightPattern|block": "%pattern",
|
||||
"brick.print|block": "`icons.brickDisplay` print %text| at x: %x| y: %y",
|
||||
"brick.setPixel|block": "`icons.brickDisplay` set pixel %on| at x: %x| y: %y",
|
||||
"brick.setStatusLight|block": "set `icons.brickButtons` to %pattern=led_pattern",
|
||||
"brick.showImage|block": "`icons.brickDisplay` show image %image=screen_image_picker",
|
||||
"brick.printPorts|block": "print ports",
|
||||
"brick.print|block": "print %text| at x: %x| y: %y",
|
||||
"brick.setLight|block": "set light to %pattern=led_pattern",
|
||||
"brick.setPixel|block": "set pixel %on| at x: %x| y: %y",
|
||||
"brick.showImage|block": "show image %image=screen_image_picker",
|
||||
"brick|block": "brick",
|
||||
"console.logValue|block": "console|log value %name|= %value",
|
||||
"console.log|block": "console|log %text",
|
||||
|
@ -85,7 +85,7 @@ namespace brick {
|
||||
* @param button the button to query the request
|
||||
*/
|
||||
//% help=input/button/is-pressed
|
||||
//% block="`icons.brickButtons` %button|is pressed"
|
||||
//% block="%button|is pressed"
|
||||
//% blockId=buttonIsPressed
|
||||
//% parts="brick"
|
||||
//% blockNamespace=brick
|
||||
@ -100,7 +100,7 @@ namespace brick {
|
||||
* @param button the button to query the request
|
||||
*/
|
||||
//% help=input/button/was-pressed
|
||||
//% block="`icons.brickButtons` %button|was pressed"
|
||||
//% block="%button|was pressed"
|
||||
//% blockId=buttonWasPressed
|
||||
//% parts="brick"
|
||||
//% blockNamespace=brick
|
||||
@ -119,7 +119,7 @@ namespace brick {
|
||||
* @param body code to run when the event is raised
|
||||
*/
|
||||
//% help=input/button/on-event
|
||||
//% blockId=buttonEvent block="on `icons.brickButtons` %button|%event"
|
||||
//% blockId=buttonEvent block="on %button|%event"
|
||||
//% parts="brick"
|
||||
//% blockNamespace=brick
|
||||
//% weight=99 blockGap=8
|
||||
@ -133,7 +133,7 @@ namespace brick {
|
||||
* @param ev the event to wait for
|
||||
*/
|
||||
//% help=input/button/pause-until
|
||||
//% blockId=buttonWaitUntil block="pause until `icons.brickButtons` %button|%event"
|
||||
//% blockId=buttonWaitUntil block="pause until %button|%event"
|
||||
//% parts="brick"
|
||||
//% blockNamespace=brick
|
||||
//% weight=98 blockGap=8
|
||||
@ -248,9 +248,9 @@ namespace brick {
|
||||
* Set lights.
|
||||
* @param pattern the lights pattern to use.
|
||||
*/
|
||||
//% blockId=setLights block="set `icons.brickButtons` to %pattern=led_pattern"
|
||||
//% weight=100 group="Light"
|
||||
export function setStatusLight(pattern: number): void {
|
||||
//% blockId=setLights block="set light to %pattern=led_pattern"
|
||||
//% weight=100 group="Buttons"
|
||||
export function setLight(pattern: number): void {
|
||||
if (currPattern === pattern)
|
||||
return
|
||||
currPattern = pattern
|
||||
|
@ -59,7 +59,6 @@ namespace console {
|
||||
namespace console.screen {
|
||||
const maxLines = 100;
|
||||
const screenLines = 8;
|
||||
const lineHeight = 12;
|
||||
let lines: string[];
|
||||
let scrollPosition = 0;
|
||||
|
||||
@ -67,8 +66,8 @@ namespace console.screen {
|
||||
if (!lines) {
|
||||
lines = [];
|
||||
console.addListener(log);
|
||||
brick.buttonUp.onEvent(ButtonEvent.Click, () => scroll(1))
|
||||
brick.buttonDown.onEvent(ButtonEvent.Click, () => scroll(-1))
|
||||
brick.buttonUp.onEvent(ButtonEvent.Click, () => scroll(-1))
|
||||
brick.buttonDown.onEvent(ButtonEvent.Click, () => scroll(1))
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +77,7 @@ namespace console.screen {
|
||||
for (let i = 0; i < screenLines; ++i) {
|
||||
const line = lines[i + scrollPosition];
|
||||
if (line)
|
||||
brick.print(line, 0, 4 + i * lineHeight)
|
||||
brick.print(line, 0, 4 + i * brick.LINE_HEIGHT)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,11 @@ namespace sensors.internal {
|
||||
|
||||
}
|
||||
|
||||
export function getActiveSensors(): Sensor[] {
|
||||
init();
|
||||
return sensorInfos.filter(si => si.sensor && si.sensor.isActive()).map(si => si.sensor);
|
||||
}
|
||||
|
||||
function readUartInfo(port: number, mode: number) {
|
||||
let buf = output.createBuffer(UartCtlOff.Size)
|
||||
buf[UartCtlOff.Port] = port
|
||||
|
@ -75,9 +75,9 @@ namespace motors {
|
||||
* @param buf message buffer
|
||||
*/
|
||||
//%
|
||||
export function readPWM(buf: Buffer): number {
|
||||
export function readPWM(buf: Buffer): void {
|
||||
init()
|
||||
return pwmMM.read(buf);
|
||||
pwmMM.read(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -261,9 +261,16 @@ namespace motors {
|
||||
//%
|
||||
isReady(): boolean {
|
||||
this.init();
|
||||
const r = readPWM(mkCmd(this._port, DAL.opOutputTest, 0))
|
||||
// 0 = ready, 1 = busy
|
||||
return r == 0;
|
||||
const buf = mkCmd(this._port, DAL.opOutputTest, 2);
|
||||
readPWM(buf)
|
||||
const flags = buf.getNumber(NumberFormat.UInt8LE, 2);
|
||||
// TODO: FIX with ~ support
|
||||
for(let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
|
||||
const flag = 1 << i;
|
||||
if ((this._port & flag) && (flags & flag))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -529,8 +536,8 @@ namespace motors {
|
||||
export const largeCD = new SynchedMotorPair(Output.CD);
|
||||
|
||||
function reset(out: Output) {
|
||||
let b = mkCmd(out, DAL.opOutputReset, 0)
|
||||
writePWM(b)
|
||||
writePWM(mkCmd(out, DAL.opOutputReset, 0))
|
||||
writePWM(mkCmd(out, DAL.opOutputClearCount, 0))
|
||||
}
|
||||
|
||||
function outOffset(out: Output) {
|
||||
@ -541,7 +548,7 @@ namespace motors {
|
||||
return 0
|
||||
}
|
||||
|
||||
interface MotorData {
|
||||
export interface MotorData {
|
||||
actualSpeed: number; // -100..+100
|
||||
tachoCount: number;
|
||||
count: number;
|
||||
@ -550,7 +557,7 @@ namespace motors {
|
||||
// only a single output at a time
|
||||
function getMotorData(out: Output): MotorData {
|
||||
init()
|
||||
let buf = motorMM.slice(outOffset(out), MotorDataOff.Size)
|
||||
const buf = motorMM.slice(outOffset(out), MotorDataOff.Size)
|
||||
return {
|
||||
actualSpeed: buf.getNumber(NumberFormat.Int8LE, MotorDataOff.Speed),
|
||||
tachoCount: buf.getNumber(NumberFormat.Int32LE, MotorDataOff.TachoCounts),
|
||||
@ -558,6 +565,11 @@ namespace motors {
|
||||
}
|
||||
}
|
||||
|
||||
export function getAllMotorData(): MotorData[] {
|
||||
init();
|
||||
return [Output.A, Output.B, Output.C, Output.D].map(out => getMotorData(out));
|
||||
}
|
||||
|
||||
interface SyncOptions {
|
||||
useSteps?: boolean;
|
||||
speed: number;
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace brick {
|
||||
export const LINE_HEIGHT = 12;
|
||||
|
||||
//% shim=screen::_setPixel
|
||||
function _setPixel(p0: uint32, p1: uint32, mode: Draw): void { }
|
||||
|
||||
@ -84,7 +86,7 @@ namespace brick {
|
||||
* @param x the starting position's x coordinate, eg: 0
|
||||
* @param y the starting position's x coordinate, eg: 0
|
||||
*/
|
||||
//% blockId=screen_setpixel block="`icons.brickDisplay` set pixel %on| at x: %x| y: %y"
|
||||
//% blockId=screen_setpixel block="set pixel %on| at x: %x| y: %y"
|
||||
//% weight=98 group="Screen"
|
||||
//% x.min=0 x.max=178 y.min=0 y.max=128 on.fieldEditor=toggleonoff
|
||||
export function setPixel(on: boolean, x: number, y: number) {
|
||||
@ -100,7 +102,7 @@ namespace brick {
|
||||
* @param x the starting position's x coordinate, eg: 0
|
||||
* @param y the starting position's x coordinate, eg: 0
|
||||
*/
|
||||
//% blockId=screen_print block="`icons.brickDisplay` print %text| at x: %x| y: %y"
|
||||
//% blockId=screen_print block="print %text| at x: %x| y: %y"
|
||||
//% weight=99 group="Screen" inlineInputMode="inline" blockGap=8
|
||||
//% x.min=0 x.max=178 y.min=0 y.max=128
|
||||
export function print(text: string, x: number, y: number, mode = Draw.Normal) {
|
||||
@ -137,7 +139,7 @@ namespace brick {
|
||||
* Shows an image on screen
|
||||
* @param image image to draw
|
||||
*/
|
||||
//% blockId=screen_show_image block="`icons.brickDisplay` show image %image=screen_image_picker"
|
||||
//% blockId=screen_show_image block="show image %image=screen_image_picker"
|
||||
//% weight=95 group="Screen" blockGap=8
|
||||
export function showImage(image: Image, delay: number = 400) {
|
||||
if (!image) return;
|
||||
@ -163,7 +165,7 @@ namespace brick {
|
||||
/**
|
||||
* Clears the screen
|
||||
*/
|
||||
//% blockId=screen_clear_screen block="`icons.brickDisplay` clear screen"
|
||||
//% blockId=screen_clear_screen block="clear screen"
|
||||
//% weight=94 group="Screen" blockGap=8
|
||||
export function clearScreen() {
|
||||
screen.clear();
|
||||
@ -208,5 +210,29 @@ namespace brick {
|
||||
setLineCore(x, x1, y, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the port states on the screen
|
||||
*/
|
||||
//% blockId=brickPrintPorts block="print ports"
|
||||
//% weight=1 group="Screen"
|
||||
export function printPorts() {
|
||||
clearScreen();
|
||||
|
||||
// motors
|
||||
const datas = motors.getAllMotorData();
|
||||
for(let i = 0; i < datas.length; ++i) {
|
||||
const x = i * 52;
|
||||
const data = datas[i];
|
||||
print(`${data.actualSpeed}%`, x, brick.LINE_HEIGHT)
|
||||
print(`${data.count}>`, x, 2 * brick.LINE_HEIGHT)
|
||||
}
|
||||
|
||||
// sensors
|
||||
const sis = sensors.internal.getActiveSensors();
|
||||
for(let i =0; i < sis.length; ++i) {
|
||||
const si = sis[i];
|
||||
const x = (si.port() - 1) * 52;
|
||||
print(`${si._query()}`, x, 9 * brick.LINE_HEIGHT)
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ screen.clear()
|
||||
brick.print("PXT!", 10, 30, Draw.Quad)
|
||||
|
||||
brick.drawRect(40, 40, 20, 10, Draw.Fill)
|
||||
brick.setStatusLight(LightsPattern.Orange)
|
||||
brick.setLight(LightsPattern.Orange)
|
||||
|
||||
brick.heart.doubled().draw(100, 50, Draw.Double | Draw.Transparent)
|
||||
|
||||
@ -12,7 +12,7 @@ brick.buttonEnter.onEvent(ButtonEvent.Click, () => {
|
||||
|
||||
brick.buttonLeft.onEvent(ButtonEvent.Click, () => {
|
||||
brick.drawRect(10, 70, 20, 10, Draw.Fill)
|
||||
brick.setStatusLight(LightsPattern.Red)
|
||||
brick.setLight(LightsPattern.Red)
|
||||
brick.setFont(brick.microbitFont())
|
||||
})
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
//% color="#68C3E2" weight=100
|
||||
//% groups='["Light", "Buttons", "Screen"]'
|
||||
//% groups='["Buttons", "Screen"]'
|
||||
//% labelLineWidth=0
|
||||
namespace brick {
|
||||
}
|
||||
@ -24,7 +24,7 @@ namespace music {
|
||||
|
||||
}
|
||||
|
||||
//% color="#48150C"
|
||||
//% color="#5F3109"
|
||||
namespace control {
|
||||
|
||||
}
|
||||
|
@ -23,9 +23,12 @@ namespace tests {
|
||||
// clear state
|
||||
this.reset();
|
||||
|
||||
console.log(`# ${this.name}`)
|
||||
console.log(`> ${this.name}`)
|
||||
this.handler()
|
||||
|
||||
if (this.errors.length)
|
||||
console.log('')
|
||||
|
||||
// ensure clean state after test
|
||||
this.reset();
|
||||
}
|
||||
@ -39,13 +42,15 @@ namespace tests {
|
||||
|
||||
const start = control.millis();
|
||||
console.sendToScreen();
|
||||
console.log(`${_tests.length} tests`)
|
||||
console.log(`${_tests.length} tests found`)
|
||||
console.log(` `)
|
||||
for (let i = 0; i < _tests.length; ++i) {
|
||||
const t = _currentTest = _tests[i];
|
||||
t.run();
|
||||
_currentTest = undefined;
|
||||
}
|
||||
console.log(`${_tests.map(t => t.errors.length).reduce((p, c) => p + c, 0)} X, ${Math.ceil((control.millis() - start) / 1000)}s`)
|
||||
console.log(` `)
|
||||
console.log(`${_tests.length} tests, ${_tests.map(t => t.errors.length).reduce((p, c) => p + c, 0)} errs in ${Math.ceil((control.millis() - start) / 1000)}s`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,7 +76,7 @@ namespace tests {
|
||||
//% blockId=testAssert block="assert %message|%condition"
|
||||
export function assert(message: string, condition: boolean) {
|
||||
if (!condition) {
|
||||
console.log(` X ${message || ''}`)
|
||||
console.log(`!!! ${message || ''}`)
|
||||
if (_currentTest)
|
||||
_currentTest.errors.push(message);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace sensors {
|
||||
}
|
||||
|
||||
_query(): number {
|
||||
return (this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff) * 0.1; // range is 0..2550, in 0.1 cm increments.
|
||||
return ((this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff) / 10) >> 0; // range is 0..2550, in 0.1 cm increments.
|
||||
}
|
||||
|
||||
_update(prev: number, curr: number) {
|
||||
@ -80,7 +80,7 @@ namespace sensors {
|
||||
distance(): number {
|
||||
// it supposedly also has an inch mode, but we stick to cm
|
||||
this._setMode(0)
|
||||
return (this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff) * 0.1; // range is 0..2550, in 0.1 cm increments.
|
||||
return this._query();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pxt-ev3",
|
||||
"version": "0.0.43",
|
||||
"version": "0.0.45",
|
||||
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
|
||||
"private": true,
|
||||
"keywords": [
|
||||
|
@ -132,10 +132,10 @@
|
||||
"logic": "#1E5AA8",
|
||||
"math": "#9DC3F7",
|
||||
"variables": "#B40000",
|
||||
"text": "#F0890A",
|
||||
"text": "#FCAC00",
|
||||
"advanced": "#969696",
|
||||
"functions": "#064597",
|
||||
"arrays": "#890058"
|
||||
"functions": "#19325A",
|
||||
"arrays": "#901F76"
|
||||
},
|
||||
"monacoColors": {
|
||||
"editor.background": "#ecf6ff"
|
||||
|
@ -34,9 +34,6 @@ namespace pxsim {
|
||||
this.color = color;
|
||||
this.changed = true;
|
||||
this.valueChanged = true;
|
||||
|
||||
runtime.queueDisplayUpdate();
|
||||
|
||||
}
|
||||
|
||||
getValue() {
|
||||
|
@ -22,20 +22,14 @@ namespace pxsim {
|
||||
setAngle(angle: number) {
|
||||
if (this.angle != angle) {
|
||||
this.angle = angle;
|
||||
this.changed = true;
|
||||
this.valueChanged = true;
|
||||
|
||||
runtime.queueDisplayUpdate();
|
||||
this.setChangedState();
|
||||
}
|
||||
}
|
||||
|
||||
setRate(rate: number) {
|
||||
if (this.rate != rate) {
|
||||
this.rate = rate;
|
||||
this.changed = true;
|
||||
this.valueChanged = true;
|
||||
|
||||
runtime.queueDisplayUpdate();
|
||||
this.setChangedState();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,11 @@ namespace pxsim {
|
||||
namespace pxsim.output {
|
||||
|
||||
export function setLights(pattern: number) {
|
||||
const lightState = ev3board().getBrickNode().lightState;
|
||||
lightState.lightPattern = pattern;
|
||||
runtime.queueDisplayUpdate();
|
||||
const brickState = ev3board().getBrickNode();
|
||||
const lightState = brickState.lightState;
|
||||
if (lightState.lightPattern != pattern) {
|
||||
lightState.lightPattern = pattern;
|
||||
brickState.setChangedState();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
namespace pxsim {
|
||||
|
||||
export class MotorNode extends BaseNode {
|
||||
export abstract class MotorNode extends BaseNode {
|
||||
isOutput = true;
|
||||
|
||||
public angle: number = 0;
|
||||
protected angle: number = 0;
|
||||
|
||||
private speed: number;
|
||||
private large: boolean;
|
||||
@ -18,7 +18,8 @@ namespace pxsim {
|
||||
if (this.speed != speed) {
|
||||
this.speed = speed;
|
||||
this.changed = true;
|
||||
runtime.queueDisplayUpdate();
|
||||
this.setChangedState();
|
||||
this.playMotorAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,8 +51,14 @@ namespace pxsim {
|
||||
|
||||
start() {
|
||||
// TODO: implement
|
||||
runtime.queueDisplayUpdate();
|
||||
this.setChangedState();
|
||||
}
|
||||
|
||||
public getAngle() {
|
||||
return this.angle;
|
||||
}
|
||||
|
||||
protected abstract playMotorAnimation(): void;
|
||||
}
|
||||
|
||||
export class MediumMotorNode extends MotorNode {
|
||||
@ -60,6 +67,32 @@ namespace pxsim {
|
||||
constructor(port: number) {
|
||||
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 {
|
||||
@ -69,5 +102,30 @@ namespace pxsim {
|
||||
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;
|
||||
return res;
|
||||
}
|
||||
|
||||
setChangedState() {
|
||||
this.changed = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ namespace pxsim {
|
||||
|
||||
|
||||
export class EV3ScreenState {
|
||||
changed: boolean = true;
|
||||
points: Uint8Array;
|
||||
constructor() {
|
||||
this.points = new Uint8Array(visuals.SCREEN_WIDTH * visuals.SCREEN_HEIGHT)
|
||||
@ -23,13 +24,13 @@ namespace pxsim {
|
||||
|
||||
setPixel(x: number, y: number, v: number) {
|
||||
this.applyMode(OFF(x, y), v)
|
||||
runtime.queueDisplayUpdate();
|
||||
this.changed = true;
|
||||
}
|
||||
|
||||
clear() {
|
||||
for (let i = 0; i < this.points.length; ++i)
|
||||
this.points[i] = 0;
|
||||
runtime.queueDisplayUpdate();
|
||||
this.changed = true;
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -72,6 +73,12 @@ namespace pxsim {
|
||||
off++
|
||||
}
|
||||
}
|
||||
|
||||
didChange() {
|
||||
const res = this.changed;
|
||||
this.changed = false;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,11 @@ namespace pxsim {
|
||||
this.valueChanged = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
setChangedState() {
|
||||
this.changed = true;
|
||||
this.valueChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
export class AnalogSensorNode extends SensorNode {
|
||||
|
@ -17,10 +17,7 @@ namespace pxsim {
|
||||
setDistance(distance: number) {
|
||||
if (this.distance != distance) {
|
||||
this.distance = distance;
|
||||
this.changed = true;
|
||||
this.valueChanged = true;
|
||||
|
||||
runtime.queueDisplayUpdate();
|
||||
this.setChangedState();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
/// <reference path="./layoutView.ts" />
|
||||
|
||||
namespace pxsim {
|
||||
export const GAME_LOOP_FPS = 32;
|
||||
}
|
||||
|
||||
namespace pxsim.visuals {
|
||||
|
||||
const EV3_STYLE = `
|
||||
@ -136,6 +140,12 @@ namespace pxsim.visuals {
|
||||
this.board.updateSubscribers.push(() => 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> {
|
||||
@ -167,54 +177,6 @@ namespace pxsim.visuals {
|
||||
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() {
|
||||
const bounds = this.element.getBoundingClientRect();
|
||||
this.width = bounds.width;
|
||||
@ -242,7 +204,7 @@ namespace pxsim.visuals {
|
||||
this.controlView.translate(controlCoords.x, controlCoords.y);
|
||||
}
|
||||
|
||||
this.updateScreen();
|
||||
//this.updateScreen();
|
||||
}
|
||||
|
||||
private getControlForNode(id: NodeType, port: number) {
|
||||
@ -355,7 +317,7 @@ namespace pxsim.visuals {
|
||||
this.closeIconView.setVisible(false);
|
||||
|
||||
this.resize();
|
||||
this.updateState();
|
||||
//this.updateState();
|
||||
|
||||
// Add Screen canvas to board
|
||||
this.buildScreenCanvas();
|
||||
@ -394,8 +356,84 @@ namespace pxsim.visuals {
|
||||
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;
|
||||
if (!state.didChange()) return;
|
||||
|
||||
const bBox = this.layoutView.getBrick().getScreenBBox();
|
||||
if (!bBox || bBox.width == 0) return;
|
||||
|
@ -78,7 +78,7 @@ namespace pxsim.visuals {
|
||||
return this.getInnerHeight() * 0.6;
|
||||
}
|
||||
|
||||
onBoardStateChanged() {
|
||||
updateState() {
|
||||
if (!this.isVisible) {
|
||||
return;
|
||||
}
|
||||
@ -91,7 +91,6 @@ namespace pxsim.visuals {
|
||||
onComponentVisible() {
|
||||
super.onComponentVisible();
|
||||
this.isVisible = true;
|
||||
this.onBoardStateChanged();
|
||||
}
|
||||
|
||||
onComponentHidden() {
|
||||
|
@ -60,7 +60,7 @@ namespace pxsim.visuals {
|
||||
return this.getInnerHeight() / 4;
|
||||
}
|
||||
|
||||
onBoardStateChanged() {
|
||||
updateState() {
|
||||
if (!this.isVisible) {
|
||||
return;
|
||||
}
|
||||
@ -74,7 +74,6 @@ namespace pxsim.visuals {
|
||||
onComponentVisible() {
|
||||
super.onComponentVisible();
|
||||
this.isVisible = true;
|
||||
this.onBoardStateChanged();
|
||||
}
|
||||
|
||||
onComponentHidden() {
|
||||
|
@ -35,10 +35,6 @@ namespace pxsim.visuals {
|
||||
return false;
|
||||
}
|
||||
|
||||
public shouldUpdateState() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public updateState() {
|
||||
this.updateLight();
|
||||
}
|
||||
|
@ -18,36 +18,10 @@ namespace pxsim.visuals {
|
||||
if (this.lastMotorAnimationId) cancelAnimationFrame(this.lastMotorAnimationId);
|
||||
|
||||
if (!speed) return;
|
||||
this.playMotorAnimation(motorState);
|
||||
this.setMotorAngle(motorState.getAngle());
|
||||
}
|
||||
|
||||
private playMotorAnimation(state: MotorNode) {
|
||||
// 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) {
|
||||
private setMotorAngle(angle: number) {
|
||||
const holeEl = this.content.getElementById(this.normalizeId(LargeMotorView.ROTATING_ECLIPSE_ID))
|
||||
const width = 34;
|
||||
const height = 34;
|
||||
|
@ -28,36 +28,10 @@ namespace pxsim.visuals {
|
||||
if (this.lastMotorAnimationId) cancelAnimationFrame(this.lastMotorAnimationId);
|
||||
|
||||
if (!speed) return;
|
||||
this.playMotorAnimation(motorState);
|
||||
this.setMotorAngle(motorState.getAngle());
|
||||
}
|
||||
|
||||
private playMotorAnimation(state: MotorNode) {
|
||||
// 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) {
|
||||
private setMotorAngle(angle: number) {
|
||||
const holeEl = this.content.getElementById(this.normalizeId(MediumMotorView.ROTATING_ECLIPSE_ID))
|
||||
const width = 47.9;
|
||||
const height = 47.2;
|
||||
|
@ -61,10 +61,6 @@ namespace pxsim.visuals {
|
||||
}
|
||||
}
|
||||
|
||||
public shouldUpdateState() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public updateState() {
|
||||
}
|
||||
|
||||
@ -179,23 +175,8 @@ namespace pxsim.visuals {
|
||||
public setSelected(selected: boolean) { }
|
||||
|
||||
protected getView() {
|
||||
if (!this.rendered) {
|
||||
this.subscribe();
|
||||
}
|
||||
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 {
|
||||
|
35
tests/colors.ts
Normal file
35
tests/colors.ts
Normal file
@ -0,0 +1,35 @@
|
||||
tests.test("Detect color red", function () {
|
||||
brick.print("Point sensor to red", 0, 50)
|
||||
brick.print("and click enter", 0, 60)
|
||||
brick.buttonEnter.pauseUntil(ButtonEvent.Click)
|
||||
brick.clearScreen()
|
||||
let actualColor = sensors.color1.color()
|
||||
tests.assertClose("Color", actualColor, ColorSensorColor.Red, 0)
|
||||
})
|
||||
|
||||
tests.test("Bright ambient light", function () {
|
||||
brick.print("Point sensor to ceiling", 0, 50)
|
||||
brick.print("light and click enter", 0, 60)
|
||||
brick.buttonEnter.pauseUntil(ButtonEvent.Click)
|
||||
brick.clearScreen()
|
||||
let actualLight: number
|
||||
for (let i = 0; i < 4; i++) {
|
||||
actualLight = sensors.color1.ambientLight()
|
||||
loops.pause(500)
|
||||
}
|
||||
tests.assertClose("Light", actualLight, 20, 15)
|
||||
})
|
||||
|
||||
tests.test("Bright reflected light", function () {
|
||||
brick.print("Point sensor to white", 0, 50)
|
||||
brick.print("desk surface", 0, 60)
|
||||
brick.print("and click enter", 0, 70)
|
||||
brick.buttonEnter.pauseUntil(ButtonEvent.Click)
|
||||
brick.clearScreen()
|
||||
let actualLight: number
|
||||
for (let i = 0; i < 4; i++) {
|
||||
actualLight = sensors.color1.reflectedLight()
|
||||
loops.pause(500)
|
||||
}
|
||||
tests.assertClose("Light", actualLight, 17, 14)
|
||||
})
|
@ -1,47 +1,42 @@
|
||||
```typescript
|
||||
// add tests package
|
||||
tests.test("lgB set speed 10", () => {
|
||||
motors.largeB.setSpeed(10);
|
||||
loops.pause(100)
|
||||
loops.pause(500)
|
||||
tests.assertClose("speedB", 10, motors.largeB.speed(), 2)
|
||||
});
|
||||
tests.test("lgB set speed 25 (reversed)", () => {
|
||||
motors.largeB.setReversed(true)
|
||||
motors.largeB.setSpeed(25)
|
||||
loops.pause(100)
|
||||
loops.pause(500)
|
||||
tests.assertClose("speedB", -25, motors.largeB.speed(), 2)
|
||||
});
|
||||
tests.test("lgBC set speed 5", () => {
|
||||
motors.largeBC.setSpeed(5)
|
||||
loops.pause(100)
|
||||
loops.pause(500)
|
||||
tests.assertClose("speedB", 5, motors.largeB.speed(), 1);
|
||||
tests.assertClose("speedC", 5, motors.largeC.speed(), 1);
|
||||
});
|
||||
tests.test("lgBC steer 50% 2x", () => {
|
||||
motors.largeBC.setBrake(true)
|
||||
motors.largeBC.steer(50, 50, 1, MoveUnit.Rotations)
|
||||
loops.pause(1000)
|
||||
loops.pause(2000)
|
||||
tests.assertClose("largeB", 360, motors.largeB.angle(), 5)
|
||||
motors.largeBC.setBrake(false)
|
||||
})
|
||||
tests.test("lgBC steer 50% 500deg", () => {
|
||||
tests.test("lgBC steer 360deg", () => {
|
||||
motors.largeBC.setBrake(true)
|
||||
motors.largeBC.steer(50, 50, 135, MoveUnit.Degrees)
|
||||
loops.pause(1000)
|
||||
tests.assertClose("largeB", 135, motors.largeB.angle(), 5)
|
||||
motors.largeBC.steer(50, 50, 360, MoveUnit.Degrees)
|
||||
loops.pause(2000)
|
||||
tests.assertClose("largeB", 360, motors.largeB.angle(), 5)
|
||||
});
|
||||
tests.test("lgBC steer 50% 2s", () => {
|
||||
tests.test("lgBC steer 50% 1s", () => {
|
||||
motors.largeBC.setBrake(true)
|
||||
motors.largeBC.steer(50, 50, 500, MoveUnit.MilliSeconds)
|
||||
loops.pause(1000)
|
||||
motors.largeBC.steer(10, 50, 1000, MoveUnit.MilliSeconds)
|
||||
loops.pause(2000)
|
||||
})
|
||||
tests.test("lgBC tank 50% 720deg", () => {
|
||||
tests.test("lgBC tank 50% 180deg", () => {
|
||||
motors.largeBC.setBrake(true)
|
||||
motors.largeBC.tank(50, 50, 180, MoveUnit.Degrees)
|
||||
loops.pause(1000)
|
||||
tests.assertClose("largeB", 180, motors.largeB.angle(), 5)
|
||||
});
|
||||
```
|
||||
|
||||
```package
|
||||
tests
|
||||
```
|
7
tests/touch.ts
Normal file
7
tests/touch.ts
Normal file
@ -0,0 +1,7 @@
|
||||
tests.test("Touch sensor pressed", function () {
|
||||
brick.print("Press touch sensor", 0, 50)
|
||||
brick.print("and click enter", 0, 60)
|
||||
brick.buttonEnter.pauseUntil(ButtonEvent.Click)
|
||||
brick.clearScreen()
|
||||
tests.assert("Pressed", sensors.touchSensor1.isPressed())
|
||||
})
|
9
tests/ultrasonic.ts
Normal file
9
tests/ultrasonic.ts
Normal file
@ -0,0 +1,9 @@
|
||||
tests.test("Ultrasonic sensor", function () {
|
||||
brick.print("Place object ", 0, 50)
|
||||
brick.print("one finger's length", 0, 60)
|
||||
brick.print("in front of sensor", 0, 70)
|
||||
brick.print("and click enter", 0, 80)
|
||||
brick.buttonEnter.pauseUntil(ButtonEvent.Click)
|
||||
brick.clearScreen()
|
||||
tests.assertClose("Distance", sensors.ultrasonic1.distance(), 7, 6)
|
||||
})
|
@ -28,9 +28,14 @@
|
||||
|
||||
div.blocklyTreeRow {
|
||||
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);
|
||||
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 */
|
||||
@ -51,6 +56,7 @@ span.blocklyTreeLabel {
|
||||
margin: 0.5rem;
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
.blocklySearchInputField {
|
||||
border-radius: 1rem !important;
|
||||
|
@ -10,7 +10,7 @@
|
||||
@emSize : 14px;
|
||||
@fontSize : 13px;
|
||||
|
||||
@primaryColor: @red;
|
||||
@primaryColor: @blue;
|
||||
@secondaryColor: @yellow;
|
||||
|
||||
@teal:#08415C;
|
||||
@ -88,6 +88,8 @@
|
||||
|
||||
@pageBackground: #fff;
|
||||
|
||||
@positiveColor: @blue;
|
||||
@defaultBorderRadius: 0px;
|
||||
|
||||
@inputPlaceholderColor: lighten(@inputColor, 80);
|
||||
|
||||
|
Reference in New Issue
Block a user