Duplicate Procedures

8 views
Skip to first unread message

Francisco

unread,
5:53 AM (7 hours ago) 5:53 AM
to Blockly
Hi all,

I've been getting issues with implementing my custom ProcedureModel's and serialization. Because my model differs from the original ObservableProcedureModel:

export class ProcedureModel implements procedures.IProcedureModel {
  private readonly id: string
  private parameters: ParameterModel[] = []
  private returnTypes: ParameterType[] | null = null
  private enabled = true
  private shouldTriggerUpdates = true

  constructor(
    private readonly workspace: Workspace,
    id?: string
  ) {
    this.id = id ?? utils.idGenerator.genUid()
  }

...
}

Respectively, here's the ParameterModel:

export class ParameterModel implements procedures.IParameterModel {
  private readonly id: string
  private name: string
  private type: ProcedureInputType

  constructor(name: string, type: ProcedureInputType, id?: string) {
    this.id = id ?? utils.idGenerator.genUid()
    this.name = name
    this.type = type
  }
...
}

Note how the ProcedureModel.name was completely scrapped. It is no longer needed now that the block's parameters symbolyse the block itself, similar to how scratch does it with their "My Blocks". I think that approach is better for functions which should act more like your "own" blocks.

Here's the types used in the models:

export type ParameterType = 'text' | 'number' | 'bool'
export type ProcedureInputType = ParameterType | 'label'

export interface ParameterState
  extends serialization.procedures.ParameterState {
  types: ProcedureInputType[]
}

export interface ProcedureState extends serialization.procedures.State {
  parameters: ParameterState[]
  /** Should only hold one return type, but it's an array because blockly */
  returnTypes: ParameterType[] | null
}


The label in the ProcedureInputType is what signifies the block. I have already started to implement this in my ProcedureBlock's (call and definition blocks), Here's a demo:

Image

The Definition block looks similar, right now the way to create those procedures (I call them functions in my toolbox) is by using prompts. There will be a function popup window at some point though.

With all this context, and the point where I'm trying to get at, is that I noticed weird behaviour regarding saving the state and loading it back in, and how the blocks are added. Specifically, When adding the definition block manually after creating the model:

  procedureMap.add(model)

  const block = workspace.newBlock('function_def') as ProcedureBlock
  block.loadExtraState({ id: model.getId() })
  block.initSvg()
  block.render()
  workspace.addTopBlock(block)

The definition block appears once on the workspace as a block, but twice in the Workspace. (instance):

Image

When saving the workspace state, two definition blocks will be saved, and upon loading it back in, it complains about two blocks holding the same id.

That's not the only issue, generally loading and serializing my custom models seems to be broken. Can anyone help me out? I'd be happy to share the codebase, it has been a fun blockly project :D It's what motivated me to contribute to blockly myself, because it's a goated library 🐐

Thanks and have an awesome day

Heliacer

Maribeth Moffatt

unread,
11:19 AM (1 hour ago) 11:19 AM
to Blockly
You don't need to call `workspace.addTopBlock` as `workspace.newBlock` already creates the block as a top block on the workspace. That is likely causing your issue.

Instead of calling newBlock, loadExtraState, initSvg, and then render, you could just call Blockly.serialization.blocks.append, which will do all of that for you if you pass in the json representation of the block you want to load.

Best,
Maribeth

Reply all
Reply to author
Forward
0 new messages