Git Product home page Git Product logo

awaybuilder's People

Contributors

80prozent avatar greg209 avatar keyemkey avatar liaocheng avatar pirrest avatar qornflex avatar richardolsson avatar rob-bateman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

awaybuilder's Issues

re-addition of the 'panel hide' button for the tree panel

In the original logicly interface we inherited, the interface panel on the left could be slide away by clicking a button positioned down the right hand side of the panel that moved the panel off the left and allowed more room for the 3d view area. It would be good to re-inplement this in the Away Builder interface for the tree panle, also considering a similar button for the properties panel that will live in a similar way on the right side of the interface.

Creating a new texture in a material through the material dropdown on a submesh with more than one submesh in the mesh causes all submeshes to adopt that texture

Steps to Reproduce

  • Open awd/MonsterHead.awd
  • Click on the head mesh and select "new material" from the dropdown
  • Go into material and select "new texture" from the diffuse texture dropdown
  • Select any image that isn't already being used in the existing mateirals

Expected result

The SubMesh has the new diffuse texture applied to its material

Actual result

The new diffuse texture is applied to all submeshes

Texture preview icon on texture dropdown for materials and material dropdown on meshes

Adding a 32x32 preview icon of a texture in the dropdown menus for the properties panel (perhaps even the texture icons in the document tree?) so that there is some indication of the texture you are selecting besides the name. For materials dropdown on meshes, the same approach can be used only in this case, the material (not being a texture itself) should use the diffuse texture icon as its icon if it is a texture material, or a solid 32x32 block of colour if it is a colour material.

Investigate performance problems on mac

On mac the application takes more than 10% of CPU even if no file is loaded. And window dragging isn't smooth. This is not true for Quentin's prototype, so must be a set up problem..

Loading a different awd when one is already loaded causes an error

Steps to reproduce:

  1. click on "Open Document" and load the sponza/sponza.awd file
  2. with the file completely loaded, click on "Open Document" and load the sponza/sponza.awd file again

runtime error:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at away3d.materials.passes::CompiledPass/addPassesFromMethods()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/away3d-core-fp11/src/away3d/materials/passes/CompiledPass.as:349]
at away3d.materials.passes::SuperShaderPass/addPassesFromMethods()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/away3d-core-fp11/src/away3d/materials/passes/SuperShaderPass.as:196]
at away3d.materials.passes::CompiledPass/invalidateShaderProgram()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/away3d-core-fp11/src/away3d/materials/passes/CompiledPass.as:342]
at away3d.materials::MaterialBase/invalidatePasses()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/away3d-core-fp11/src/away3d/materials/MaterialBase.as:446]
at away3d.materials::MaterialBase/removeOwner()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/away3d-core-fp11/src/away3d/materials/MaterialBase.as:392]
at away3d.entities::Mesh/set material()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/away3d-core-fp11/src/away3d/entities/Mesh.as:165]
at away3d.entities::Mesh/dispose()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/away3d-core-fp11/src/away3d/entities/Mesh.as:214]
at away3d.library::AssetLibraryBundle/removeAllAssets()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/away3d-core-fp11/src/away3d/library/AssetLibraryBundle.as:399]
at away3d.library::AssetLibrary$/removeAllAssets()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/away3d-core-fp11/src/away3d/library/AssetLibrary.as:209]
at awaybuilder.controller.document::NewDocumentCommand/execute()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/controller/document/NewDocumentCommand.as:27]
at org.robotlegs.base::CommandMap/execute()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/CommandMap.as:182]
at org.robotlegs.base::CommandMap/routeEventToCommand()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/CommandMap.as:232]
at Function/()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/CommandMap.as:98]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at org.robotlegs.mvcs::Command/dispatch()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/mvcs/Command.as:57]
at awaybuilder.controller.document::ReplaceDocumentCommand/execute()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/controller/document/ReplaceDocumentCommand.as:24]
at org.robotlegs.base::CommandMap/execute()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/CommandMap.as:182]
at org.robotlegs.base::CommandMap/routeEventToCommand()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/CommandMap.as:232]
at Function/()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/CommandMap.as:98]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at org.robotlegs.mvcs::Actor/dispatch()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/mvcs/Actor.as:98]
at awaybuilder.desktop.model::FileSystemDocumentService/file_open_selectHandler()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-desktop/src/awaybuilder/desktop/model/FileSystemDocumentService.as:154]

