diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc index 990d02ce..5dfc2c0b 100644 --- a/.markdownlint.jsonc +++ b/.markdownlint.jsonc @@ -118,7 +118,7 @@ // MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content "MD024": { // Only check sibling headings - "allow_different_nesting": false, + "allow_different_nesting": true, // Only check sibling headings "siblings_only": false }, diff --git a/README.md b/README.md index 438f52cb..21ab14b1 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ A complete overhaul of [Music Blocks](https://github.com/sugarlabs/musicblocks). The aim of the new architecture is modularity and extensibility. The idea is to create a core visual programming platform, and extend it with other features. -- The source code for the components specific to the application wil reside in this +- The source code for the components specific to the application resides in this [**musicblocks-v4**](https://github.com/sugarlabs/musicblocks-v4/) repository. -- The source code for the programming framework will reside in the +- The source code for the programming framework resides in the [**musicblocks-v4-lib**](https://github.com/sugarlabs/musicblocks-v4-lib/) repository. - **musicblocks-v4-lib** is bundled as an _npm_ package and imported as a dependency in @@ -18,90 +18,61 @@ programming platform, and extend it with other features. ### Components -![Component Architecture](docs/images/architecture/components.jpg) +![Component Architecture](docs/images/architecture/components.png) -#### Core +**Note:** The greyed out components haven't been built yet. -3 core components: **Interface**, **Syntax**, **Integration** +This is a highly pluggable architecture — except for application level functionality, anything related +to project building and execution are features which shall be dynamically pluggable (they may or may +not be configured to load). -- **Interface** component shall contain the UI components. These are the ones which use _React_ and -follow _Model-View-ViewModel_ (_MVVM_) architecture. +Components can be strictly or partially dependent on other components. In case of strict dependency, +a depending component needs to be loaded for a dependent component to be loaded. In case of partial +dependency, a dependent component adds extra functionality to the depending component if it is loaded. - - **Menu** shall handle top level operations like running projects, managing projects, undo/redo, - application settings. +#### Programming Framework - - **Config** shall be used to configure the feature configurations. +This is reponsible for defining the _syntax constructs_ (_syntax elements_, _syntax tree_) and +utilities (_syntax specification_, _syntax warehouse_), and contains the _execution engine_ +(_scheduler_, _interpreter_, _parser_, _symbol table_) for running the program represented by the +_syntax tree_. See +[`musicblocks-v4-lib/README.md`](https://github.com/sugarlabs/musicblocks-v4-lib/blob/develop/README.md) +for details. - - **Status** shall display the application status. +The components in `musicblocks-v4` shall use the constructs exposed by `musicblocks-v4-lib`. - - **Info** shall display logs. +#### View Framework - - **Console** shall provide an interactive tool to run application level commands and - display messages (like a terminal). +This is responsible for creating the skeleton of the UI — components that have a view shall request +component wrappers from the _view framework_ and encapsule their DOM inside the wrappers. - - **Debugger** shall be used to debug Music Blocks programs by monitoring states. +#### Integration - - **Editor** shall be responsible to building Music Blocks programs in text form. +This is responsible for adding general application-wide functionalities like _internationalisation_, +_project management_, and _activity history_. - - **Planet** shall be a repository for openly shared projects. +#### Plugin - UI -- **Syntax** component shall contain the programming framework. These are responsible for internal -representation and execution of Music Blocks programs. This shall come with a factory set of program -building syntax elements. +This contains UI components for application-wide interactive/informative functionality. - - **Elements** shall describe the rudimentary syntax element constructs — **data**, **expressions**, - **statements**, and **blocks**. +#### Plugin - Art - - **Specification** shall describe the ambient configurations (label, selective connectivity, etc.) - for syntax elements. +This is responsible for artwork generation. It shall contain a set of _syntax elements_ of +instructions and arguments related to artwork generation and artboard (artwork canvas) states. - - **Warehouse** shall instantiate and maintain a table of syntax element instances. +#### Plugin - Music - - **Tree** shall respresent the syntax tree by maintaining the interconnections between syntax - elements. +This is responsible for music generation. It shall contain a set of _syntax elements_ of +instructions and arguments related to music generation, composition, and music states. - - **Symbol Table** shall maintain the set of program variables. +#### Plugin - Bricks - - **Parser** shall handle the sequential traversal of syntax elements. +This is responsible for building Music Blocks programs using graphical bricks (blocks). - - **Interpreter** shall orchestrate running Music Blocks programs — exeution of syntax elements. +#### Config -- **Integrations** component shall contain the components responsible for handling application -configurations and other bookkeeping. - - - **Config** shall handle application specific configurations and loading of configured plugins. - - - **i18n** shall handle internationalisation — managing language strings. - - - **Projects** shall handle for creating, loading, merging, and exporting projects. - - - **History** shall handle maintaining a log of application-level operations for rollback. - -In addition, a **Broker** component shall be responsible for inter-component communication. - -#### Plugins - -2 kinds of plugins: **Features** and **Syntax Builders** - -- **Features** add new functionality to the application. These may add interface components and new -set of syntax elements. - -- **Syntax Builders** add interfaces to build Music Blocks programs. - -Plugins may be extended themselves to add more optional functionalities. - -##### Plugin (Feature) - Painter - -This shall add artwork generating functionality, and a set of syntax elements to interact with them. - -##### Plugin (Feature) - Singer - -This shall add music generating functionality, and a set of syntax elements to interact with them. -This shall be extended to add widgets for generating syntax element stacks. - -##### Plugin (Syntax Builder) - Bricks - -This shall add the functionality to build Music Blocks programs using visual bricks. +This is responsible for conditionally loading the pluggable components dynamically and sharing instance +references between them. ### Wireframe diff --git a/docs/artboard.md b/docs/artboard.md deleted file mode 100644 index 715e6ff0..00000000 --- a/docs/artboard.md +++ /dev/null @@ -1,168 +0,0 @@ -## Artboard - -The artboard component is responsible for controllling all the graphics management. It creates turtles, canvases for each turtle, control the turtle(sprite) movements, communicate a particular turtle to draw on canvas. Any change to the background canvas can be done by manipulating this component. - -Artboard is composed of three components. -
    -
  1. Underlay
  2. -
  3. Manager
  4. -
  5. Interactor
  6. -
