diff --git a/index.html b/index.html
index 6213bf0..ff877f9 100644
--- a/index.html
+++ b/index.html
@@ -91,20 +91,6 @@
-
-
@@ -312,14 +298,14 @@
- 20
+ 5
- 20
+ 5
@@ -332,14 +318,14 @@
pi.PUD_DOWN
- 4
+ 6
- 4
+ 6
@@ -348,7 +334,7 @@
50
- 20
+ 5
@@ -360,14 +346,14 @@
- 20
+ 5
- 14
+ 12
@@ -436,16 +422,6 @@
-
- 11
- 気温
- 湿度
-
-
- 4
-
-
-
1
@@ -564,37 +540,11 @@
meow
-
+
ことば
once
TRUE
-
-
@@ -658,7 +608,7 @@
-
+
@@ -702,11 +652,6 @@
お名前は?
-
-
- 5
-
-
@@ -808,9 +753,6 @@
-
-
-
@@ -902,12 +844,68 @@
-
-
-
+
+
+ 答え
+
+
+ お名前は?
+
+
+
+
+
+
+ ・・・
+
+
+
+
+ 2
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+ 答え
+
+
+
+
+ たん
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package-lock.json b/package-lock.json
index 115a786..9417f9a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -775,9 +775,9 @@
}
},
"electron": {
- "version": "11.2.3",
- "resolved": "https://registry.npmjs.org/electron/-/electron-11.2.3.tgz",
- "integrity": "sha512-6yxOc42nDAptHKNlUG/vcOh2GI9x2fqp2nQbZO0/3sz2CrwsJkwR3i3oMN9XhVJaqI7GK1vSCJz0verOkWlXcQ==",
+ "version": "11.3.0",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-11.3.0.tgz",
+ "integrity": "sha512-MhdS0gok3wZBTscLBbYrOhLaQybCSAfkupazbK1dMP5c+84eVMxJE/QGohiWQkzs0tVFIJsAHyN19YKPbelNrQ==",
"dev": true,
"requires": {
"@electron/get": "^1.0.1",
@@ -1249,9 +1249,9 @@
}
},
"globalthis": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz",
- "integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz",
+ "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==",
"dev": true,
"optional": true,
"requires": {
@@ -1499,9 +1499,9 @@
}
},
"lodash": {
- "version": "4.17.20",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
- "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true,
"optional": true
},
diff --git a/package.json b/package.json
index 859e2d9..7fcb72c 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
},
"homepage": "https://github.com/ocogeclub/ocoge#readme",
"devDependencies": {
- "electron": "11.2.3",
+ "electron": "11.3.0",
"electron-rebuild": "^2.3.4"
},
"dependencies": {
diff --git a/scripts/eleclib.js b/scripts/eleclib.js
index abfd9df..48cbd3f 100644
--- a/scripts/eleclib.js
+++ b/scripts/eleclib.js
@@ -5,7 +5,7 @@
// ローカルプロパティ
// Hard Coding!!!
const appName = 'ocoge';
-const defpath = '/home/pi/Documents/ocoge/';
+const defpath = '/home/pi/Documents/ocoge_docs/';
const mascotDefPath = '/home/pi/Applications/ocoge/img/';
// Require
const fs = require('fs');
@@ -18,7 +18,7 @@ const clipboard = require('electron').clipboard;
var saveFilepath = null;
var wsChanged = false;
-var mascotFilePath = './img/cogechee.png';
+var mascotFilePath = mascotDefPath + 'cogechee.png';
// 0で数値の桁合わせ
// NUM=値 LEN=桁数
@@ -26,10 +26,10 @@ const zeroPadding = (NUM, LEN) => (Array(LEN).join('0') + NUM).slice(-LEN);
// 現在の日付時刻から workspace フォルダ内のユニークなファイルパスを作成
const getUniqueFilepath = () => {
- let today = new Date();
- let filename = today.getFullYear() + '-' + zeroPadding((today.getMonth() + 1), 2) + '-' + zeroPadding(today.getDate(), 2) + '-' + zeroPadding(today.getHours(), 2) + '-' + zeroPadding(today.getMinutes(), 2) + '-' + zeroPadding(today.getSeconds(), 2);
- let filepath = path.join(defpath, filename);
- return filepath;
+ let today = new Date();
+ let filename = today.getFullYear() + '-' + zeroPadding((today.getMonth() + 1), 2) + '-' + zeroPadding(today.getDate(), 2) + '-' + zeroPadding(today.getHours(), 2) + '-' + zeroPadding(today.getMinutes(), 2) + '-' + zeroPadding(today.getSeconds(), 2);
+ let filepath = path.join(defpath, filename);
+ return filepath;
}
// クリップボードにコピー
@@ -37,7 +37,7 @@ exports.copyText = text => clipboard.writeText(text);
// リンクを外部ブラウザで開く
exports.openURL = (url) => {
- shell.openExternal(url);
+ shell.openExternal(url);
}
// タイトルバーにファイル名を表示
@@ -50,23 +50,23 @@ exports.openURL = (url) => {
// saveFilepath を更新
// ウィンドウタイトルバーテキストを変更
const setSaveFilepath = filepath => {
- let title;
- saveFilepath = filepath;
- // if (filepath) title = filepath + ' - ' + appName;
- // else title = appName;
- // mainWin.setTitle(title);
- this.setWsChanged(false);
+ let title;
+ saveFilepath = filepath;
+ // if (filepath) title = filepath + ' - ' + appName;
+ // else title = appName;
+ // mainWin.setTitle(title);
+ this.setWsChanged(false);
}
// ワークスペースが変更された・保存された
// ウィンドウタイトルバーテキストを変更
exports.setWsChanged = changed => {
- let title;
- wsChanged = changed;
- if (saveFilepath) title = saveFilepath + ' - ' + appName;
- else title = appName;
- if (changed) title = '*' + title;
- mainWin.setTitle(title);
+ let title;
+ wsChanged = changed;
+ if (saveFilepath) title = saveFilepath + ' - ' + appName;
+ else title = appName;
+ if (changed) title = '*' + title;
+ mainWin.setTitle(title);
}
// 保存ファイルプロパティを更新
@@ -74,159 +74,161 @@ exports.newFile = () => setSaveFilepath(null);
// ワークスペースファイル読み込みの一連の動作のラッパ
exports.loadWsFile = () => {
- let filepath = openFile('xml', defpath);
- if (filepath.length > 0) {
- if (saveFilepath === null) {
- setSaveFilepath(filepath);
- } //読み込みに失敗してもsaveFilepathが更新されてしまうのはちょっと具合が悪いかも
- return readFromFile(filepath);
- } else {
- return '';
- }
+ let filepath = openFile('xml', defpath);
+ if (filepath.length > 0) {
+ if (saveFilepath === null) {
+ setSaveFilepath(filepath);
+ } //読み込みに失敗してもsaveFilepathが更新されてしまうのはちょっと具合が悪いかも
+ return readFromFile(filepath);
+ } else {
+ return '';
+ }
}
// その他ファイル読み込みの一連の動作のラッパ
exports.loadFile = ext => {
- let filepath = openFile(ext, defpath);
- if (filepath.length > 0) {
- return readFromFile(filepath);
- } else {
- return '';
- }
+ let filepath = openFile(ext, defpath);
+ if (filepath.length > 0) {
+ return readFromFile(filepath);
+ } else {
+ return '';
+ }
}
exports.selectMascotFile = () => {
- return openFile('png', mascotDefPath);
+ return openFile('png', mascotDefPath);
}
// オープンファイルダイアログ
const openFile = (ext, dpath) => {
- let filter;
- if (ext == 'xml') {
- filter = { name: 'XML - Extensible Markup Language', extensions: ['xml'] };
- } else if (ext == 'js') {
- filter = { name: 'JS - JavaScript', extensions: ['js'] };
- } else if (ext == 'png') {
- filter = { name: 'PNG - Portable Network Graphics', extensions: ['png'] };
- } else {
- filter = { name: 'text file', extensions: ['txt'] };
- }
- let filepaths = dialog.showOpenDialogSync(mainWin, {
- properties: ['openFile'],
- title: 'Select a file',
- defaultPath: dpath,
- filters: [
- filter
- ]
- });
- if (filepaths == undefined) {
- return '';
- } else {
- return filepaths[0];
- }
+ let filter;
+ if (ext == 'xml') {
+ filter = { name: 'XML - Extensible Markup Language', extensions: ['xml'] };
+ } else if (ext == 'js') {
+ filter = { name: 'JS - JavaScript', extensions: ['js'] };
+ } else if (ext == 'png') {
+ filter = { name: 'PNG - Portable Network Graphics', extensions: ['png'] };
+ } else {
+ filter = { name: 'text file', extensions: ['txt'] };
+ }
+ let filepaths = dialog.showOpenDialogSync(mainWin, {
+ properties: ['openFile'],
+ title: 'Select a file',
+ defaultPath: dpath,
+ filters: [
+ filter
+ ]
+ });
+ if (filepaths == undefined) {
+ return '';
+ } else {
+ return filepaths[0];
+ }
}
// ファイルからデータを読み込み
const readFromFile = filepath => {
- let data = '';
- try {
- data = fs.readFileSync(filepath, 'utf-8');
- }
- catch (err) {
- console.log(err);
- }
- return data;
+ let data = '';
+ try {
+ data = fs.readFileSync(filepath, 'utf-8');
+ }
+ catch (err) {
+ console.log(err);
+ }
+ return data;
}
// テキストファイル読み込み: 外部スクリプト動的読み込みに使用
exports.readTextFile = filepath => {
- return readFromFile(filepath);
+ return readFromFile(filepath);
}
// ワークスペースファイル保存の一連の動作のラッパ
exports.saveWsFile = data => {
- if (saveFilepath === null) {
- let filepath = selectSaveFile('xml');
- if (filepath === undefined) { //キャンセル
- return undefined;
- } else {
- setSaveFilepath(filepath);
- } //これも保存が成功したら変更するようにすべきかしら
- } else this.setWsChanged(false);
- return writeToFile(saveFilepath, data);
+ if (saveFilepath === null) {
+ let filepath = selectSaveFile('xml');
+ if (filepath === undefined) { //キャンセル
+ return undefined;
+ } else {
+ setSaveFilepath(filepath);
+ } //これも保存が成功したら変更するようにすべきかしら
+ } else this.setWsChanged(false);
+ return writeToFile(saveFilepath, data);
}
// その他ファイル保存の一連の動作のラッパ
exports.saveFile = (data, ext) => {
- let filepath = selectSaveFile(ext);
- if (filepath === undefined) { //キャンセル
- return undefined;
- }
- return writeToFile(filepath, data);
+ let filepath = selectSaveFile(ext);
+ if (filepath === undefined) { //キャンセル
+ return undefined;
+ }
+ return writeToFile(filepath, data);
}
// ファイル保存ダイアログ
const selectSaveFile = ext => {
- let filter;
- let defName;
- if (ext == 'xml') {
- filter = { name: 'xml file', extensions: ['xml'] };
- defName = getUniqueFilepath() + '.xml';
- } else if (ext == 'js') {
- filter = { name: 'javascript file', extensions: ['js'] };
- // ワークスペース保存名がある場合、それをベースにファイル名の候補を決める
- if (saveFilepath === null) {
- defName = getUniqueFilepath() + '.js';
- } else {
- let dirname = path.dirname(saveFilepath);
- let basename = path.basename(saveFilepath, '.xml');
- defName = path.join(dirname, basename) + '.js';
- }
+ let filter;
+ let defName;
+ if (ext == 'xml') {
+ filter = { name: 'xml file', extensions: ['xml'] };
+ defName = getUniqueFilepath() + '.xml';
+ } else if (ext == 'js') {
+ filter = { name: 'javascript file', extensions: ['js'] };
+ // ワークスペース保存名がある場合、それをベースにファイル名の候補を決める
+ if (saveFilepath === null) {
+ defName = getUniqueFilepath() + '.js';
} else {
- filter = { name: 'text file', extensions: ['txt'] };
+ let dirname = path.dirname(saveFilepath);
+ let basename = path.basename(saveFilepath, '.xml');
+ defName = path.join(dirname, basename) + '.js';
}
- let filename = dialog.showSaveDialogSync(mainWin, {
- title: '保存先を決定してください',
- defaultPath: defName,
- filters: [filter]
- });
- return filename;
+ } else {
+ filter = { name: 'text file', extensions: ['txt'] };
+ }
+ let filename = dialog.showSaveDialogSync(mainWin, {
+ title: '保存先を決定してください',
+ defaultPath: defName,
+ filters: [filter]
+ });
+ return filename;
}
// ファイル書き込み
const writeToFile = (filepath, data) => {
- try {
- fs.writeFileSync(filepath, data);
- return true;
- }
- catch (err) {
- return false;
- }
+ try {
+ fs.writeFileSync(filepath, data);
+ return true;
+ }
+ catch (err) {
+ return false;
+ }
}
// 子プロセス関連
let children = [];
// 新しい子プロセスを作成し、配列に保存
exports.addChild = (child) => {
- children.push(child);
+ children.push(child);
}
// 全ての子プロセスを殺し、配列をクリア
exports.killAllChildren = () => {
- children.forEach(function( child ) {
- child.kill();
- });
- children = [];
+ children.forEach(function (child) {
+ child.kill();
+ });
+ children = [];
}
// 設定(保存ファイルパスと未保存フラグ)をローカルストレージに保存
exports.savePrefsToLS = () => {
- let wc = '0';
- if (wsChanged) wc = '1';
- let o = { 'saveFilepath': saveFilepath, 'wsChanged': wc, 'mascotFilePath': mascotFilePath };
- let s = JSON.stringify(o);
- localStorage.setItem("abrage.json", s);
+ let wc = '0';
+ if (wsChanged) wc = '1';
+ let o = { 'saveFilepath': saveFilepath, 'wsChanged': wc, 'mascotFilePath': mascotFilePath };
+ let s = JSON.stringify(o);
+ localStorage.setItem("ocoge.json", s);
}
// 設定(保存ファイルパスと未保存フラグ)をローカルストレージからロード
exports.loadPrefsFromLS = () => {
- let s = localStorage.getItem("abrage.json");
+ let s = localStorage.getItem("ocoge.json");
+ if (s !== null) {
let o = JSON.parse(s);
setSaveFilepath(o.saveFilepath);
if (o.wsChanged == '0') this.setWsChanged(false);
else this.setWsChanged(true);
if (o.mascotFilePath) this.setMascotFilePath(o.mascotFilePath);
+ }
}
// マスコット画像パスをプロパティにセット
@@ -236,5 +238,5 @@ exports.getMascotFilePath = () => mascotFilePath;
// ファイル名にアプリケーションのドキュメントルートまでのパスをつけて返す
exports.getDocPath = filename => {
- return path.join(appDocRoot, filename);
+ return path.join(appDocRoot, filename);
}
diff --git a/scripts/ugj_blocks.js b/scripts/ugj_blocks.js
index a2a53a8..08cf0d7 100644
--- a/scripts/ugj_blocks.js
+++ b/scripts/ugj_blocks.js
@@ -1,5 +1,5 @@
/** Hard Coding!!! */
-const appDocRoot = '/home/pi/Documents/ocoge/'
+const appDocRoot = '/home/pi/Documents/ocoge_docs/'
/** Fix Basic Blocks ****************************************************************************************/
Blockly.Blocks['ugj_control_for'] = {
@@ -24,36 +24,10 @@ Blockly.Blocks['ugj_control_for'] = {
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(Blockly.Msg.LOOPS_HUE);
- this.setTooltip("");
+ this.setTooltip("インデックス番号を決められた数ずつ増やし(減らし)ながら、ステートメントを実行します。");
this.setHelpUrl("");
}
};
-
-// Blockly.Blocks['ugj_controls_for'] = {
-// init: function () {
-// this.appendDummyInput()
-// .appendField(new Blockly.FieldVariable("番号"), "index");
-// this.appendValueInput("from")
-// .setCheck("Number")
-// .appendField("を");
-// this.appendValueInput("to")
-// .setCheck("Number")
-// .appendField("から");
-// this.appendValueInput("by")
-// .setCheck("Number")
-// .appendField("まで");
-// this.appendDummyInput()
-// .appendField("ずつ増やしながら");
-// this.appendStatementInput("do")
-// .setCheck(null);
-// this.setInputsInline(true);
-// this.setPreviousStatement(true, null);
-// this.setNextStatement(true, null);
-// this.setColour(Blockly.Msg.LOOPS_HUE);
-// this.setTooltip("インデックス番号を決められた数ずつ増やし(減らし)ながら、ステートメントを実行します。");
-// this.setHelpUrl("");
-// }
-// };
Blockly.JavaScript['ugj_control_for'] = function (block) {
var variable_index = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('index'), Blockly.Variables.NAME_TYPE);
var value_from = Blockly.JavaScript.valueToCode(block, 'from', Blockly.JavaScript.ORDER_ATOMIC);
@@ -72,20 +46,6 @@ Blockly.JavaScript['ugj_control_for'] = function (block) {
].join('\n');
return code;
};
-// Blockly.JavaScript['ugj_controls_for'] = function (block) {
-// var variable_index = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('index'), Blockly.Variables.NAME_TYPE);
-// var value_from = Blockly.JavaScript.valueToCode(block, 'from', Blockly.JavaScript.ORDER_ATOMIC);
-// var value_to = Blockly.JavaScript.valueToCode(block, 'to', Blockly.JavaScript.ORDER_ATOMIC);
-// var value_by = Blockly.JavaScript.valueToCode(block, 'by', Blockly.JavaScript.ORDER_ATOMIC);
-// var statements_do = Blockly.JavaScript.statementToCode(block, 'do');
-// var code = [
-// `for (${variable_index} = ${value_from}; ${variable_index} <= ${value_to}; ${variable_index} += ${value_by}) {`,
-// statements_do,
-// `}`,
-// ''
-// ].join('\n');
-// return code;
-// };
Blockly.Blocks['ugj_controls_forEach'] = {
init: function () {
@@ -146,16 +106,18 @@ Blockly.JavaScript['ugj_hextodec'] = function (block) {
/************* */
/** GPIO Start */
/************* */
+var ugjGpioStart = {
+ "type": "ugj_gpio_start",
+ "message0": "%{BKY_GPIO_START_TITLE}",
+ "previousStatement": null,
+ "nextStatement": null,
+ "tooltip": "%{BKY_GPIO_START_TOOLTIP}",
+ "helpUrl": "",
+ "style": "gpio_blocks"
+};
Blockly.Blocks['ugj_gpio_start'] = {
init: function () {
- this.appendDummyInput()
- .appendField("GPIO を使えるようにする");
- this.setInputsInline(true);
- this.setPreviousStatement(true, null);
- this.setNextStatement(true, null);
- this.setStyle('gpio_blocks')
- this.setTooltip("GPIOを初期化して接続します。");
- this.setHelpUrl("");
+ this.jsonInit(ugjGpioStart);
}
};
Blockly.JavaScript['ugj_gpio_start'] = function (block) {
@@ -187,16 +149,40 @@ Blockly.JavaScript['ugj_gpio_start_remote'] = function (block) {
/************ */
/** GPIO Stop */
/************ */
+// var ugjGpioStart = {
+// "type": "ugj_gpio_start",
+// "message0": "%{BKY_GPIO_START_TITLE}",
+// "previousStatement": null,
+// "nextStatement": null,
+// "tooltip": "%{BKY_GPIO_START_TOOLTIP}",
+// "helpUrl": "",
+// "style": "gpio_blocks"
+// };
+// Blockly.Blocks['ugj_gpio_start'] = {
+// init: function () {
+// this.jsonInit(ugjGpioStart);
+// }
+// };
+var ugjGpioStop = {
+ "type": "ugj_gpio_stop",
+ "message0": "%{BKY_GPIO_STOP_TITLE}",
+ "previousStatement": null,
+ "nextStatement": null,
+ "tooltip": "%{BKY_GPIO_STOP_TOOLTIP}",
+ "helpUrl": "",
+ "style": "gpio_blocks"
+};
Blockly.Blocks['ugj_gpio_stop'] = {
init: function () {
- this.appendDummyInput()
- .appendField("GPIO の後片付けをする");
- this.setInputsInline(true);
- this.setPreviousStatement(true, null);
- this.setNextStatement(true, null);
- this.setStyle('gpio_blocks')
- this.setTooltip("GPIOとの接続を終了します。");
- this.setHelpUrl("");
+ this.jsonInit(ugjGpioStop);
+ // this.appendDummyInput()
+ // .appendField("GPIO の後片付けをする");
+ // this.setInputsInline(true);
+ // this.setPreviousStatement(true, null);
+ // this.setNextStatement(true, null);
+ // this.setStyle('gpio_blocks')
+ // this.setTooltip("GPIOとの接続を終了します。");
+ // this.setHelpUrl("");
}
};
Blockly.JavaScript['ugj_gpio_stop'] = function (block) {
@@ -584,45 +570,6 @@ Blockly.JavaScript['ugj_gpio_i2creadbyte'] = function (block) {
return [code, Blockly.JavaScript.ORDER_NONE];
};
-/*********** */
-/** DHT11/22 */
-/*********** */
-Blockly.Blocks['ugj_dht'] = {
- init: function () {
- this.appendValueInput("gpio")
- .setCheck("Number")
- .appendField("GPIO");
- this.appendDummyInput()
- .appendField("の温湿度センサー DHT")
- .appendField(new Blockly.FieldDropdown([["11", "11"], ["22", "22"]]), "type")
- .appendField("から")
- .appendField(new Blockly.FieldVariable("気温"), "temperature")
- .appendField(new Blockly.FieldVariable("湿度"), "humidity")
- .appendField("を取得");
- this.setInputsInline(true);
- this.setPreviousStatement(true, null);
- this.setNextStatement(true, null);
- this.setStyle('gpio_blocks')
- this.setTooltip("温湿度センサー DHT11/DHT22 を使用して気温と湿度を読み取ります。");
- this.setHelpUrl("");
- }
-};
-Blockly.JavaScript['ugj_dht'] = function (block) {
- var value_gpio = Blockly.JavaScript.valueToCode(block, 'gpio', Blockly.JavaScript.ORDER_ATOMIC);
- var dropdown_type = block.getFieldValue('type');
- var variable_temperature = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('temperature'), Blockly.Variables.NAME_TYPE);
- var variable_humidity = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('humidity'), Blockly.Variables.NAME_TYPE);
- let fix = dropdown_type / 11 - 1;
- var code = [
- `try {`,
- `let res = await dht.read(${dropdown_type}, ${value_gpio});`,
- `${variable_temperature} = res.temperature.toFixed(${fix});`,
- `${variable_humidity} = res.humidity.toFixed(${fix});`,
- `} catch (err) {console.error("Failed to read sensor data:", err);}`,
- ''
- ].join('\n');
- return code;
-};
@@ -1223,109 +1170,6 @@ Blockly.JavaScript['ugj_sound_play'] = function (block) {
return code;
};
-/***************************** */
-/** Cloud Speech Recognization */
-/***************************** */
-Blockly.Blocks['ugj_multimedia_cloudspeech_recognition'] = {
- init: function () {
- this.appendDummyInput()
- .appendField("音声認識で")
- .appendField(new Blockly.FieldVariable("ことば"), "transcript")
- .appendField("を取得する:")
- .appendField(new Blockly.FieldDropdown([["一回のみ", "once"], ["継続", "continue"]]), "continuous")
- .appendField(new Blockly.FieldCheckbox("TRUE"), "interim")
- .appendField("未確定も取得");
- this.appendStatementInput("isFinal_do")
- .setCheck(null)
- .appendField("確定したら");
- this.appendStatementInput("isInterim_do")
- .setCheck(null)
- .appendField("未確定なら");
- this.appendStatementInput("onStart_do")
- .setCheck(null)
- .appendField("開始したら");
- this.appendStatementInput("onError_do")
- .setCheck(null)
- .appendField("停止したら");
- this.setInputsInline(true);
- this.setPreviousStatement(true);
- this.setStyle('multimedia_blocks')
- this.setTooltip("Google Cloud Speech API による音声認識を行います。言葉を検知したらステートメントが実行されます。認識途中の暫定結果を取得することもできます。");
- this.setHelpUrl("");
- }
-};
-Blockly.JavaScript['ugj_multimedia_cloudspeech_recognition'] = function (block) {
- var variable_transcript = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('transcript'), Blockly.Variables.NAME_TYPE);
- var dropdown_continuous = block.getFieldValue('continuous');
- var checkbox_interim = block.getFieldValue('interim') == 'TRUE';
- var statements_isfinal_do = Blockly.JavaScript.statementToCode(block, 'isFinal_do');
- var statements_isinterim_do = Blockly.JavaScript.statementToCode(block, 'isInterim_do');
- var statements_onStart_do = Blockly.JavaScript.statementToCode(block, 'onStart_do');
- var statements_onError_do = Blockly.JavaScript.statementToCode(block, 'onError_do');
- var functionName = Blockly.JavaScript.provideFunction_(
- 'listenTimeout',
- [
- 'const ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = () => {',
- 'clearTimeout(tout);',
- 'tout = setTimeout(() => {',
- `console.log('Timeout.');`,
- 'recording.stop();',
- '}, 15000);',
- '}'
- ]
- );
- var code = [
- `const client = new speech.SpeechClient({`,
- `projectId: 'ugjiclass',`,
- `keyFilename: './.shared/OCOGE-8a8e7ecac31c.json',`,
- `});`,
- `const request = {`,
- `config: {`,
- `encoding: 'LINEAR16',`,
- `sampleRateHertz: 16000,`,
- `languageCode: 'ja-JP'`,
- `},`,
- ``].join('\n');
- if (dropdown_continuous == 'once') code += 'singleUtterance: true,\n';
- if (checkbox_interim == true) code += 'interimResults: true,\n';
- code += [
- `};`,
- `var tout;`,
- `${functionName}();`,
- `const recognizeStream = client`,
- `.streamingRecognize(request)`,
- `.on('error', console.error)`,
- `.on('data', data => {`,
- `let result = data.results[0];`,
- `if (result && result.alternatives[0]) {`,
- `${variable_transcript} = result.alternatives[0].transcript;`,
- `if (result.isFinal) {`,
- statements_isfinal_do,
- `${functionName}();`,
- `} else {`,
- statements_isinterim_do,
- `}`,
- `} else {`,
- `console.log('Reached transcription time limit.');`,
- `recording.stop();`,
- 'clearTimeout(tout);',
- `}`,
- `});`,
- `const recording = recorder.record({`,
- `sampleRate: 16000,`,
- `recorder: 'sox',`,
- `silence: '0.5',`,
- `});`,
- `recording`,
- `.stream()`,
- `.on('error', err => {${statements_onError_do}})`,
- `.pipe(recognizeStream);`,
- statements_onStart_do,
- ''
- ].join('\n');
- return code;
-};
-
/*************************** */
/** Web Speech Recognization */
/*************************** */
@@ -1353,7 +1197,7 @@ Blockly.Blocks['ugj_multimedia_webspeech_recognition'] = {
this.setInputsInline(true);
this.setPreviousStatement(true);
this.setStyle('multimedia_blocks')
- this.setTooltip("Web Speech API による音声認識を行います。言葉を検知したらステートメントが実行されます。認識途中の暫定結果を取得することもできます。");
+ this.setTooltip("Web Speech API による音声認識を行います。言葉を検知したらステートメントが実行されます。認識途中の暫定結果を取得することもできます。※Web版のみの機能です。");
this.setHelpUrl("");
}
};
@@ -1996,9 +1840,6 @@ Blockly.Blocks['ugj_event_answer'] = {
init: function () {
this.appendValueInput("question")
.setCheck("String");
- // this.appendValueInput("sec")
- // .setCheck("Number")
- // .appendField("と");
this.appendDummyInput()
.appendField("ときいて")
.appendField(new Blockly.FieldVariable("答え"), "answer")
@@ -2013,7 +1854,6 @@ Blockly.Blocks['ugj_event_answer'] = {
};
Blockly.JavaScript['ugj_event_answer'] = function (block) {
var value_question = Blockly.JavaScript.valueToCode(block, 'question', Blockly.JavaScript.ORDER_ATOMIC);
- // var value_sec = Blockly.JavaScript.valueToCode(block, 'sec', Blockly.JavaScript.ORDER_ATOMIC);
var variable_answer = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('answer'), Blockly.Variables.NAME_TYPE);
var statements_do = Blockly.JavaScript.statementToCode(block, 'do');
var code = [
@@ -2126,24 +1966,7 @@ Blockly.JavaScript['ugj_child_gesture'] = function (block) {
var code = `'python3', ['./scripts/gesture.py']`;
return [code, Blockly.JavaScript.ORDER_NONE];
};
-// face.py
-Blockly.Blocks['ugj_child_facepy'] = {
- init: function () {
- this.appendDummyInput()
- .appendField("face.py:カメラ画像を表示")
- .appendField(new Blockly.FieldDropdown([["しない", " "], ["する", "-w"]]), "win");
- this.setOutput(true, "shcmd");
- this.setOutputShape(Blockly.OUTPUT_SHAPE_ROUND);
- this.setStyle('special_blocks')
- this.setTooltip("OpenCVによる顔認識 Python2スクリプト - 顔のX座標を返します。");
- this.setHelpUrl("");
- }
-};
-Blockly.JavaScript['ugj_child_facepy'] = function (block) {
- var dropdown_win = block.getFieldValue('win');
- var code = `'python', ['./scripts/face.py', '${dropdown_win}']`;
- return [code, Blockly.JavaScript.ORDER_NONE];
-};
+
// open jtalk
Blockly.Blocks['ugj_child_openjtalk'] = {
init: function () {
@@ -2364,29 +2187,6 @@ Blockly.JavaScript['ugj_child_testjs'] = function (block) {
// TODO: Change ORDER_NONE to the correct strength.
return [code, Blockly.JavaScript.ORDER_NONE];
};
-// Debug *Danger*
-Blockly.Blocks['ugj_child_debug'] = {
- init: function () {
- this.appendValueInput("cmd")
- .setCheck("String")
- .appendField("cmd");
- this.appendValueInput("opt")
- .setCheck("Array")
- .appendField("opt");
- this.setInputsInline(true);
- this.setOutput(true, "shcmd");
- this.setOutputShape(Blockly.OUTPUT_SHAPE_ROUND);
- this.setStyle('special_blocks')
- this.setTooltip("さわるなきけん");
- this.setHelpUrl("");
- }
-};
-Blockly.JavaScript['ugj_child_debug'] = function (block) {
- var value_cmd = Blockly.JavaScript.valueToCode(block, 'cmd', Blockly.JavaScript.ORDER_ATOMIC);
- var value_opt = Blockly.JavaScript.valueToCode(block, 'opt', Blockly.JavaScript.ORDER_ATOMIC);
- var code = `${value_cmd}, ${value_opt}`;
- return [code, Blockly.JavaScript.ORDER_NONE];
-};
/******************* */
/** Show Blackboard ** */
diff --git a/scripts/ugj_script.js b/scripts/ugj_script.js
index 8ac70e5..8bd4ed9 100644
--- a/scripts/ugj_script.js
+++ b/scripts/ugj_script.js
@@ -1,5 +1,5 @@
const testfunc = () => {
- elec.openURL('http://ocoge.club');
+ elec.openURL('http://ocoge.club');
}
//============ User Customize Start ===============
@@ -13,55 +13,49 @@ var network_color = '340';
var special_color = '20';
var snippets_color = '90';
-// Blockly.Msg.UGJ_GPIO_HUE = 0;//FF7799
-// Blockly.Msg.UGJ_MULTIMEDIA_HUE = 240;//CF63CF
-// Blockly.Msg.UGJ_NETWORK_HUE = 340;//"#54C4EA"
-// Blockly.Msg.UGJ_SPECIAL_HUE = 20;//"#0FBD8C"
-// Blockly.Msg.UGJ_SNIPPETS_HUE = 90;
-
var theme = Blockly.Theme.defineTheme('ocoge', {
- 'base': Blockly.Themes.Classic,
- 'startHats': true,
- 'componentStyles': {
- 'toolboxBackgroundColour': 'aliceblue',
- 'flyoutBackgroundColour': 'lavender',
- 'toolboxForegroundColour': 'white',
- 'flyoutForegroundColour': 'steelblue'
+ 'base': Blockly.Themes.Classic,
+ 'startHats': true,
+ 'componentStyles': {
+ 'toolboxBackgroundColour': 'aliceblue',
+ 'flyoutBackgroundColour': 'lavender',
+ 'toolboxForegroundColour': 'white',
+ 'flyoutForegroundColour': 'steelblue'
+ },
+ 'blockStyles': {
+ 'gpio_blocks': {
+ "colourPrimary": gpio_color
},
- 'blockStyles': {
- 'gpio_blocks': {
- "colourPrimary": gpio_color
- },
- 'multimedia_blocks': {
- "colourPrimary": multimedia_color
- },
- 'network_blocks': {
- "colourPrimary": network_color
- },
- 'special_blocks': {
- "colourPrimary": special_color
- },
- 'snippets_blocks': {
- "colourPrimary": snippets_color
- }
+ 'multimedia_blocks': {
+ "colourPrimary": multimedia_color
},
- 'categoryStyles': {
- "gpio_category": {
- "colour": gpio_color
- },
- "multimedia_category": {
- "colour": multimedia_color
- },
- "network_category": {
- "colour": network_color
- },
- "special_category": {
- "colour": special_color
- },
- "snippets_category": {
- "colour": snippets_color
- }
+ 'network_blocks': {
+ "colourPrimary": network_color
},
+ 'special_blocks': {
+ "colourPrimary": special_color
+ },
+ 'snippets_blocks': {
+ "colourPrimary": snippets_color
+ }
+ },
+ 'categoryStyles': {
+ "gpio_category": {
+ "colour": gpio_color
+ },
+ "multimedia_category": {
+ "colour": multimedia_color
+ },
+ "network_category": {
+ "colour": network_color
+ },
+ "special_category": {
+ "colour": special_color
+ },
+ "snippets_category": {
+ "colour": snippets_color
+ }
+ },
});
// Customize messages
@@ -70,71 +64,76 @@ Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"] = "";
Blockly.Msg["MATH_CHANGE_TITLE"] = "変数 %1 を %2 増やす";
Blockly.Msg["VARIABLES_SET"] = "変数 %1 を %2 にする";
Blockly.Msg["TEXT_PRINT_TITLE"] = "ダイアログに %1 を表示";
+Blockly.Msg["LOGIC_BOOLEAN_FALSE"] = "偽";
+Blockly.Msg["LOGIC_BOOLEAN_TOOLTIP"] = "真 または 偽 を返します。";
+Blockly.Msg["LOGIC_BOOLEAN_TRUE"] = "真";
+// ローカライズ対応の準備
+Blockly.Msg["GPIO_START_TITLE"] = "GPIO を使えるようにする";
+Blockly.Msg["GPIO_START_TOOLTIP"] = "GPIOを初期化して接続します。";
+Blockly.Msg["GPIO_STOP_TITLE"] = "GPIO の後片付けをする";
+Blockly.Msg["GPIO_STOP_TOOLTIP"] = "GPIOとの接続を終了します。";
// Customize Toolbox
class CustomCategory extends Blockly.ToolboxCategory {
- /** Constructor for a custom category. @override */
- constructor(categoryDef, toolbox, opt_parent) {
- super(categoryDef, toolbox, opt_parent);
- }
- /** @override */
- addColourBorder_(colour) {
- this.rowDiv_.style.backgroundColor = colour;
- }
- /** @override */
- setSelected(isSelected) {
- // We do not store the label span on the category, so use getElementsByClassName.
- var labelDom = this.rowDiv_.getElementsByClassName('blocklyTreeLabel')[0];
- if (isSelected) {
- // Change the background color of the div to white.
- this.rowDiv_.style.backgroundColor = 'white';
- // Set the colour of the text to the colour of the category.
- labelDom.style.color = this.colour_;
- this.iconDom_.style.color = this.colour_;
- } else {
- // Set the background back to the original colour.
- this.rowDiv_.style.backgroundColor = this.colour_;
- // Set the text back to white.
- labelDom.style.color = 'white';
- this.iconDom_.style.color = 'white';
- }
- // This is used for accessibility purposes.
- Blockly.utils.aria.setState(/** @type {!Element} */(this.htmlDiv_),
- Blockly.utils.aria.State.SELECTED, isSelected);
+ /** Constructor for a custom category. @override */
+ constructor(categoryDef, toolbox, opt_parent) {
+ super(categoryDef, toolbox, opt_parent);
+ }
+ /** @override */
+ addColourBorder_(colour) {
+ this.rowDiv_.style.backgroundColor = colour;
+ }
+ /** @override */
+ setSelected(isSelected) {
+ // We do not store the label span on the category, so use getElementsByClassName.
+ var labelDom = this.rowDiv_.getElementsByClassName('blocklyTreeLabel')[0];
+ if (isSelected) {
+ // Change the background color of the div to white.
+ this.rowDiv_.style.backgroundColor = 'white';
+ // Set the colour of the text to the colour of the category.
+ labelDom.style.color = this.colour_;
+ this.iconDom_.style.color = this.colour_;
+ } else {
+ // Set the background back to the original colour.
+ this.rowDiv_.style.backgroundColor = this.colour_;
+ // Set the text back to white.
+ labelDom.style.color = 'white';
+ this.iconDom_.style.color = 'white';
}
+ // This is used for accessibility purposes.
+ Blockly.utils.aria.setState(/** @type {!Element} */(this.htmlDiv_),
+ Blockly.utils.aria.State.SELECTED, isSelected);
+ }
}
Blockly.registry.register(
- Blockly.registry.Type.TOOLBOX_ITEM,
- Blockly.ToolboxCategory.registrationName,
- CustomCategory, true);
+ Blockly.registry.Type.TOOLBOX_ITEM,
+ Blockly.ToolboxCategory.registrationName,
+ CustomCategory, true);
//============ User Customize End ===============
-//背景canvasの準備
+//背景canvasとマスコットの準備
const ugj_canvasBgImg = (imgSrc, x, y) => { //x,y == -1: center or middle
- let el = document.getElementById('canvas_bg');
- let ctx = el.getContext('2d');
- ctx.fillStyle = 'rgb(255,255,255)';
- ctx.fillRect(0,0,480,360);
- let img = new Image();
- img.src = imgSrc;
- img.onload = () => {
- if (x<0) { //センタリング
- let w = img.width;
- if (w>=480) x=0;
- else x = Math.floor((480 - w) / 2);
- }
- if (y<0) { //縦中寄せ
- let h = img.height;
- if (h>=360) y=0;
- else y = Math.floor((360 - h) /2);
- }
- ctx.drawImage(img, x, y);
+ let el = document.getElementById('canvas_bg');
+ let ctx = el.getContext('2d');
+ ctx.fillStyle = 'rgb(255,255,255)';
+ ctx.fillRect(0, 0, 480, 360);
+ let img = new Image();
+ img.src = imgSrc;
+ img.onload = () => {
+ if (x < 0) { //センタリング
+ let w = img.width;
+ if (w >= 480) x = 0;
+ else x = Math.floor((480 - w) / 2);
}
+ if (y < 0) { //縦中寄せ
+ let h = img.height;
+ if (h >= 360) y = 0;
+ else y = Math.floor((360 - h) / 2);
+ }
+ ctx.drawImage(img, x, y);
+ }
};
-// マスコット
-// ugj_canvasBgImg("./img/mimmy.png?" + new Date().getTime()); // ミミィ
-// ugj_canvasBgImg("./img/cogechee.png?" + new Date().getTime(), -1,-1); // こげちー
// HTML部品のインスタンス - 画面上の必要な部品はすべてここで取得しておく
ugjel_displayArea = document.getElementById('display_area'); // ディスプレイ部
@@ -145,181 +144,183 @@ ugjel_inputBox = document.getElementById('inputBox'); // 入力フィールド
// その他のプロパティ
ugj_inputEvLstnrID = 0; // 入力フォームの動的イベントリスナの最新のID
ugj_sounds = (names => { // サウンドファイルのいろいろの配列の初期化
- let sounds = [];
- names.forEach(value => {
- let filepath = `./sounds/${value}.wav`;
- sounds[value] = { 'file': filepath, 'audio': new Audio(filepath) };
- });
- return sounds;
+ let sounds = [];
+ names.forEach(value => {
+ let filepath = `./sounds/${value}.wav`;
+ sounds[value] = { 'file': filepath, 'audio': new Audio(filepath) };
+ });
+ return sounds;
})(['meow', 'bounce', 'type_chime', 'type_dink', 'type_tap', 'type_space', 'type_return']); // サウンドファイルのベース名のリスト
// メソッド
// マスコット選択
const ugj_selectMascot = () => {
- let fname = elec.selectMascotFile();
- if (fname) {
- ugj_canvasBgImg(fname, -1, -1);
- elec.setMascotFilePath(fname);
- }
+ let fname = elec.selectMascotFile();
+ if (fname) {
+ ugj_canvasBgImg(fname, -1, -1);
+ elec.setMascotFilePath(fname);
+ }
}
// サウンド再生 - 連続再生のため、再生開始後すぐにオーディオ要素を再生成する
const ugj_soundPlay = soundName => {
- ugj_sounds[soundName]['audio'].play();
- ugj_sounds[soundName]['audio'] = new Audio(ugj_sounds[soundName]['file']);
+ ugj_sounds[soundName]['audio'].play();
+ ugj_sounds[soundName]['audio'] = new Audio(ugj_sounds[soundName]['file']);
};
// OK,Cancel 2択のダイアログを表示
const ugj_confirm = (title, message, callback) => {
- CustomDialog.show(title, message, {
- showOkay: true,
- onOkay: () => callback(true),
- showCancel: true,
- onCancel: () => callback(false)
- });
+ CustomDialog.show(title, message, {
+ showOkay: true,
+ onOkay: () => callback(true),
+ showCancel: true,
+ onCancel: () => callback(false)
+ });
};
const ugj_htmlEntities = str =>// HTMLエンティティのエスケープ
- String(str).replace(//g, '>').replace(/"/g, '"');//.replace(/&/g, '&').replace(/ /g, ' ');
+ String(str).replace(//g, '>').replace(/"/g, '"');//.replace(/&/g, '&').replace(/ /g, ' ');
// 新規ワークスペース
const ugj_newWorkspace = () => {
- ugj_confirm('新規ワークスペース', '保存していない内容はすべて破棄されます。よろしいですか?', okey => {
- if (okey) {
- workspace.clear();
- elec.newFile();
- }
- });
+ ugj_confirm('新規ワークスペース', '保存していない内容はすべて破棄されます。よろしいですか?', okey => {
+ if (okey) {
+ workspace.clear();
+ elec.newFile();
+ }
+ });
}
// ワークスペースをファイルに保存・読込
const ugj_saveWorkspaceToFile = () => {
- let xml = Blockly.Xml.workspaceToDom(workspace);
- let xml_text = Blockly.Xml.domToText(xml);
- if (elec.saveWsFile(xml_text) === false) {
- alert('保存できませんでした。');
- }
+ let xml = Blockly.Xml.workspaceToDom(workspace);
+ let xml_text = Blockly.Xml.domToText(xml);
+ if (elec.saveWsFile(xml_text) === false) {
+ alert('保存できませんでした。');
+ }
}
const ugj_loadWorkspaceFromFile = () => {
- let xml_text = elec.loadWsFile();
- if (xml_text.length > 0) {
- let xml = Blockly.Xml.textToDom(xml_text);
- Blockly.Xml.domToWorkspace(xml, workspace);
- }
+ let xml_text = elec.loadWsFile();
+ if (xml_text.length > 0) {
+ let xml = Blockly.Xml.textToDom(xml_text);
+ Blockly.Xml.domToWorkspace(xml, workspace);
+ }
}
// ワークスペースを別名で保存
const ugj_saveWorkspaceAs = () => {
- elec.newFile();
- ugj_saveWorkspaceToFile();
+ elec.newFile();
+ ugj_saveWorkspaceToFile();
}
// ワークスペースをローカルストレージに保存・読込
const ugj_saveWorkspace = () => {
- // Workspace
- let xml = Blockly.Xml.workspaceToDom(workspace);
- let xml_text = Blockly.Xml.domToText(xml);
- localStorage.setItem("abrage.xml", xml_text);
+ // Workspace
+ let xml = Blockly.Xml.workspaceToDom(workspace);
+ let xml_text = Blockly.Xml.domToText(xml);
+ localStorage.setItem("ocoge.xml", xml_text);
}
const ugj_loadWorkspace = () => {
- // Workspace
- let xml_text = localStorage.getItem("abrage.xml");
+ // Workspace
+ let xml_text = localStorage.getItem("ocoge.xml");
+ if (xml_text !== null) {
if (xml_text.length != 0) {
- let xml = Blockly.Xml.textToDom(xml_text);
- Blockly.Xml.domToWorkspace(xml, workspace);
+ let xml = Blockly.Xml.textToDom(xml_text);
+ Blockly.Xml.domToWorkspace(xml, workspace);
}
+ }
}
// ワークスペースからコードを生成して必要であれば整形処理をする
const ugj_createCode = (args) => {
- addAsync = args.async || false;
- beautify = args.beautify || false;
+ addAsync = args.async || false;
+ beautify = args.beautify || false;
- let code = Blockly.JavaScript.workspaceToCode(workspace);
+ let code = Blockly.JavaScript.workspaceToCode(workspace);
- // 追加モジュールのrequire
- let requires = [
- ['_gpio_', false, `const pi = require('ocoge_pigpiod');\n`],
- ['_axios_', false, `const axios = require('axios');\n`],
- ['_sendmail', false, `const nodemailer = require('nodemailer');\n`],
- ['_cloudspeech_', false, `const speech = require('@google-cloud/speech');\nconst recorder = require('node-record-lpcm16');\n`],
- ['_httpserver', false, `const http = require('http');\n`],
- ['_file_', false, `const fs = require('fs');\n`],
- // ['_bme280', false, `const BME280 = require('bme280-sensor');`],
- ['_dht', false, `const dht = require("node-dht-sensor").promises;`],
- ['_socket_', false, `const net = require('net');`]
- ];
- let blockArray = workspace.getAllBlocks();
- blockArray.forEach(value => {
- for (var i = 0, l = requires.length; i < l; i++) {
- if (value.type.indexOf(requires[i][0]) >= 0) requires[i][1] = true;
- }
- });
+ // 追加モジュールのrequire
+ let requires = [
+ ['_gpio_', false, `const pi = require('ocoge_pigpiod');\n`],
+ ['_axios_', false, `const axios = require('axios');\n`],
+ ['_sendmail', false, `const nodemailer = require('nodemailer');\n`],
+ ['_cloudspeech_', false, `const speech = require('@google-cloud/speech');\nconst recorder = require('node-record-lpcm16');\n`],
+ ['_httpserver', false, `const http = require('http');\n`],
+ ['_file_', false, `const fs = require('fs');\n`],
+ // ['_bme280', false, `const BME280 = require('bme280-sensor');`],
+ ['_dht', false, `const dht = require("node-dht-sensor").promises;`],
+ ['_socket_', false, `const net = require('net');`]
+ ];
+ let blockArray = workspace.getAllBlocks();
+ blockArray.forEach(value => {
for (var i = 0, l = requires.length; i < l; i++) {
- if (requires[i][1]) code = requires[i][2] + code;
+ if (value.type.indexOf(requires[i][0]) >= 0) requires[i][1] = true;
}
+ });
+ for (var i = 0, l = requires.length; i < l; i++) {
+ if (requires[i][1]) code = requires[i][2] + code;
+ }
- // await使用のため、必要に応じてコード全体をasync付き即時関数でラップ
- if (addAsync) {
- code = [
- '(async () => {',
- code,
- '})();'
- ].join('\n');
- }
+ // await使用のため、必要に応じてコード全体をasync付き即時関数でラップ
+ if (addAsync) {
+ code = [
+ '(async () => {',
+ code,
+ '})();'
+ ].join('\n');
+ }
- // コードを綺麗に
- if (beautify) code = js_beautify(code, { indent_size: 2 });
+ // コードを綺麗に
+ if (beautify) code = js_beautify(code, { indent_size: 2 });
- return code;
+ return code;
}
// ブロックスクリプト実行
const ugj_runCode = () => {
- document.activeElement.blur(); //実行ボタンからフォーカスを外す:エンターキー押下が悪さをするため
- let code = ugj_createCode({ 'async': true });
- try {
- eval(code);
- } catch (e) {
- alert(e);
- }
+ document.activeElement.blur(); //実行ボタンからフォーカスを外す:エンターキー押下が悪さをするため
+ let code = ugj_createCode({ 'async': true });
+ try {
+ eval(code);
+ } catch (e) {
+ alert(e);
+ }
}
// JavaScriptコードをダイアログで表示・保存
// エレメントのオブジェクトとかコールバックとか
// 色々この中で完結させてみる
const ugj_showCode = () => {
- const dialog = document.getElementById('codeDlg');
- const content = document.getElementById('dlgContent');
- const btn_close = document.getElementById('dlgClose');
- const btn_export = document.getElementById('dlgExport');
- const chkbox_cli = document.getElementById('dlgCli');
+ const dialog = document.getElementById('codeDlg');
+ const content = document.getElementById('dlgContent');
+ const btn_close = document.getElementById('dlgClose');
+ const btn_export = document.getElementById('dlgExport');
+ const chkbox_cli = document.getElementById('dlgCli');
- let code = ugj_createCode({ 'beautify': true });
- code = ugj_htmlEntities(code);
- content.innerHTML = PR.prettyPrintOne(code, 'js', true);
+ let code = ugj_createCode({ 'beautify': true });
+ code = ugj_htmlEntities(code);
+ content.innerHTML = PR.prettyPrintOne(code, 'js', true);
- dialog.showModal();
+ dialog.showModal();
- const close_cb = () => {
- dialog.close();
- btn_close.removeEventListener('click', close_cb);
- btn_export.removeEventListener('click', export_cb);
+ const close_cb = () => {
+ dialog.close();
+ btn_close.removeEventListener('click', close_cb);
+ btn_export.removeEventListener('click', export_cb);
+ }
+ const export_cb = () => {
+ code = ugj_createCode({ 'async': true, 'beautify': true });
+ // blackboardWrite()をconsole.log()に書き換え、
+ // document... と ugj_... と elec... をコメントアウト(ブラウザ関連部分の追放という意味では不完全なので注意)
+ if (chkbox_cli.checked)
+ code = code.replace(/const appendDiv[^#]*\/\/#/gm, 'const blackboardWrite = text => console.log(text);').replace(/(^(?=.*document.)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*ugj_)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*elec.)[^;]*;)/gm, '/* $1 */');
+ if (elec.saveFile(code, 'js') === false) {
+ alert('保存できませんでした。');
}
- const export_cb = () => {
- code = ugj_createCode({ 'async': true, 'beautify': true });
- // blackboardWrite()をconsole.log()に書き換え、
- // document... と ugj_... と elec... をコメントアウト(ブラウザ関連部分の追放という意味では不完全なので注意)
- if (chkbox_cli.checked)
- code = code.replace(/const appendDiv[^#]*\/\/#/gm, 'const blackboardWrite = text => console.log(text);').replace(/(^(?=.*document.)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*ugj_)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*elec.)[^;]*;)/gm, '/* $1 */');
- if (elec.saveFile(code, 'js') === false) {
- alert('保存できませんでした。');
- }
- close_cb();
- }
- btn_close.addEventListener('click', close_cb);
- btn_export.addEventListener('click', export_cb);
+ close_cb();
+ }
+ btn_close.addEventListener('click', close_cb);
+ btn_export.addEventListener('click', export_cb);
}
@@ -327,102 +328,102 @@ const ugj_showCode = () => {
ugj_fdTimeoutID = null;
ugj_fdRecentBox = null;
const ugj_fukidashi = (text, sec) => {
- // Canvas Context
- const context = document.getElementById('canvas').getContext('2d');
- // 吹き出しを消去する関数
- const clearFd = (x, y, w, h) => context.clearRect(x, y, w, h);
- // 前回の思い出を忘れる
- if (ugj_fdRecentBox !== null) {
- clearFd(ugj_fdRecentBox.x, ugj_fdRecentBox.y, ugj_fdRecentBox.w, ugj_fdRecentBox.h);
- clearTimeout(ugj_fdTimeoutID);
- ugj_fdRecentBox = null;
- }
+ // Canvas Context
+ const context = document.getElementById('canvas').getContext('2d');
+ // 吹き出しを消去する関数
+ const clearFd = (x, y, w, h) => context.clearRect(x, y, w, h);
+ // 前回の思い出を忘れる
+ if (ugj_fdRecentBox !== null) {
+ clearFd(ugj_fdRecentBox.x, ugj_fdRecentBox.y, ugj_fdRecentBox.w, ugj_fdRecentBox.h);
+ clearTimeout(ugj_fdTimeoutID);
+ ugj_fdRecentBox = null;
+ }
- // 基本設定
- let rtopX = 170; // フキダシ右上 X座標
- let rtopY = 40; // フキダシ右上 Y座標
- let boxWidth = 140;
- let padding = 5;
- let radius = 5;// 円弧の半径
+ // 基本設定
+ let rtopX = 170; // フキダシ右上 X座標
+ let rtopY = 40; // フキダシ右上 Y座標
+ let boxWidth = 140;
+ let padding = 5;
+ let radius = 5;// 円弧の半径
- // 吹き出しの背景色
- context.fillStyle = "#b7e6ff";
+ // 吹き出しの背景色
+ context.fillStyle = "#b7e6ff";
- // テキスト設定
- let limitedWidth = boxWidth - (padding * 2);
- let size = 14;
- context.font = size + "px ''";
+ // テキスト設定
+ let limitedWidth = boxWidth - (padding * 2);
+ let size = 14;
+ context.font = size + "px ''";
- // テキスト調整 行に分解
- let lineTextList = text.split("\n");
- let newLineTextList = [];
- lineTextList.forEach((lineText) => {
+ // テキスト調整 行に分解
+ let lineTextList = text.split("\n");
+ let newLineTextList = [];
+ lineTextList.forEach((lineText) => {
+ if (context.measureText(lineText).width > limitedWidth) {
+ characterList = lineText.split("");// 1文字ずつ分割
+ let preLineText = "";
+ lineText = "";
+ characterList.forEach((character) => {
+ lineText += character;
if (context.measureText(lineText).width > limitedWidth) {
- characterList = lineText.split("");// 1文字ずつ分割
- let preLineText = "";
- lineText = "";
- characterList.forEach((character) => {
- lineText += character;
- if (context.measureText(lineText).width > limitedWidth) {
- newLineTextList.push(preLineText);
- lineText = character;
- }
- preLineText = lineText;
- });
+ newLineTextList.push(preLineText);
+ lineText = character;
}
- newLineTextList.push(lineText);
- });
- let lineLength = newLineTextList.length;
-
- // 角丸
- let width = boxWidth;// 枠の幅
- let height = (size * lineLength) + (padding * 3); // 枠の高さ
- let toRadianCoefficient = Math.PI / 180; // 角度からラジアンへの変換係数
- // 角丸原点(左上座標)
- let boxOrigin = {
- "x": rtopX - width,
- "y": rtopY,
+ preLineText = lineText;
+ });
}
- // 円弧から円弧までの直線は自動で引かれます、角度は回り方によって変わります。
- // arc(中心x, 中心y, 半径, 開始角度, 終了角度, 反時計回り)
- context.beginPath();
- context.arc(boxOrigin.x + radius, boxOrigin.y + radius, radius, 180 * toRadianCoefficient, 270 * toRadianCoefficient, false);// 左上
- context.arc(boxOrigin.x + width - radius, boxOrigin.y + radius, radius, 270 * toRadianCoefficient, 0, false);// 右上
- context.arc(boxOrigin.x + width - radius, boxOrigin.y + height - radius, radius, 0, 90 * toRadianCoefficient, false);// 右下
- context.arc(boxOrigin.x + radius, boxOrigin.y + height - radius, radius, 90 * toRadianCoefficient, 180 * toRadianCoefficient, false);// 左下
- context.closePath();
- context.fill();
+ newLineTextList.push(lineText);
+ });
+ let lineLength = newLineTextList.length;
- // 矢印(ヒゲ)
- let arrow = {
- "x": rtopX - width / 2 + 40,
- "y": rtopY + height + 10,
- "width": 10,
- "height": 10,
- }
- context.beginPath();
- context.moveTo(arrow.x, arrow.y);
- context.lineTo(arrow.x, arrow.y - arrow.height);
- context.lineTo(arrow.x - arrow.width, arrow.y - arrow.height);
- context.fill();
+ // 角丸
+ let width = boxWidth;// 枠の幅
+ let height = (size * lineLength) + (padding * 3); // 枠の高さ
+ let toRadianCoefficient = Math.PI / 180; // 角度からラジアンへの変換係数
+ // 角丸原点(左上座標)
+ let boxOrigin = {
+ "x": rtopX - width,
+ "y": rtopY,
+ }
+ // 円弧から円弧までの直線は自動で引かれます、角度は回り方によって変わります。
+ // arc(中心x, 中心y, 半径, 開始角度, 終了角度, 反時計回り)
+ context.beginPath();
+ context.arc(boxOrigin.x + radius, boxOrigin.y + radius, radius, 180 * toRadianCoefficient, 270 * toRadianCoefficient, false);// 左上
+ context.arc(boxOrigin.x + width - radius, boxOrigin.y + radius, radius, 270 * toRadianCoefficient, 0, false);// 右上
+ context.arc(boxOrigin.x + width - radius, boxOrigin.y + height - radius, radius, 0, 90 * toRadianCoefficient, false);// 右下
+ context.arc(boxOrigin.x + radius, boxOrigin.y + height - radius, radius, 90 * toRadianCoefficient, 180 * toRadianCoefficient, false);// 左下
+ context.closePath();
+ context.fill();
- // テキスト描画
- context.fillStyle = "#000000";
- newLineTextList.forEach((lineText, index) => {
- context.fillText(lineText, boxOrigin.x + padding, boxOrigin.y + padding + (size * (index + 1)));
- });
+ // 矢印(ヒゲ)
+ let arrow = {
+ "x": rtopX - width / 2 + 40,
+ "y": rtopY + height + 10,
+ "width": 10,
+ "height": 10,
+ }
+ context.beginPath();
+ context.moveTo(arrow.x, arrow.y);
+ context.lineTo(arrow.x, arrow.y - arrow.height);
+ context.lineTo(arrow.x - arrow.width, arrow.y - arrow.height);
+ context.fill();
- // 描画した吹き出しの位置情報を保存
- ugj_fdRecentBox = { x: boxOrigin.x, y: boxOrigin.y, w: width, h: height + arrow.height };
- // 指定時間後に消去(0以下で自動消去なし)
- if (sec > 0) {
- ugj_fdTimeoutID = setTimeout(() => {
- clearFd(boxOrigin.x, boxOrigin.y, width, height + arrow.height);
- }, sec * 1000);
- }
+ // テキスト描画
+ context.fillStyle = "#000000";
+ newLineTextList.forEach((lineText, index) => {
+ context.fillText(lineText, boxOrigin.x + padding, boxOrigin.y + padding + (size * (index + 1)));
+ });
- // return [boxOrigin.x, boxOrigin.y, width, height+arrow.height];
- // https://qiita.com/horikeso/items/95595f379a8dfa63c34a
+ // 描画した吹き出しの位置情報を保存
+ ugj_fdRecentBox = { x: boxOrigin.x, y: boxOrigin.y, w: width, h: height + arrow.height };
+ // 指定時間後に消去(0以下で自動消去なし)
+ if (sec > 0) {
+ ugj_fdTimeoutID = setTimeout(() => {
+ clearFd(boxOrigin.x, boxOrigin.y, width, height + arrow.height);
+ }, sec * 1000);
+ }
+
+ // return [boxOrigin.x, boxOrigin.y, width, height+arrow.height];
+ // https://qiita.com/horikeso/items/95595f379a8dfa63c34a
}
//=====================================
@@ -435,37 +436,37 @@ var blocklyDiv = document.getElementById('blocklyDiv');
// var workspace = Blockly.inject(blocklyDiv,
// {toolbox: document.getElementById('toolbox')});
var workspace = Blockly.inject(blocklyDiv,
- {
- toolbox: document.getElementById('toolbox'),
- theme: theme,
+ {
+ toolbox: document.getElementById('toolbox'),
+ theme: theme,
- scrollbars: true,
- grid: {
- spacing: 20,
- length: 1,
- colour: '#888',//888
- snap: true
- },
- zoom: { startScale: 1.0, controls: true },
- trashcan: true,
- media: './google-blockly/media/'
- });
+ scrollbars: true,
+ grid: {
+ spacing: 20,
+ length: 1,
+ colour: '#888',//888
+ snap: true
+ },
+ zoom: { startScale: 1.0, controls: true },
+ trashcan: true,
+ media: './google-blockly/media/'
+ });
var onresize = function (e) {
- // Compute the absolute coordinates and dimensions of blocklyArea.
- var element = blocklyArea;
- var x = 0;
- var y = 0;
- do {
- x += element.offsetLeft;
- y += element.offsetTop;
- element = element.offsetParent;
- } while (element);
- // Position blocklyDiv over blocklyArea.
- blocklyDiv.style.left = x + 'px';
- blocklyDiv.style.top = y + 'px';
- blocklyDiv.style.width = blocklyArea.offsetWidth + 'px';
- blocklyDiv.style.height = blocklyArea.offsetHeight + 'px';
- Blockly.svgResize(workspace);
+ // Compute the absolute coordinates and dimensions of blocklyArea.
+ var element = blocklyArea;
+ var x = 0;
+ var y = 0;
+ do {
+ x += element.offsetLeft;
+ y += element.offsetTop;
+ element = element.offsetParent;
+ } while (element);
+ // Position blocklyDiv over blocklyArea.
+ blocklyDiv.style.left = x + 'px';
+ blocklyDiv.style.top = y + 'px';
+ blocklyDiv.style.width = blocklyArea.offsetWidth + 'px';
+ blocklyDiv.style.height = blocklyArea.offsetHeight + 'px';
+ Blockly.svgResize(workspace);
};
window.addEventListener('resize', onresize, false);
onresize();
@@ -476,95 +477,95 @@ Blockly.svgResize(workspace);
// ワークスペースの未保存の変更のフラグ
const ugj_wsUpdateCB = event => {
- if (event.type != Blockly.Events.UI) {
- elec.setWsChanged(true);
- }
+ if (event.type != Blockly.Events.UI) {
+ elec.setWsChanged(true);
+ }
}
// ウィンドウロード・アンロード時
window.onload = () => {
- var menu = document.getElementById('conmenu'); //独自コンテキストメニュー
- var area = document.getElementById('dlgContent'); //対象エリア
- var body = document.body; //bodyエリア
- body.oncontextmenu = () => false;
- //右クリック時に独自コンテキストメニューを表示する
- area.addEventListener('contextmenu', function (e) {
- menu.style.left = e.pageX + 'px';
- menu.style.top = e.pageY + 'px';
- menu.classList.add('on');
- });
- //左クリック時に独自コンテキストメニューを非表示にする
- body.addEventListener('click', function () {
- if (menu.classList.contains('on')) {
- menu.classList.remove('on');
- }
- });
+ var menu = document.getElementById('conmenu'); //独自コンテキストメニュー
+ var area = document.getElementById('dlgContent'); //対象エリア
+ var body = document.body; //bodyエリア
+ body.oncontextmenu = () => false;
+ //右クリック時に独自コンテキストメニューを表示する
+ area.addEventListener('contextmenu', function (e) {
+ menu.style.left = e.pageX + 'px';
+ menu.style.top = e.pageY + 'px';
+ menu.classList.add('on');
+ });
+ //左クリック時に独自コンテキストメニューを非表示にする
+ body.addEventListener('click', function () {
+ if (menu.classList.contains('on')) {
+ menu.classList.remove('on');
+ }
+ });
- // ワークスペースといくつかの環境のオートリストア
- ugj_loadWorkspace();
- elec.loadPrefsFromLS();
- setTimeout(() => { // 環境設定のロードが終わってからイベントリスナを作成
- workspace.addChangeListener(ugj_wsUpdateCB);
- }, 100);
- // 背景canvas
- ugj_canvasBgImg(elec.getMascotFilePath(), -1,-1);
+ // ワークスペースといくつかの環境のオートリストア
+ ugj_loadWorkspace();
+ elec.loadPrefsFromLS();
+ setTimeout(() => { // 環境設定のロードが終わってからイベントリスナを作成
+ workspace.addChangeListener(ugj_wsUpdateCB);
+ }, 100);
+ // 背景canvas
+ ugj_canvasBgImg(elec.getMascotFilePath(), -1, -1);
}
window.onbeforeunload = () => {
- ugj_saveWorkspace();
- elec.savePrefsToLS();
+ ugj_saveWorkspace();
+ elec.savePrefsToLS();
}
// Electron動作とブラウザ動作を自動で仕分け
if (typeof require == 'function') {
- // requireが使える = Electron
- var elec = require('./scripts/eleclib');
- console.log('elec loaded.');
+ // requireが使える = Electron
+ var elec = require('./scripts/eleclib');
+ console.log('elec loaded.');
} else {
- //ブラウザ動作
- //requireのダミー
- var require = (e) => {
- alert(`この機能またはブロック [${e}] は web 版ではご利用になれません。\n詳しくはお問い合わせください。`);
- // if (e=='elec' || e=='ocoge' || e=='child_process' || e=='@google-cloud/speech' || e=='nodemailer' || e=='fs' )
- // alert(`この機能またはブロックは web 版ではご利用になれません。\n詳しくはお問い合わせください。`);
- // else return;
- }
- //elecを名前空間で置き換え
- var elec = {};
- elec.saveFile = () => require('elec');
- elec.savePrefsToLS = () => { ; }
- elec.loadPrefsFromLS = () => { ; }
- elec.newFile = () => { ; }
- elec.setWsChanged = () => { ; }
+ //ブラウザ動作
+ //requireのダミー
+ var require = (e) => {
+ alert(`この機能またはブロック [${e}] は web 版ではご利用になれません。\n詳しくはお問い合わせください。`);
+ // if (e=='elec' || e=='ocoge' || e=='child_process' || e=='@google-cloud/speech' || e=='nodemailer' || e=='fs' )
+ // alert(`この機能またはブロックは web 版ではご利用になれません。\n詳しくはお問い合わせください。`);
+ // else return;
+ }
+ //elecを名前空間で置き換え
+ var elec = {};
+ elec.saveFile = () => require('elec');
+ elec.savePrefsToLS = () => { ; }
+ elec.loadPrefsFromLS = () => { ; }
+ elec.newFile = () => { ; }
+ elec.setWsChanged = () => { ; }
- // マスコット
- elec.getMascotFilePath = () => './img/cogechee.png';
+ // マスコット
+ elec.getMascotFilePath = () => './img/cogechee.png';
- //ワークスペースのダウンロード
- elec.saveWsFile = xml_text => {
- let blob = new Blob([xml_text], { "type": "text/xml" });
- const downLoadLink = document.createElement("a");
- document.body.appendChild(downLoadLink);
- downLoadLink.download = 'workspace.xml';
- downLoadLink.href = URL.createObjectURL(blob);
- downLoadLink.click();
- downLoadLink.parentElement.removeChild(downLoadLink);
- return true;
- }
- //ワークスペースのインポート
- elec.loadWsFile = () => {
- const fileInputEl = document.createElement('input');
- document.body.appendChild(fileInputEl);
- fileInputEl.type = 'file';
- fileInputEl.addEventListener('change', ev => {
- let reader = new FileReader();
- reader.readAsText(ev.target.files[0]);
- reader.addEventListener('load', () => {
- let xml = Blockly.Xml.textToDom(reader.result);
- Blockly.Xml.domToWorkspace(xml, workspace);
- });
- });
- fileInputEl.click();
- fileInputEl.parentElement.removeChild(fileInputEl);
- return '';
- }
+ //ワークスペースのダウンロード
+ elec.saveWsFile = xml_text => {
+ let blob = new Blob([xml_text], { "type": "text/xml" });
+ const downLoadLink = document.createElement("a");
+ document.body.appendChild(downLoadLink);
+ downLoadLink.download = 'workspace.xml';
+ downLoadLink.href = URL.createObjectURL(blob);
+ downLoadLink.click();
+ downLoadLink.parentElement.removeChild(downLoadLink);
+ return true;
+ }
+ //ワークスペースのインポート
+ elec.loadWsFile = () => {
+ const fileInputEl = document.createElement('input');
+ document.body.appendChild(fileInputEl);
+ fileInputEl.type = 'file';
+ fileInputEl.addEventListener('change', ev => {
+ let reader = new FileReader();
+ reader.readAsText(ev.target.files[0]);
+ reader.addEventListener('load', () => {
+ let xml = Blockly.Xml.textToDom(reader.result);
+ Blockly.Xml.domToWorkspace(xml, workspace);
+ });
+ });
+ fileInputEl.click();
+ fileInputEl.parentElement.removeChild(fileInputEl);
+ return '';
+ }
}
\ No newline at end of file