Focus interaction for scene objects

The focus interaction moves the focus and distance of the camera so that it cetrally displays the selected object at a suitable distance for the size of the object.

This can work on any object container or group of (selected) objects, and on the root object container (ie the scene)

when a file is initially loaded, the focus interaction will be called on the scene so that the file contents are displayed centrally and at a suitable size

containers need to be selectable even if they contain sub-hierarchy

currently clicking on a container containing a mesh will select the mesh (albeit without the bounding box).

this needs to change so that clicking on a container containing a mesh (or anything else) will select the container and display the bounding box and gizmo for that container.

Gizmos interaction to be wired up

Currently, all gizmos do nothing when clicked by the mouse. They need to react as each gizmo should to click and drag movements, altering the transform properties of the selected 3d object

creating a new material from the submesh dropdown should create a duplicate of the default material (without the texture), not a duplicate of the existing material

Steps to reproduce

  • Open awd/MonsterHead.awd
  • Click on the head mesh and select "new material" from the dropdown

Expected result

A new material is created that is a copy of the Default material without the default texture (ie a color material)

Actual result

A new material is created that is a copy of the currently selected material in the dropdown

Adjusting any stepper on the properties panel for a light and then clicking back on the view causes a runtime error

this bug occurs for both Directional lights and points lights

Steps to reproduce

  • Open PolarBear.awd
  • Create a new material on the bear mesh, go to lights and create a new light picker
  • Add a Directional or Pointlight and go into its properties panel
    *Click once on any stepper in the panel, then click anywhere in the view

Error Stacktrace

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at awaybuilder.view.components.controls::DragableNumericStepper/childUpOutside()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/view/components/controls/DragableNumericStepper.as:233]

Keyboard events logic

We need a way to centralize keyboard events in the application.
What I propose: catch keyboard events in some mediator, and send them via robotlegs. Then any mediator can catch them and perform actions on view.

Integrate different file type loading (3DS, OBJ, MD2, MD5, Collada)

We need to add the option for importing file types other than AWD and displaying them in the interface. Perhaps this should belong inside an "import..." item in the file menu, then list the different file types we can succefully import. Clicking each one of the options would open a file browser window that can only select files with the correct extension for importing

double click on a container to go 'into' the hierarchy

referencing the fix for issue #32, we will also need a way to select containers and meshes contained within a heirarchy. This is already possible in the left-hand nav, but for it to work in the view the proposition is to have a double-click 'enter into' a container similar to the flash pro double click on a movieclip containing sub-clips

several things will be needed for this - a breadcrumb in the view to show where you are currently viewing, a disabling and greying out (maybe half-alpha?) of objects in the scene that are not part of the current active container view.

Deleting doesn't work on mesh with children

Steps to reproduce:

open onkba/onkba.awd

click on Bip01 in the library panel

click the delete button

Expected result

entire Bip01should disappear in the library and the view

Actual result

Bip01 stays exactly the same, or some (but not all) of the tree disappears. In the latter case, tree is unusable after this point

when creating and then deleting a light (point or directional), the representations on stage do not disappear

Steps to reproduce

  • Open PolarBear.awd
  • Create a new material on the bear
  • Create a new LightPicker on the material
  • Create a new PointLight and Directional Light on the lightpicker
  • Select the PointLight and click the "delete" button under the list box
  • Select the DirectionalLight and click the "delete" button under the list box

Expected results

Both lights are removed from the lightpicker and are no longer visible in the view

Actual results

Both lights are removed from the lightpicker but remain visible in the view

Small models move in 'steps' with position gizmo

When trying to move very small objects on stage (ie when zoomed in) with the position gizmo, the position exhibits a quantisation, moving in steps rather than smoothly. Same problem can be seen when scaling with the scale gizmo

tree representation has root nodes to group object types

Currently the tree root nodes are the root content data of the AWD file. In order to make navigating data types easier, i would propose we have root nodes that group the acutal root data nodes of the file. eg all root mesh and obejctcontainer3d nodes are grouped inside a root node in the tree called "scene". All material nodes are grouped inside a root node called "materials" etc. These groupings don't need to exist in the file data, they are purely for convenience when navigating the data inside the tree interface

Selection of objects in view should be mirrored by selection of objects in tree and vice versa

Where applicable, selection of objects in view should be mirrored by selection of objects in tree and vice versa.

Eg. a mesh item selected in the view should appear selected in the tree.