- -![Artboards](https://user-images.githubusercontent.com/45814442/123537788-df608e00-d74e-11eb-8702-7674b0db84a5.png) - -### Underlay -This refers to main canvas in the background which holds the palettes, menus and blocks. It will be present even if there are no turtles (sprite). - -### Interactor -It is the interaction point between the canvases and other components. - -#### Manager -This is the main sub component of artboard as it is responsible for handling all artboards.For e.g. it can add a new artboard(canvas), remove an existing artboard, renders a particular turtle to draw on artboard, etc. It receives signals from monitor component to do a change in a particular artboard. It maintains a list of artboards which are currently present in the program. Before knowing how it handles several artboards let us take a look at the overall design structure of artboard and turtle. - -#### Turtle and Artboard -There is a dedicated canvas for each turtle and all drawings corresponding to the its turtle reside in it. We can say there is one-to-one relationship between artboard and turtle. Artboard is designed based on MVVM (Model-View-ViewModel). The model of an artboard contains properties specific to its artboard like line parameters, arc parameters, etc. The ViewModel contains a reference to the corresponding DOM element. e.g. - canvas and turtle positions, style etc.The view component is basically a HTML canvas generated by p5 library and all the functions to draw line, arcs, clear, etc are written using p5 library. See the below figure for more clarity. - -![Artboard](https://user-images.githubusercontent.com/45814442/123538922-b3e0a200-d754-11eb-988e-df51620d5353.png) - -### File Structure - -All relevant folders and files of artboard are listed down - - - -## p5 Library and Artboard -[p5](https://p5js.org/) library is used to create and handle canvases. p5 provides many inbuilt functions to draw graphics and control over the canvas.p5.js has a number of predefined functions which we can use to draw anything we want. The most basic (and necessary) functions are the setup() and draw() functions. A simple canvas using p5 in react can be created like this. - -[`p5 Canvas is created in instance mode.`](https://github.com/processing/p5.js/wiki/Global-and-instance-mode) - - - const Sketch = (sketch: P5Instance): void => { - let demoCanvas: p5.Element; - - /** This is a setup function */ - sketch.setup = () => { - demoCanvas = sketch.createCanvas(1200, 600); - }; - - /** This is a draw function */ - sketch.draw = () => { - sketch.background(220); - sketch.ellipse(50, 50, 80, 80); - }; - }; - -It creates a canvas as p5 element with a circle on top of it. There are two important functions `setup` and `draw`. The code inside the `draw()` function runs continuously from top to bottom until the program is stopped. The setup function runs only once in the beginning. - -### Integration p5 Sketches with React - -By using React we get all the advantages of declarative code with clean, reusable and reactive components. All the while still maintaining the easy to use abstractions exposed by p5. The above sketch defintion is called inside a react component. - -### How Do We Add A Sketch In React? - -The sample sketch above is written in plain javascript and we can’t just write the same code in react. We have to add it using a few manipulations. - -Adding a sketch in react is fairly simple, we need to do three basic things: -
    -
  1. Create a function which encapsulates our sketch
  2. -
  3. Create a p5 object using the p5 package that we installed earlier
  4. -
  5. Pass our sketch to the p5 object as an argument
  6. -
-The canvas is wrapped inside a react component so that we can use some of the lifecycle to manipulate it accordingly. - - - const DemoSketch: React.FC = ({ sketch, children, ...props }) => { - - /** Sketch takes a P5Instance of canvas, props contains attributes like bg color, etc*/ - const demoSketch = createRef(); - const [instance, setInstance] = useState(); - const id = `demo-sketch`; - useEffect(() => { - instance?.updateWithProps?.(props); - }, [props]); - - useEffect(() => { - if (demoSketch.current === null) return; - instance?.remove(); - const canvas = new p5(Sketch, document.getElementById(id) as HTMLElement) as P5Instance; - canvas.updateWithProps?.(props); - setInstance(canvas); - }, [sketch, demoSketch.current]); - - return ( -
- {children} -
- ); - }; - -For more information on the integration of p5 sketches with react, please read this [post](https://levelup.gitconnected.com/integrating-p5-sketches-into-your-react-app-de44a8c74e91). - -## Artboard and react hooks - - sketch.updateWithProps = (props: SketchProps) => { - if (props.color) { - bgcolor = parseInt(props.color, 10); - } - }; - - useEffect(() => { - instance?.updateWithProps?.(props); - }, [props]); - - -We declare a reference variable called "demoSketch" using React's useRef hook. This just let's our other libraries have a node or reference insertion point. It's important that we pass "domSketch.current" into DOM because ".current" gives the actual HTML node we want. And finally, we return some jsx of a div that has the ref attribute equal to the value of our useRef hook variable. - -Similarly, useEffect hook is used to reflect the change on the canvas. In the above example we see the `updateWithProps()` function, which is called when the properties of a wrapper component are changed. Read more [here](https://github.com/jamesrweb/react-p5-wrapper). - -### Monitor and Manager - -### Manager and Artboard - -### Artboard and Turtles - - diff --git a/docs/images/architecture/components.jpg b/docs/images/architecture/components.jpg deleted file mode 100644 index 7151bb8c..00000000 Binary files a/docs/images/architecture/components.jpg and /dev/null differ diff --git a/docs/images/architecture/components.png b/docs/images/architecture/components.png new file mode 100644 index 00000000..ec8ba70a Binary files /dev/null and b/docs/images/architecture/components.png differ diff --git a/src/CHANGELOG.md b/src/CHANGELOG.md new file mode 100644 index 00000000..bff45acb --- /dev/null +++ b/src/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +## 4.0.0 [2022-02-13] + +- Sets up a _Node.js_ project for _React_ using `create-react-app`. +- Bundles the _Programming Framework_ ([musicblocks-v4-lib](https://github.com/sugarlabs/musicblocks-v4-lib)). +- Adds a basic _View Framework_ that creates a _workspace_ wrapper, and _toolbar_ buttons and wrappers. +- Adds the _Config_ component that creates a dependency tree of components and dynamically loads them. +- Adds the _Painter_ component with a single SVG _sprite_. +- Adds basic _Syntax Elements_ for _Painter_ instructions. +- Adds a basic _Editor_ to author programs using _Painter_ instructions. +- Displays the _Painter_ instructions API in the _Editor_. +- Adds a basic _Menu_ to run and reset programs authored in the _Editor_. +- Adds project documentation. +- Adds `lint` and `CD` workflows. diff --git a/src/archive/docs/artboard.md b/src/archive/docs/artboard.md new file mode 100644 index 00000000..42c701b7 --- /dev/null +++ b/src/archive/docs/artboard.md @@ -0,0 +1,178 @@ +# Artboard + +The artboard component is responsible for controllling all the graphics management. It creates turtles, +canvases for each turtle, control the turtle(sprite) movements, communicate a particular turtle to draw +on canvas. Any change to the background canvas can be done by manipulating this component. + +Artboard is composed of three components. + +1. Underlay +2. Manager +3. Interactor + +![Artboards](https://user-images.githubusercontent.com/45814442/123537788-df608e00-d74e-11eb-8702-7674b0db84a5.png) + +## Underlay + +This refers to main canvas in the background which holds the palettes, menus and blocks. It will be +present even if there are no turtles (sprite). + +## Interactor + +It is the interaction point between the canvases and other components. + +## Manager + +This is the main sub component of artboard as it is responsible for handling all artboards.For e.g. +it can add a new artboard(canvas), remove an existing artboard, renders a particular turtle to draw +on artboard, etc. It receives signals from monitor component to do a change in a particular artboard. +It maintains a list of artboards which are currently present in the program. Before knowing how it +handles several artboards let us take a look at the overall design structure of artboard and turtle. + +### Turtle and Artboard + +There is a dedicated canvas for each turtle and all drawings corresponding to the its turtle reside +in it. We can say there is one-to-one relationship between artboard and turtle. Artboard is designed +based on MVVM (Model-View-ViewModel). The model of an artboard contains properties specific to its +artboard like line parameters, arc parameters, etc. The ViewModel contains a reference to the +corresponding DOM element. e.g. - canvas and turtle positions, style etc.The view component is basically +a HTML canvas generated by p5 library and all the functions to draw line, arcs, clear, etc are written +using p5 library. See the below figure for more clarity. + +![Artboard](https://user-images.githubusercontent.com/45814442/123538922-b3e0a200-d754-11eb-988e-df51620d5353.png) + +## File Structure + +All relevant folders and files of artboard are listed down - + +- Types + - artboard.d.ts + - context.d.ts + +- Components + - artboard + - Artboard.tsx + - Manager.tsx + - Underlay.tsx + - Monitor.ts + +- Context + - ArtBoardContext.ts + +- Models + - artboard + - ArtBoardDraw.ts + - Artboard.ts + - ArtboardManager.ts + - Turtle.ts + +- Views + - artboard + - Artboard.scss + - Artboard.tsx + - ArtboardHandler.tsx + - ArtboardSketch.tsx + - ArtboardTurtle.tsx + +## p5 Library and Artboard + +[p5](https://p5js.org/) library is used to create and handle canvases. p5 provides many inbuilt +functions to draw graphics and control over the canvas.p5.js has a number of predefined functions +which we can use to draw anything we want. The most basic (and necessary) functions are the setup() +and draw() functions. A simple canvas using p5 in react can be created like this. + +[`p5 Canvas is created in instance mode.`](https://github.com/processing/p5.js/wiki/Global-and-instance-mode) + +```typescript +const Sketch = (sketch: P5Instance): void => { + let demoCanvas: p5.Element; + + /** This is a setup function */ + sketch.setup = () => { + demoCanvas = sketch.createCanvas(1200, 600); + }; + + /** This is a draw function */ + sketch.draw = () => { + sketch.background(220); + sketch.ellipse(50, 50, 80, 80); + }; +}; +``` + +It creates a canvas as p5 element with a circle on top of it. There are two important functions `setup` +and `draw`. The code inside the `draw()` function runs continuously from top to bottom until the +program is stopped. The setup function runs only once in the beginning. + +### Integration p5 Sketches with React + +By using React we get all the advantages of declarative code with clean, reusable and reactive +components. All the while still maintaining the easy to use abstractions exposed by p5. The above +sketch defintion is called inside a react component. + +### How Do We Add A Sketch In React? + +The sample sketch above is written in plain JavaScript and we can’t just write the same code in react. +We have to add it using a few manipulations. + +Adding a sketch in react is fairly simple, we need to do three basic things: + +1. Create a function which encapsulates our sketch +2. Create a p5 object using the p5 package that we installed earlier +3. Pass our sketch to the p5 object as an argument + +The canvas is wrapped inside a react component so that we can use some of the lifecycle to manipulate +it accordingly. + +```typescript +const DemoSketch: React.FC = ({ sketch, children, ...props }) => { + + /** Sketch takes a P5Instance of canvas, props contains attributes like bg color, etc*/ + const demoSketch = createRef(); + const [instance, setInstance] = useState(); + const id = `demo-sketch`; + useEffect(() => { + instance?.updateWithProps?.(props); + }, [props]); + + useEffect(() => { + if (demoSketch.current === null) return; + instance?.remove(); + const canvas = new p5(Sketch, document.getElementById(id) as HTMLElement) as P5Instance; + canvas.updateWithProps?.(props); + setInstance(canvas); + }, [sketch, demoSketch.current]); + + return ( +
+ {children} +
+ ); +}; +``` + +For more information on the integration of p5 sketches with react, please read this +[post](https://levelup.gitconnected.com/integrating-p5-sketches-into-your-react-app-de44a8c74e91). + +## Artboard and react hooks + +```typescript +sketch.updateWithProps = (props: SketchProps) => { + if (props.color) { + bgcolor = parseInt(props.color, 10); + } +}; + +useEffect(() => { + instance?.updateWithProps?.(props); +}, [props]); +``` + +We declare a reference variable called "demoSketch" using React's useRef hook. This just let's our +other libraries have a Node.js or reference insertion point. It's important that we pass +"domSketch.current" into DOM because ".current" gives the actual HTML Node.js we want. And finally, +we return some jsx of a div that has the ref attribute equal to the value of our useRef hook variable. + +Similarly, useEffect hook is used to reflect the change on the canvas. In the above example we see +the `updateWithProps()` function, which is called when the properties of a wrapper component are +changed. Read more [here](https://github.com/jamesrweb/react-p5-wrapper). diff --git a/docs/images/menu-documentation/menu-view-structure.png b/src/archive/docs/images/menu-documentation/menu-view-structure.png similarity index 100% rename from docs/images/menu-documentation/menu-view-structure.png rename to src/archive/docs/images/menu-documentation/menu-view-structure.png diff --git a/docs/img/artBoardOverview.png b/src/archive/docs/img/artBoardOverview.png similarity index 100% rename from docs/img/artBoardOverview.png rename to src/archive/docs/img/artBoardOverview.png diff --git a/docs/img/paletteStructure.png b/src/archive/docs/img/paletteStructure.png similarity index 100% rename from docs/img/paletteStructure.png rename to src/archive/docs/img/paletteStructure.png diff --git a/docs/img/paletteView.png b/src/archive/docs/img/paletteView.png similarity index 100% rename from docs/img/paletteView.png rename to src/archive/docs/img/paletteView.png diff --git a/docs/img/turtle.png b/src/archive/docs/img/turtle.png similarity index 100% rename from docs/img/turtle.png rename to src/archive/docs/img/turtle.png