I am trying to make a block that groups other blocks. In my case, these groups form a group of shapes on a 3D surface.
The repeat block shape is perfect for this. And with some difficulty, I managed to convert the forever block from the pxt-sample into the shape of a repeat block.
My question is I have no idea what to do with the body. I have run thread.runInBackground but I don’t think that is correct, because I need the statements to be added deterministically. This code works fine but when I add in a repeat loop it all goes to crazytown. What should I do to make sure that the code for cylinder and cube gets called?
export function subtractShapes(body: RefAction): void {
board().addBlock("difference( <CHILDREN> )"); // add a JSCad statement to the interpreter.
body()
}
Also, I should mention, generally it’s best to do APIs that take in non-primitives inside of libs/ instead of in the simulator. Then you don’t have to deal with internals directly like this. For example, you could have an API in the simulator like this:
//%
export function addBlock(block: string) {
board().addBlock(block)
}
and then define the public function in the libs folder like this:
Can I ask which file you would pop it into in /libs… does it matter? This bit seems to be missing from the documentation… I started from the pxt-sample project… so I am assuming it’s ns.ts cause that’s got Turtle stuff in it?
You can think of all the TypeScript code in libs as “user code”, the files in there don’t have any special importance; any TS file that is listed in pxt.json will be added to the user’s project as a dependency. If you look at the pxt.json inside of the blocksprj project, you’ll see it has a dependency on the “core” package that contains ns.ts.
In general, writing as much code as possible in libs is helpful because it makes the code more portable between editors. It also lets you use the MakeCode debugger with your code.
BTW, the name ns.ts is for “namespace” because that’s the file that defines the namespaces and their colors/names in the UI.
Hello, I’m trying to use the inner event blocks as a callback for a subscription from a websocket event. I’m storing the websocket connection as part of the simulator Board. The event block is defined in /libs/core/ns.ts below
/**
Subscribe to a topic
@param topic
@param response
@param body
*/
//% blockId=subscribeMessage block=“on $message as type: $type from topic: $topic”
//% draggableParameters
export function subscribeBlock(topic: string, type: MessageTypes, handler: (message: messages.RosMessage) => void){
subscribe(topic, type, handler);
}
It calls a function defined in /sim/api.ts:
/**
Subscribe to a topic
@param topic
@param response
@param body
*/
//%
export function subscribe(topic: string, type: MessageTypes, handler: (message: messages.RosMessage) => void){
const b = board()
function callback(msg: object){
const pxtMsg = messages.createMessage(type)
pxtMsg.data = msg
handler(pxtMsg)
}
console.log(callback.toString())
b.ros.subscribe(topic, type, callback)
}
However, when a message is received and the callback runs, I get the error.
pxtsim.js:1 Uncaught Error: sim error: undefined
at oops (pxtsim.js:1)
at inline__P201 (eval at Runtime (pxtsim.js:1), :116:12)
at callback (sim.js:339)
at Topic. (sim.js:294)
at Topic.EventEmitter.emit (roslib.js:762)
at Ros.Topic._messageCallback (roslib.js:3140)
at Ros.EventEmitter.emit (roslib.js:762)
at handleMessage (roslib.js:2969)
at handlePng (roslib.js:2987)
at WebSocket.onMessage (roslib.js:3054)
Would any of you have any idea how to use the function handler as a callback?
So… I am having a bit of trouble following your callstack… but perhaps there are more expert folks who can help with that.
The way I solved this in BuildBee was to use blocks like this
Which so happen to resolve in the JavaScript pane in a way you might want. The cube code is actually run inside of a callback.
operators.move(10, Axis.X, function () {
shapes.cube(10, 10, 10)
})
The downside to this is that while my technique works for javascript it seems to not work in python, which is why python is currently turned off in my pxt.
You’re welcome to look at the source code here:
What happens is that for moveAsync (which is what it’s called in operators.ts) the cube code is inside of the body (represented by the RefAction)
export function moveAsync(mm: number, direction: Axis, body: RefAction): Promise<void>
I so happen to make that body code run straight away, by calling runFiberAsync - but I imagine you could hold onto that body variable and call it later.
function _makeBlock(someData: string, body: RefAction) {
return new Promise<void>((resolve, reject) => {
board().doStuffToSimulator(someData)
// execute the child blocks
pxsim.runtime.runFiberAsync(body).then((result) => {
resolve(result)
}).catch((error) => {
reject(error)
})
})
}
Someone may have a waaaaay better idea but that’s just going off what I know. Good luck!
hello, thank you for your response. I’ve actually been going off your repo a ton and its been insanely helpful. I feel like the official docs are missing quite a bit of information. Anyways I managed to figure it out using the RefAction.
However, I was hoping that I could have local parameters defined in the callback function within the body of the block like so,
function myBlock(param1: string, handler: (localParam: number) => void){
//insert block code here
}
The makecode dev team response above said that it’s possible if I define the block function in ./libs/core, but I’m having difficulty trying to link up the block in ./libs/core with the ./sim functions.
After a mental breakdown trying to figure that out, I just gave up. Would you have any idea how to pull it off?
Yeah I have to admit I had significant trouble trying to do it “the right way” - it is on my list to go back and shuffle the code into the right spot. But I have to admit I am forcing myself to learn the bare minimum of typescript as I go along.
Perhaps if we work it out together we’ll both sort it? What did you try?
@khayliang - I just discovered a huge clue yesterday - the typescript in my project was waaaay out of date. I had forked my project from pxt-sample, which must be ageing.
I was adding a field editor to my project and it just kept throwing TS1005 errors pulling in type definitions. I upgraded my package.json from:
“typescript”: “2.6.1”
to
“typescript”: “3.7.5”