We can potentially add further helpful synchronicity between tree and view for other object types. Perhaps when you select a material in the tree, the meshes that use that material in the view get selected? or when you select a geometry, the meshes that use that geometry are selected? possibly a 4.1 beta feature

selecting a container that contains another mesh causes a runtime error

Steps to reproduce:

  1. open the MonsterHead.awd file
  2. Click on the "cont0" container in the library panel

runtime error:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at awaybuilder.view.mediators::CoreEditorMediator/eventDispatcher_itemsSelectHandler()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/view/mediators/CoreEditorMediator.as:725]
at org.robotlegs.base::EventMap/routeEventToListener()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/EventMap.as:181]
at Function/()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/EventMap.as:107]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at org.robotlegs.mvcs::Mediator/dispatch()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/mvcs/Mediator.as:89]
at awaybuilder.view.mediators::LibraryPanelMediator/view_treeChangeHandler()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/view/mediators/LibraryPanelMediator.as:140]
at org.robotlegs.base::EventMap/routeEventToListener()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/EventMap.as:181]
at Function/()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/EventMap.as:107]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/framework/src/mx/core/UIComponent.as:13160]
at awaybuilder.view.components::LibraryPanel/mouseUpHandler()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/view/components/LibraryPanel.mxml:144]

drag and drop functionality for importing files to an open library

As a shortcut to using the import menu, dragging and dropping a compatible file will ahve the same effect as importing from the file menu. The only difference will be in a popup that asks whether the use want to merge the file with the existing library, or create and open a new library. this is to avoid anyone accidentally dragging and dropping a file into an open project, and also allows a quick way of previewing individual awd files without just automatically merging them into one

import menu item in file can import 3d files or textures

For the import option in the file menu, it is possible to import a 3d model that will automatically merge with your existing scene, or an image file that will be added to your available textures.

With a 3d file, the options should include obj, 3ds, collada (dae), md2, md5 and AWD

With an image, the options should include jpg, png and atf

The last option will automatically create an ATFTexture object for use in the library. .png and .jpg files will automatically create BitmapTexture objects

Zoom distance is incorrect after panning and rotating

To recreate:

  1. Load a model
  2. Pan the object to the edge or off the screen
  3. Rotate the object back into the view
  4. Zoom in.

Expected results:
You should be able to zoom into the object as you would without having panned and rotated.

Actual result:
The zoom distance is limited so you cannot get as close to the object

add a "new" shortcut button next to any dropdown selector in properties for a shared document resource

Example: in Mesh properties, we have a dropdown menu for each submesh mateiral.

this has a shortcut button to edit the submesh, but it should also have an 'add new' button alongside so that it is easy to create a new material to be used by the mesh should that be required. Adding a material in this way should introduce a new material object to the document tree on the left, as well as automatically linking the mateiral to the submesh it has been added under.

For other properties such as geometry, texture, animator etc, this functionality should be replicated.

When changing a material type from singlepass to multipass, a runtime error is thrown

Steps to reproduce

  • Open PolarBear.awd
  • Select the mesh and create a new mateiral
  • go into the material panel and open the "General" subpanel
  • Select "multipass"
  • Click the back arrow at the top of the material panel

Error Stack

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at awaybuilder.model.vo.scene::AssetVO/equals()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/model/vo/scene/AssetVO.as:19]
at awaybuilder.view.components.editors.renderers::SubmeshItemRenderer/set data()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/view/components/editors/renderers/SubmeshItemRenderer.mxml:32]
at spark.components::SkinnableDataContainer/updateRenderer()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/spark/src/spark/components/SkinnableDataContainer.as:614]
at spark.components.supportClasses::ListBase/updateRenderer()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/spark/src/spark/components/supportClasses/ListBase.as:1114]
at spark.components::DataGroup/setUpItemRenderer()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/spark/src/spark/components/DataGroup.as:1165]
at spark.components::DataGroup/getVirtualElementAt()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/spark/src/spark/components/DataGroup.as:1557]
at spark.layouts::VerticalLayout/updateDisplayListVirtual()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/spark/src/spark/layouts/VerticalLayout.as:1840]
at spark.layouts::VerticalLayout/updateDisplayList()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/spark/src/spark/layouts/VerticalLayout.as:2138]
at spark.components.supportClasses::GroupBase/updateDisplayList()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/spark/src/spark/components/supportClasses/GroupBase.as:1302]
at spark.components::DataGroup/updateDisplayList()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/spark/src/spark/components/DataGroup.as:1494]
at mx.core::UIComponent/validateDisplayList()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/framework/src/mx/core/UIComponent.as:9007]
at mx.managers::LayoutManager/validateClient()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/framework/src/mx/managers/LayoutManager.as:1041]
at mx.core::UIComponent/validateNow()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/framework/src/mx/core/UIComponent.as:8085]
at awaybuilder.view.mediators::PropertiesPanelMediator/eventDispatcher_itemsSelectHandler()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/view/mediators/PropertiesPanelMediator.as:570]
at org.robotlegs.base::EventMap/routeEventToListener()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/EventMap.as:181]
at Function/()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/EventMap.as:107]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at org.robotlegs.mvcs::Mediator/dispatch()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/mvcs/Mediator.as:89]
at awaybuilder.view.mediators::PropertiesPanelMediator/view_showParentMeshHandler()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/view/mediators/PropertiesPanelMediator.as:261]
at org.robotlegs.base::EventMap/routeEventToListener()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/EventMap.as:181]
at Function/()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/EventMap.as:107]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[/Users/justinmclean/Documents/ApacheFlexSDK/frameworks/projects/framework/src/mx/core/UIComponent.as:13160]
at awaybuilder.view.components.editors::MaterialPropertiesEditor/editParentObjectButton_clickHandler()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/view/components/editors/MaterialPropertiesEditor.mxml:316]
at awaybuilder.view.components.editors::MaterialPropertiesEditor/__editParentObjectButton_click()[/Users/robbateman/Documents/Adobe Flash Builder 4.7/AwayBuilder/awaybuilder-core/src/awaybuilder/view/components/editors/MaterialPropertiesEditor.mxml:568]

horizontal wireframes disappear

when viewing the orientation grid or the bounding box of a mesh, any horizontal lines rendered by the wireframe disappear. This is especially noticeable when the app in initially started. Presumably a problem in the wireframe renderer?

Full featured .awd file needed

Hello, Richard,
To continue development we need another .awd file with all types of items in it, to test tree UI component, its parsing etc.
Right now some of the assets are embeded inside app itself to show bear file,
but we need to remove them, and to do that we need to have them inside .awd (or defined by external links in it)
Also we need an example of parsing that file, to see all possible options..

Could you please provide a file and parsing example? Thanks

Combing the material property panel for both color mateirals and texture materials

rather than use two different property panel setups for texture materials and color materials, we can have a single panel with a radiobutton at the top that selects material type (that can in future be extended to include things like single pass texture material, multipass texure material etc)

the current radio button would have an option for tetxure material and an option for colr material mode. When the mode is switched, the properties panel needs to update to either remove the panel elements that aren't associated with the texture type, or grey them out (whichever makes more sense) Currently these properties are:

color (only applicable for color materials)
texture (only applicable for texture materials)

Pan control mode to move the center focus of hovercontroller

The current motion is simply to turn the camera left and right, which doesn't sit well with switching back and forth between pan mode and rotate mode for the view

Desired functionality should be rotate of hovercontroller on click and drag for rotate mode (as is currently), and movement of target position of hovercontroller left/right/up/down for pan mode

Better organisation of packages inside the source folders

i was thinking it would be good to spend some time properly integrating the packages etc so that they are more like one codebase eg only have one events package for each project, one controllers package etc. If we want to create a separation between quentin and mike's code, we could potentially have a separate library project that would allow the same package structures while keeping codebases seaparated for easier maintenance - but i'll let you decide what would be the best solution

Delete, Copy and paste controls need hooking up to data model

Delete, copy and paste in the toolbar (and menu) should act like any other delete, copy and paste function. Once a selected item is copied, it is retained in a "clipboard" and pasted as a new item in the document every time the paste command is called. The delete toolbar item is fairly self explanatory, however, when a texture or object that can be shared across object properties is deleted, it will be necessary to nullify (or replace with the default) all those objects that are affected.

The default material is not something that should be viewable in the properties panel

Steps to reproduce

  • Open PolarBear.awd
  • Select the polar bear mesh

Expected result

the submesh of the polarbear has a material selection of "Default" that has a greyed out arrow for going into

Actual result

the submesh of the polarbear has a material selection of "Default" that has an active arrow for going into. when clicked, the properties panel of the default material can be viewed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.